diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 2bede5eed..921699168 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -18,6 +18,7 @@ module Instructeurs @dossiers_archived_count_per_procedure = dossiers.archived.group('groupe_instructeurs.procedure_id').count @dossiers_termines_count_per_procedure = dossiers.termine.visible_by_administration.group('groupe_instructeurs.procedure_id').reorder(nil).count @dossiers_expirant_count_per_procedure = dossiers.termine_or_en_construction_close_to_expiration.group('groupe_instructeurs.procedure_id').count + @dossiers_supprimes_recemment_count_per_procedure = dossiers.hidden_by_administration.group('groupe_instructeurs.procedure_id').reorder(nil).count groupe_ids = current_instructeur.groupe_instructeurs.pluck(:id) @followed_dossiers_count_per_procedure = current_instructeur @@ -35,7 +36,8 @@ module Instructeurs 'traités' => @dossiers_termines_count_per_procedure.sum { |_, v| v }, 'dossiers' => @dossiers_count_per_procedure.sum { |_, v| v }, 'expirant' => @dossiers_expirant_count_per_procedure.sum { |_, v| v }, - 'archivés' => @dossiers_archived_count_per_procedure.sum { |_, v| v } + 'archivés' => @dossiers_archived_count_per_procedure.sum { |_, v| v }, + 'supprimes_recemment' => @dossiers_supprimes_recemment_count_per_procedure.sum { |_, v| v } } @procedure_ids_en_cours_with_notifications = current_instructeur.procedure_ids_with_notifications(:en_cours) @@ -51,9 +53,9 @@ module Instructeurs @current_filters = current_filters @displayed_fields_options, @displayed_fields_selected = procedure_presentation.displayed_fields_for_select - @a_suivre_count, @suivis_count, @traites_count, @tous_count, @archives_count, @expirant_count = current_instructeur + @a_suivre_count, @suivis_count, @traites_count, @tous_count, @supprimes_recemment_count, @archives_count, @expirant_count = current_instructeur .dossiers_count_summary(groupe_instructeur_ids) - .fetch_values('a_suivre', 'suivis', 'traites', 'tous', 'archives', 'expirant') + .fetch_values('a_suivre', 'suivis', 'traites', 'tous', 'supprimes_recemment', 'archives', 'expirant') dossiers_visibles = Dossier .where(groupe_instructeur_id: groupe_instructeur_ids) @@ -72,6 +74,7 @@ module Instructeurs @termines_dossiers = dossiers_visibles.termine.visible_by_administration @all_state_dossiers = dossiers_visibles.all_state.visible_by_administration + @supprimes_recemment_dossiers = dossiers_visibles.termine.hidden_by_administration @archived_dossiers = dossiers_visibles.archived @expirant_dossiers = dossiers_visibles.termine_or_en_construction_close_to_expiration @@ -88,6 +91,9 @@ module Instructeurs when 'tous' dossiers_count = @tous_count @all_state_dossiers + when 'supprimes_recemment' + dossiers_count = @supprimes_recemment_count + @supprimes_recemment_dossiers when 'archives' dossiers_count = @archives_count @archived_dossiers @@ -282,6 +288,13 @@ module Instructeurs ) end + def restore + dossier = current_instructeur.dossiers.find(params[:dossier_id]) + dossier.restore(current_instructeur) + flash.notice = t('instructeurs.dossiers.restore') + redirect_to instructeur_procedure_path(procedure) + end + private def assign_to_params diff --git a/app/models/dossier.rb b/app/models/dossier.rb index b1dcc6b0a..c0f11c577 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -815,6 +815,10 @@ class Dossier < ApplicationRecord restore_dossier_and_destroy_deleted_dossier(author) end end + elsif author_is_administration(author) && hidden_by_administration? + transaction do + update(hidden_by_administration_at: nil) + end end end diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 1e29a5b6e..b569ee895 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -236,7 +236,8 @@ class Instructeur < ApplicationRecord COUNT(DISTINCT dossiers.id) FILTER (where not archived AND dossiers.state in ('en_construction', 'en_instruction') AND follows.instructeur_id = :instructeur_id) AS suivis, COUNT(DISTINCT dossiers.id) FILTER (where not archived AND dossiers.state in ('accepte', 'refuse', 'sans_suite')) AS traites, COUNT(DISTINCT dossiers.id) FILTER (where not archived AND NOT (dossiers.hidden_by_user_at IS NOT NULL AND state = 'en_construction')) AS tous, - COUNT(DISTINCT dossiers.id) FILTER (where archived) AS archives, + COUNT(DISTINCT dossiers.id) FILTER (where not archived AND (dossiers.hidden_by_administration_at IS NOT NULL AND dossiers.state in ('accepte', 'refuse', 'sans_suite') )) AS supprimes_recemment, + COUNT(DISTINCT dossiers.id) FILTER (where archived) AS archives, COUNT(DISTINCT dossiers.id) FILTER (where procedures.procedure_expires_when_termine_enabled AND ( @@ -256,7 +257,6 @@ class Instructeur < ApplicationRecord ON follows.dossier_id = dossiers.id AND follows.unfollowed_at IS NULL WHERE "dossiers"."hidden_at" IS NULL - AND "dossiers"."hidden_by_administration_at" IS NULL AND "dossiers"."state" != 'brouillon' AND "dossiers"."groupe_instructeur_id" in (:groupe_instructeur_ids) EOF diff --git a/app/views/instructeurs/dossiers/_header_actions.html.haml b/app/views/instructeurs/dossiers/_header_actions.html.haml index 47f7b4893..a680b9f8d 100644 --- a/app/views/instructeurs/dossiers/_header_actions.html.haml +++ b/app/views/instructeurs/dossiers/_header_actions.html.haml @@ -28,7 +28,8 @@ state: dossier.state, archived: dossier.archived, dossier_is_followed: current_instructeur&.follow?(dossier), - close_to_expiration: dossier.close_to_expiration? } + close_to_expiration: dossier.close_to_expiration?, + supprimes_recemment: dossier.hidden_by_administration? } .state-button diff --git a/app/views/instructeurs/procedures/_dossier_actions.html.haml b/app/views/instructeurs/procedures/_dossier_actions.html.haml index 87add5c29..ad122588b 100644 --- a/app/views/instructeurs/procedures/_dossier_actions.html.haml +++ b/app/views/instructeurs/procedures/_dossier_actions.html.haml @@ -21,12 +21,18 @@ %span.icon.archive .dropdown-description Archiver le dossier - - %li.danger - = link_to supprimer_dossier_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, data: { confirm: "Voulez vous vraiment supprimer le dossier #{dossier_id} ? Cette action est irréversible. \nNous vous suggérons de télécharger le dossier au format PDF au préalable." } do - %span.icon.delete - .dropdown-description - = t('views.instructeurs.dossiers.delete_dossier') + - if supprimes_recemment + %li.danger + = link_to restore_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, data: { confirm: "Voulez vous vraiment restaurer le dossier #{dossier_id}" } do + %span.icon.reply + .dropdown-description + = t('views.instructeurs.dossiers.restore') + - else + %li.danger + = link_to supprimer_dossier_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, data: { confirm: "Voulez vous vraiment supprimer le dossier #{dossier_id} ? Cette action est irréversible. \nNous vous suggérons de télécharger le dossier au format PDF au préalable." } do + %span.icon.delete + .dropdown-description + = t('views.instructeurs.dossiers.delete_dossier') - elsif Dossier::EN_CONSTRUCTION_OU_INSTRUCTION.include?(state) - if dossier_is_followed diff --git a/app/views/instructeurs/procedures/_list.html.haml b/app/views/instructeurs/procedures/_list.html.haml index 6f60a13af..073a1bea9 100644 --- a/app/views/instructeurs/procedures/_list.html.haml +++ b/app/views/instructeurs/procedures/_list.html.haml @@ -45,6 +45,15 @@ .stats-legend = t('pluralize.case', count: dossier_count) + %li + %object + = link_to(instructeur_procedure_path(p, statut: 'supprimes_recemment')) do + - dossier_count = dossiers_supprimes_recemment_count_per_procedure[p.id] || 0 + .stats-number + = number_with_html_delimiter(dossier_count) + .stats-legend + = t('pluralize.dossiers_supprimes_recemment', count: dossier_count) + - if p.procedure_expires_when_termine_enabled %li %object diff --git a/app/views/instructeurs/procedures/_tabs.html.haml b/app/views/instructeurs/procedures/_tabs.html.haml index e1337fdaa..9b35e6d70 100644 --- a/app/views/instructeurs/procedures/_tabs.html.haml +++ b/app/views/instructeurs/procedures/_tabs.html.haml @@ -22,6 +22,11 @@ active: statut == 'tous', badge: number_with_html_delimiter(tous_count)) + = tab_item(t('pluralize.dossiers_supprimes_recemment', count: supprimes_recemment_count), + instructeur_procedure_path(procedure, statut: 'supprimes_recemment'), + active: statut == 'supprimes_recemment', + badge: number_with_html_delimiter(supprimes_recemment_count)) + - if procedure.procedure_expires_when_termine_enabled = tab_item(t('pluralize.dossiers_close_to_expiration', count: expirant_count), instructeur_procedure_path(procedure, statut: 'expirant'), diff --git a/app/views/instructeurs/procedures/index.html.haml b/app/views/instructeurs/procedures/index.html.haml index 4356c463e..cfafa34b1 100644 --- a/app/views/instructeurs/procedures/index.html.haml +++ b/app/views/instructeurs/procedures/index.html.haml @@ -13,6 +13,7 @@ dossiers_archived_count_per_procedure: @dossiers_archived_count_per_procedure, dossiers_termines_count_per_procedure: @dossiers_termines_count_per_procedure, dossiers_expirant_count_per_procedure: @dossiers_expirant_count_per_procedure, + dossiers_supprimes_recemment_count_per_procedure: @dossiers_supprimes_recemment_count_per_procedure, followed_dossiers_count_per_procedure: @followed_dossiers_count_per_procedure, procedure_ids_en_cours_with_notifications: @procedure_ids_en_cours_with_notifications, procedure_ids_termines_with_notifications: @procedure_ids_termines_with_notifications } diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index 4738e7f6e..dfeb65b78 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -17,6 +17,7 @@ suivis_count: @suivis_count, traites_count: @traites_count, tous_count: @tous_count, + supprimes_recemment_count: @supprimes_recemment_count, archives_count: @archives_count, expirant_count: @expirant_count, has_en_cours_notifications: @has_en_cours_notifications, @@ -31,6 +32,8 @@ %p.explication-onglet Les dossiers dans cet onglet sont terminés : ils ont été acceptés, refusés ou classés sans suite. - if @statut == 'tous' %p.explication-onglet Tous les dossiers qui ont été déposés sur cette démarche, quel que soit le statut. + - if @statut == 'supprimes_recemment' + %p.explication-onglet Tous les dossiers terminés et supprimés par les instructeurs sur cette démarche - if @statut == 'archives' %p.explication-onglet Les dossiers de cet onglet sont archivés : vous ne pouvez plus y répondre, et les demandeurs ne peuvent plus les modifier. @@ -135,7 +138,8 @@ state: p.state, archived: p.archived, dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), - close_to_expiration: @statut == 'expirant' } + close_to_expiration: @statut == 'expirant', + supprimes_recemment: @statut == 'supprimes_recemment' } = pagination - else diff --git a/config/locales/en.yml b/config/locales/en.yml index ec96dd382..e6668fac8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -140,6 +140,7 @@ en: archived_dossier: "This file will be kept for an additional month" delete_dossier: "Delete file" deleted_by_user: "File deleted by user" + restore: "Restore the file" avis: introduction_file_explaination: "File attached to the request for advice" users: @@ -419,6 +420,7 @@ en: dossiers: deleted_by_instructeur: "The folder has been deleted" impossible_deletion: "Unable to delete : the folder is not processed" + restore: "The folder has been restored" france_connect: particulier: password_confirmation: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 49bed38a3..51c6641fd 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -137,6 +137,7 @@ fr: archived_dossier: "Le dossier sera conservé 1 mois supplémentaire" delete_dossier: "Supprimer le dossier" deleted_by_user: "Dossier supprimé par l'usager" + restore: "Restaurer le dossier" avis: introduction_file_explaination: "Fichier joint à la demande d’avis" users: @@ -372,13 +373,13 @@ fr: one: dossier invité other: dossiers invités dossiers_supprimes_recemment: - zero: dossier supprimé recemment - one: dossier supprimé recemment - other: dossiers supprimés recemment + zero: supprimé recemment + one: supprimé recemment + other: supprimés recemment dossiers_supprimes_definitivement: - zero: dossier supprimé définitivement - one: dossier supprimé définitivement - other: dossiers supprimés définitivement + zero: supprimé définitivement + one: supprimé définitivement + other: supprimés définitivement dossiers_transferes: zero: demande de transfert one: demande de transfert @@ -427,6 +428,7 @@ fr: dossiers: deleted_by_instructeur: "Le dossier a bien été supprimé de votre interface" impossible_deletion: "Supression impossible : le dossier n'est pas traité" + restore: "Le dossier a bien été restauré" administrateurs: procedures: show: diff --git a/config/routes.rb b/config/routes.rb index 9cd48ead5..cc303bc9e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -386,6 +386,7 @@ Rails.application.routes.draw do post 'avis' => 'dossiers#create_avis' get 'print' => 'dossiers#print' get 'telecharger_pjs' => 'dossiers#telecharger_pjs' + patch 'restore' end end diff --git a/db/migrate/20220127135056_add_supprimes_recemment_to_procedure_presentations.rb b/db/migrate/20220127135056_add_supprimes_recemment_to_procedure_presentations.rb new file mode 100644 index 000000000..4aa655ffe --- /dev/null +++ b/db/migrate/20220127135056_add_supprimes_recemment_to_procedure_presentations.rb @@ -0,0 +1,10 @@ +class AddSupprimesRecemmentToProcedurePresentations < ActiveRecord::Migration[6.1] + def up + ProcedurePresentation.update_all(%Q(filters = filters || '{"supprimes_recemment": []}')) + change_column_default :procedure_presentations, :filters, { "tous" => [], "suivis" => [], "traites" => [], "a-suivre" => [], "archives" => [], "supprimes_recemment" => [], "expirant": [] } + end + + def down + change_column_default :procedure_presentations, :filters, { "tous" => [], "suivis" => [], "traites" => [], "a-suivre" => [], "archives" => [], "expirant": [] } + end +end diff --git a/db/schema.rb b/db/schema.rb index aef752fc6..973f86d48 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_12_02_133139) do +ActiveRecord::Schema.define(version: 2022_01_27_135056) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -569,7 +569,7 @@ ActiveRecord::Schema.define(version: 2021_12_02_133139) do create_table "procedure_presentations", id: :serial, force: :cascade do |t| t.integer "assign_to_id" t.jsonb "sort", default: {"order"=>"desc", "table"=>"notifications", "column"=>"notifications"}, null: false - t.jsonb "filters", default: {"tous"=>[], "suivis"=>[], "traites"=>[], "a-suivre"=>[], "archives"=>[], "expirant"=>[]}, null: false + t.jsonb "filters", default: {"tous"=>[], "suivis"=>[], "traites"=>[], "a-suivre"=>[], "archives"=>[], "expirant"=>[], "supprimes_recemment"=>[]}, null: false t.datetime "created_at" t.datetime "updated_at" t.jsonb "displayed_fields", default: [{"label"=>"Demandeur", "table"=>"user", "column"=>"email"}], null: false diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 336afd076..8cde2714c 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -839,4 +839,25 @@ describe Instructeurs::DossiersController, type: :controller do end end end + + describe '#restore' do + let(:instructeur) { create(:instructeur) } + let!(:gi_p1_1) { GroupeInstructeur.create(label: '1', procedure: procedure) } + let!(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) } + let!(:dossier) { create(:dossier, state: 'accepte', procedure: procedure, groupe_instructeur: procedure.groupe_instructeurs.first, hidden_by_administration_at: 1.hour.ago) } + + before do + sign_in(instructeur.user) + instructeur.groupe_instructeurs << gi_p1_1 + patch :restore, + params: { + procedure_id: procedure.id, + dossier_id: dossier.id + } + end + + it "puts hidden_by_administration_at to nil" do + expect(dossier.reload.hidden_by_administration_at).to eq(nil) + end + end end diff --git a/spec/views/instructeur/procedures/_list.html.haml_spec.rb b/spec/views/instructeur/procedures/_list.html.haml_spec.rb index 7de854f9a..9c9de8f25 100644 --- a/spec/views/instructeur/procedures/_list.html.haml_spec.rb +++ b/spec/views/instructeur/procedures/_list.html.haml_spec.rb @@ -8,6 +8,7 @@ describe 'instructeurs/procedures/_list.html.haml', type: :view do dossiers_a_suivre_count_per_procedure: 2, dossiers_archived_count_per_procedure: 1, dossiers_termines_count_per_procedure: 1, + dossiers_supprimes_recemment_count_per_procedure: 0, dossiers_expirant_count_per_procedure: 0, followed_dossiers_count_per_procedure: 0, procedure_ids_en_cours_with_notifications: [], diff --git a/spec/views/instructeur/procedures/_tabs.html.haml_spec.rb b/spec/views/instructeur/procedures/_tabs.html.haml_spec.rb index e69a66a37..7fdb7bf54 100644 --- a/spec/views/instructeur/procedures/_tabs.html.haml_spec.rb +++ b/spec/views/instructeur/procedures/_tabs.html.haml_spec.rb @@ -11,6 +11,7 @@ describe 'instructeurs/procedures/_tabs.html.haml', type: :view do suivis_count: 0, traites_count: 0, tous_count: 0, + supprimes_recemment_count: 0, archives_count: 0, expirant_count: 0, has_en_cours_notifications: false,