diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 1605c4de1..ae148d258 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -23,6 +23,12 @@ module Instructeurs redirect_back(fallback_location: instructeur_dossier_path(@dossier.procedure, @dossier)) end + def extend_conservation_and_restore + dossier.extend_conservation_and_restore(1.month, current_instructeur) + flash[:notice] = t('views.instructeurs.dossiers.archived_dossier') + redirect_back(fallback_location: instructeur_dossier_path(@dossier.procedure, @dossier)) + end + def geo_data send_data dossier.to_feature_collection.to_json, type: 'application/json', @@ -376,6 +382,10 @@ module Instructeurs Dossier .where(id: current_instructeur.dossiers.visible_by_administration) .or(Dossier.where(id: current_user.dossiers.for_procedure_preview)) + elsif action_name == 'extend_conservation_and_restore' + Dossier + .where(id: current_instructeur.dossiers.visible_by_administration) + .or(Dossier.where(id: current_instructeur.dossiers.hidden_by_expired)) else current_instructeur.dossiers.visible_by_administration end diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 8a28e937c..cfba65dde 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -57,7 +57,7 @@ module Users @user_dossiers = current_user.dossiers.state_not_termine.merge(@dossiers_visibles) @dossiers_traites = current_user.dossiers.state_termine.merge(@dossiers_visibles) @dossiers_invites = current_user.dossiers_invites.merge(@dossiers_visibles) - @dossiers_supprimes_recemment = current_user.dossiers.hidden_by_user.merge(ordered_dossiers) + @dossiers_supprimes_recemment = (current_user.dossiers.hidden_by_user.or(current_user.dossiers.hidden_by_expired)).merge(ordered_dossiers) @dossier_transferes = @dossiers_visibles.where(dossier_transfer_id: DossierTransfer.for_email(current_user.email)) @dossiers_close_to_expiration = current_user.dossiers.close_to_expiration.merge(@dossiers_visibles) @dossiers_supprimes_definitivement = deleted_dossiers @@ -259,6 +259,12 @@ module Users redirect_back(fallback_location: dossier_path(@dossier)) end + def extend_conservation_and_restore + dossier.extend_conservation_and_restore(dossier.procedure.duree_conservation_dossiers_dans_ds.months, current_user) + flash[:notice] = t('views.users.dossiers.archived_dossier', duree_conservation_dossiers_dans_ds: dossier.procedure.duree_conservation_dossiers_dans_ds) + redirect_back(fallback_location: dossier_path(@dossier)) + end + def modifier @dossier = dossier_with_champs end @@ -530,6 +536,8 @@ module Users Dossier.visible_by_user.or(Dossier.for_procedure_preview).or(Dossier.for_editing_fork) elsif action_name == 'restore' Dossier.hidden_by_user + elsif action_name == 'extend_conservation_and_restore' + Dossier.visible_by_user.or(Dossier.hidden_by_expired) else Dossier.visible_by_user end diff --git a/app/mailers/dossier_mailer.rb b/app/mailers/dossier_mailer.rb index 1064af740..43bde1a5f 100644 --- a/app/mailers/dossier_mailer.rb +++ b/app/mailers/dossier_mailer.rb @@ -129,32 +129,32 @@ class DossierMailer < ApplicationMailer mail(to: to_email, subject: @subject) end - def notify_deletion_to_administration(deleted_dossier, to_email) + def notify_deletion_to_administration(hidden_dossier, to_email) configure_defaults_for_email(to_email) - @subject = default_i18n_subject(dossier_id: deleted_dossier.dossier_id) - @deleted_dossier = deleted_dossier + @subject = default_i18n_subject(dossier_id: hidden_dossier.id) + @hidden_dossier = hidden_dossier mail(to: to_email, subject: @subject) end - def notify_automatic_deletion_to_user(deleted_dossiers, to_email) + def notify_automatic_deletion_to_user(hidden_dossiers, to_email) configure_defaults_for_email(to_email) - I18n.with_locale(deleted_dossiers.first.user_locale) do - @state = deleted_dossiers.first.state - @subject = default_i18n_subject(count: deleted_dossiers.size) - @deleted_dossiers = deleted_dossiers + I18n.with_locale(hidden_dossiers.first.user_locale) do + @state = hidden_dossiers.first.state + @subject = default_i18n_subject(count: hidden_dossiers.size) + @hidden_dossiers = hidden_dossiers mail(to: to_email, subject: @subject) end end - def notify_automatic_deletion_to_administration(deleted_dossiers, to_email) + def notify_automatic_deletion_to_administration(hidden_dossiers, to_email) configure_defaults_for_email(to_email) - @subject = default_i18n_subject(count: deleted_dossiers.size) - @deleted_dossiers = deleted_dossiers + @subject = default_i18n_subject(count: hidden_dossiers.size) + @hidden_dossiers = hidden_dossiers mail(to: to_email, subject: @subject) end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 7ea0d4e99..63bbb2c59 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -221,10 +221,12 @@ class Dossier < ApplicationRecord scope :prefilled, -> { where(prefilled: true) } scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) } scope :hidden_by_administration, -> { where.not(hidden_by_administration_at: nil) } - scope :visible_by_user, -> { where(for_procedure_preview: false).where(hidden_by_user_at: nil, editing_fork_origin_id: nil) } + scope :hidden_by_expired, -> { where.not(hidden_by_expired_at: nil) } + scope :visible_by_user, -> { where(for_procedure_preview: false, hidden_by_user_at: nil, editing_fork_origin_id: nil, hidden_by_expired_at: nil) } scope :visible_by_administration, -> { state_not_brouillon .where(hidden_by_administration_at: nil) + .where(hidden_by_expired_at: nil) .merge(visible_by_user.or(state_not_en_construction)) } scope :visible_by_user_or_administration, -> { visible_by_user.or(visible_by_administration) } @@ -363,12 +365,12 @@ class Dossier < ApplicationRecord scope :without_brouillon_expiration_notice_sent, -> { where(brouillon_close_to_expiration_notice_sent_at: nil) } scope :without_en_construction_expiration_notice_sent, -> { where(en_construction_close_to_expiration_notice_sent_at: nil) } scope :without_termine_expiration_notice_sent, -> { where(termine_close_to_expiration_notice_sent_at: nil) } - scope :deleted_by_user_expired, -> { where('dossiers.hidden_by_user_at < ?', 1.week.ago) } scope :deleted_by_administration_expired, -> { where('dossiers.hidden_by_administration_at < ?', 1.week.ago) } - scope :en_brouillon_expired_to_delete, -> { state_brouillon.deleted_by_user_expired } - scope :en_construction_expired_to_delete, -> { state_en_construction.deleted_by_user_expired } - scope :termine_expired_to_delete, -> { state_termine.deleted_by_user_expired.deleted_by_administration_expired } + scope :deleted_by_automatic_expired, -> { where('dossiers.hidden_by_expired_at < ?', 1.week.ago) } + scope :en_brouillon_expired_to_delete, -> { state_brouillon.deleted_by_user_expired.or(state_brouillon.deleted_by_automatic_expired) } + scope :en_construction_expired_to_delete, -> { state_en_construction.deleted_by_user_expired.or(state_en_construction.deleted_by_automatic_expired) } + scope :termine_expired_to_delete, -> { state_termine.deleted_by_user_expired.deleted_by_administration_expired.or(state_termine.deleted_by_automatic_expired) } scope :brouillon_near_procedure_closing_date, -> do # select users who have submitted dossier for the given 'procedures.id' @@ -415,7 +417,7 @@ class Dossier < ApplicationRecord when 'tous' visible_by_administration.all_state when 'supprimes_recemment' - hidden_by_administration.state_termine + hidden_by_administration.state_termine.or(hidden_by_expired) when 'archives' visible_by_administration.archived when 'expirant' @@ -600,6 +602,10 @@ class Dossier < ApplicationRecord termine? || reason == :procedure_removed end + def can_be_deleted_by_automatic?(reason) + reason == :expired && !en_instruction? + end + def can_terminer_automatiquement_by_sva_svr? sva_svr_decision_triggered_at.nil? && !pending_correction? && (sva_svr_decision_on.today? || sva_svr_decision_on.past?) end @@ -645,7 +651,12 @@ class Dossier < ApplicationRecord def close_to_expiration? return false if en_instruction? - expiration_notification_date < Time.zone.now + expiration_notification_date < Time.zone.now && Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks.ago < expiration_notification_date + end + + def has_expired? + return false if en_instruction? + expiration_notification_date < Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks.ago end def after_notification_expiration_date @@ -677,6 +688,12 @@ class Dossier < ApplicationRecord termine_close_to_expiration_notice_sent_at: nil) end + def extend_conservation_and_restore(conservation_extension, author) + extend_conservation(conservation_extension) + update(hidden_by_expired_at: nil, hidden_by_reason: nil) + restore(author) + end + def show_procedure_state_warning? procedure.discarded? || (brouillon? && !procedure.dossier_can_transition_to_en_construction?) end @@ -766,6 +783,10 @@ class Dossier < ApplicationRecord !procedure.brouillon? && !brouillon? end + def hidden_by_expired? + hidden_by_expired_at.present? + end + def hidden_by_user? hidden_by_user_at.present? end @@ -820,37 +841,32 @@ class Dossier < ApplicationRecord end end - def expired_keep_track_and_destroy! - transaction do - DeletedDossier.create_from_dossier(self, :expired) - log_automatic_dossier_operation(:supprimer, self) - dossier_operation_logs.purge_discarded - destroy! - end - true - rescue - false - end - - def author_is_user(author) + def is_user?(author) author.is_a?(User) end - def author_is_administration(author) + def is_administration?(author) author.is_a?(Instructeur) || author.is_a?(Administrateur) || author.is_a?(SuperAdmin) end + def is_automatic?(author) + author == :automatic + end + def hide_and_keep_track!(author, reason) transaction do - if author_is_administration(author) && can_be_deleted_by_administration?(reason) + if is_administration?(author) && can_be_deleted_by_administration?(reason) update(hidden_by_administration_at: Time.zone.now, hidden_by_reason: reason) - elsif author_is_user(author) && can_be_deleted_by_user? + log_dossier_operation(author, :supprimer, self) + elsif is_user?(author) && can_be_deleted_by_user? update(hidden_by_user_at: Time.zone.now, dossier_transfer_id: nil, hidden_by_reason: reason) + log_dossier_operation(author, :supprimer, self) + elsif is_automatic?(author) && can_be_deleted_by_automatic?(reason) + update(hidden_by_expired_at: Time.zone.now, hidden_by_reason: reason) + log_automatic_dossier_operation(:supprimer, self) else raise "Unauthorized dossier hide attempt Dossier##{id} by #{author} for reason #{reason}" end - - log_dossier_operation(author, :supprimer, self) end if en_construction? && !hidden_by_administration? @@ -863,14 +879,18 @@ class Dossier < ApplicationRecord def restore(author) transaction do - if author_is_administration(author) + if is_administration?(author) update(hidden_by_administration_at: nil) - elsif author_is_user(author) + elsif is_user?(author) update(hidden_by_user_at: nil) end if !hidden_by_user? && !hidden_by_administration? update(hidden_by_reason: nil) + elsif hidden_by_user? + update(hidden_by_reason: :user_request) + elsif hidden_by_administration? + update(hidden_by_reason: :instructeur_request) end log_dossier_operation(author, :restaurer, self) diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 5933df7b7..bf600c0a6 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -227,18 +227,18 @@ class Instructeur < ApplicationRecord def dossiers_count_summary(groupe_instructeur_ids) query = <<~EOF SELECT - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND not archived AND dossiers.state in ('en_construction', 'en_instruction') AND follows.id IS NULL) AS a_suivre, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND not archived AND dossiers.state in ('en_construction', 'en_instruction') AND follows.instructeur_id = :instructeur_id) AS suivis, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND not archived AND dossiers.state in ('accepte', 'refuse', 'sans_suite')) AS traites, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND not archived) AS tous, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND archived) AS archives, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NOT NULL AND not archived AND dossiers.state in ('accepte', 'refuse', 'sans_suite')) AS supprimes_recemment, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND procedures.procedure_expires_when_termine_enabled + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_by_expired_at IS NULL AND not archived AND dossiers.state in ('en_construction', 'en_instruction') AND follows.id IS NULL) AS a_suivre, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_by_expired_at IS NULL AND not archived AND dossiers.state in ('en_construction', 'en_instruction') AND follows.instructeur_id = :instructeur_id) AS suivis, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_by_expired_at IS NULL AND not archived AND dossiers.state in ('accepte', 'refuse', 'sans_suite')) AS traites, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_by_expired_at IS NULL AND not archived) AS tous, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_by_expired_at IS NULL AND archived) AS archives, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NOT NULL AND not archived OR dossiers.hidden_by_expired_at IS NOT NULL) AS supprimes_recemment, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_by_expired_at IS NULL AND procedures.procedure_expires_when_termine_enabled AND ( dossiers.state in ('accepte', 'refuse', 'sans_suite') AND dossiers.processed_at + dossiers.conservation_extension + (procedures.duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now ) OR ( - dossiers.state in ('en_construction') + dossiers.state in ('en_construction') AND dossiers.hidden_by_expired_at IS NULL AND dossiers.en_construction_at + dossiers.conservation_extension + (duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now ) ) AS expirant diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 85521f70f..e7680f936 100644 --- a/app/services/dossier_projection_service.rb +++ b/app/services/dossier_projection_service.rb @@ -1,5 +1,5 @@ class DossierProjectionService - class DossierProjection < Struct.new(:dossier_id, :state, :archived, :hidden_by_user_at, :hidden_by_administration_at, :for_tiers, :prenom, :nom, :batch_operation_id, :sva_svr_decision_on, :corrections, :columns) do + class DossierProjection < Struct.new(:dossier_id, :state, :archived, :hidden_by_user_at, :hidden_by_administration_at, :hidden_by_reason, :for_tiers, :prenom, :nom, :batch_operation_id, :sva_svr_decision_on, :corrections, :columns) do def pending_correction? return false if corrections.blank? @@ -44,13 +44,14 @@ class DossierProjectionService batch_operation_field = { TABLE => 'self', COLUMN => 'batch_operation_id' } hidden_by_user_at_field = { TABLE => 'self', COLUMN => 'hidden_by_user_at' } hidden_by_administration_at_field = { TABLE => 'self', COLUMN => 'hidden_by_administration_at' } + hidden_by_reason_field = { TABLE => 'self', COLUMN => 'hidden_by_reason' } for_tiers_field = { TABLE => 'self', COLUMN => 'for_tiers' } individual_first_name = { TABLE => 'individual', COLUMN => 'prenom' } individual_last_name = { TABLE => 'individual', COLUMN => 'nom' } sva_svr_decision_on_field = { TABLE => 'self', COLUMN => 'sva_svr_decision_on' } dossier_corrections = { TABLE => 'dossier_corrections', COLUMN => 'resolved_at' } champ_value = champ_value_formatter(dossiers_ids, fields) - ([state_field, archived_field, sva_svr_decision_on_field, hidden_by_user_at_field, hidden_by_administration_at_field, for_tiers_field, individual_first_name, individual_last_name, batch_operation_field, dossier_corrections] + fields) # the view needs state and archived dossier attributes + ([state_field, archived_field, sva_svr_decision_on_field, hidden_by_user_at_field, hidden_by_administration_at_field, hidden_by_reason_field, for_tiers_field, individual_first_name, individual_last_name, batch_operation_field, dossier_corrections] + fields) .each { |f| f[:id_value_h] = {} } .group_by { |f| f[TABLE] } # one query per table .each do |table, fields| @@ -73,7 +74,7 @@ class DossierProjectionService .pluck(:id, *fields.map { |f| f[COLUMN].to_sym }) .each do |id, *columns| fields.zip(columns).each do |field, value| - if [state_field, archived_field, hidden_by_user_at_field, hidden_by_administration_at_field, for_tiers_field, batch_operation_field, sva_svr_decision_on_field].include?(field) + if [state_field, archived_field, hidden_by_user_at_field, hidden_by_administration_at_field, hidden_by_reason_field, for_tiers_field, batch_operation_field, sva_svr_decision_on_field].include?(field) field[:id_value_h][id] = value else field[:id_value_h][id] = value&.strftime('%d/%m/%Y') # other fields are datetime @@ -150,6 +151,7 @@ class DossierProjectionService archived_field[:id_value_h][dossier_id], hidden_by_user_at_field[:id_value_h][dossier_id], hidden_by_administration_at_field[:id_value_h][dossier_id], + hidden_by_reason_field[:id_value_h][dossier_id], for_tiers_field[:id_value_h][dossier_id], individual_first_name[:id_value_h][dossier_id], individual_last_name[:id_value_h][dossier_id], diff --git a/app/services/expired/dossiers_deletion_service.rb b/app/services/expired/dossiers_deletion_service.rb index 9d4bfddb7..a7f58b7f7 100644 --- a/app/services/expired/dossiers_deletion_service.rb +++ b/app/services/expired/dossiers_deletion_service.rb @@ -93,27 +93,26 @@ class Expired::DossiersDeletionService < Expired::MailRateLimiter administration_notifications = group_by_fonctionnaire_email(dossiers_to_remove) .map { |(email, dossiers)| [email, dossiers.map(&:id)] } - deleted_dossier_ids = [] + hidden_dossier_ids = [] dossiers_to_remove.find_each do |dossier| - if dossier.expired_keep_track_and_destroy! - deleted_dossier_ids << dossier.id - end + dossier.hide_and_keep_track!(:automatic, :expired) + hidden_dossier_ids << dossier.id end user_notifications.each do |(email, dossier_ids)| - dossier_ids = dossier_ids.intersection(deleted_dossier_ids) + dossier_ids = dossier_ids.intersection(hidden_dossier_ids) if dossier_ids.present? mail = DossierMailer.notify_automatic_deletion_to_user( - DeletedDossier.where(dossier_id: dossier_ids).to_a, + Dossier.where(id: dossier_ids).to_a, email ) send_with_delay(mail) end end administration_notifications.each do |(email, dossier_ids)| - dossier_ids = dossier_ids.intersection(deleted_dossier_ids) + dossier_ids = dossier_ids.intersection(hidden_dossier_ids) if dossier_ids.present? mail = DossierMailer.notify_automatic_deletion_to_administration( - DeletedDossier.where(dossier_id: dossier_ids).to_a, + Dossier.where(id: dossier_ids).to_a, email ) send_with_delay(mail) diff --git a/app/views/dossier_mailer/notify_automatic_deletion_to_administration.html.haml b/app/views/dossier_mailer/notify_automatic_deletion_to_administration.html.haml index 7d2cb3e91..f0a18eb0c 100644 --- a/app/views/dossier_mailer/notify_automatic_deletion_to_administration.html.haml +++ b/app/views/dossier_mailer/notify_automatic_deletion_to_administration.html.haml @@ -3,9 +3,14 @@ %p= t(:hello, scope: [:views, :shared, :greetings]) %p - = t('.header', count: @deleted_dossiers.size) + = t('.header', count: @hidden_dossiers.size) %ul - - @deleted_dossiers.each do |d| - %li n° #{d.dossier_id} (#{d.procedure.libelle}) + - @hidden_dossiers.each do |d| + %li n° #{d.id} (#{d.procedure.libelle}) + +%p + = t('.footer', count: @hidden_dossiers.size) + = link_to("mes dossiers", dossiers_url) + \. = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_automatic_deletion_to_user.html.haml b/app/views/dossier_mailer/notify_automatic_deletion_to_user.html.haml index 8d2079e12..0da270439 100644 --- a/app/views/dossier_mailer/notify_automatic_deletion_to_user.html.haml +++ b/app/views/dossier_mailer/notify_automatic_deletion_to_user.html.haml @@ -3,15 +3,14 @@ %p= t(:hello, scope: [:views, :shared, :greetings]) %p - = t('.header', count: @deleted_dossiers.size) + = t('.header', count: @hidden_dossiers.size) %ul - - @deleted_dossiers.each do |d| - %li N° #{d.dossier_id} (#{d.procedure.libelle}) + - @hidden_dossiers.each do |d| + %li N° #{d.id} (#{d.procedure.libelle}) %p - %strong= t('.account_active', count: @deleted_dossiers.size) - -- if @state == Dossier.states.fetch(:en_construction) - %p= t('.footer_en_construction', count: @deleted_dossiers.size, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks)) + = t('.footer', count: @hidden_dossiers.size) + = link_to("mes dossiers", dossiers_url) + \. = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_brouillon_near_deletion.html.haml b/app/views/dossier_mailer/notify_brouillon_near_deletion.html.haml index 2b358eab6..1c70807a3 100644 --- a/app/views/dossier_mailer/notify_brouillon_near_deletion.html.haml +++ b/app/views/dossier_mailer/notify_brouillon_near_deletion.html.haml @@ -8,6 +8,8 @@ - @dossiers.each do |d| %li= link_to("n° #{d.id} (#{d.procedure.libelle})", dossier_url(d)) -%p= sanitize(t('.footer', count: @dossiers.size)) +%p + = t('.account_active', count: @dossiers.size) + = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_deletion_to_administration.html.haml b/app/views/dossier_mailer/notify_deletion_to_administration.html.haml index 55da5cfe9..af217d4a3 100644 --- a/app/views/dossier_mailer/notify_deletion_to_administration.html.haml +++ b/app/views/dossier_mailer/notify_deletion_to_administration.html.haml @@ -3,6 +3,6 @@ %p= t(:hello, scope: [:views, :shared, :greetings]) %p - = t('.body', dossier_id: @deleted_dossier.dossier_id, procedure: @deleted_dossier.procedure.libelle) + = t('.body', dossier_id: @hidden_dossier.id, procedure: @hidden_dossier.procedure.libelle) = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml b/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml index 1bd80d74b..0ad8ed135 100644 --- a/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml +++ b/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml @@ -4,18 +4,17 @@ %p - if @state == Dossier.states.fetch(:en_construction) - = t('.header_en_construction', count: @dossiers.size) + = t('.header_en_construction', count: @dossiers.size, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks)) - else - = t('.header_termine', count: @dossiers.size) + = t('.header_termine', count: @dossiers.size, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks)) + %ul - @dossiers.each do |d| %li #{link_to("N° #{d.id} (#{d.procedure.libelle})", dossier_url(d))}. Retrouvez le dossier au format #{link_to("PDF", instructeur_dossier_url(d.procedure, d, format: :pdf))} -%p - - if @state == Dossier.states.fetch(:en_construction) - = sanitize(t('.footer_en_construction', count: @dossiers.size, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks))) - - else - = sanitize(t('.footer_termine', count: @dossiers.size, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks))) +- if @state == Dossier.states.fetch(:en_construction) + %p + = sanitize(t('.footer_en_construction')) = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml b/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml index be5eeaa32..07fadd71d 100644 --- a/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml +++ b/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml @@ -12,13 +12,15 @@ %li #{link_to("N° #{d.id} (#{d.procedure.libelle})", dossier_url(d))} -%p - %strong= t('.account_active', count: @dossiers.size) - %p - if @state == Dossier.states.fetch(:en_construction) = sanitize(t('.footer_en_construction', count: @dossiers.size, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks))) - else = sanitize(t('.footer_termine', count: @dossiers.size, dossiers_url: dossiers_url, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks))) + = link_to("mes dossiers", dossiers_url) + \. +%p + = t('.account_active', count: @dossiers.size) + = render partial: "layouts/mailers/signature" diff --git a/app/views/instructeurs/dossiers/_expiration_banner.html.haml b/app/views/instructeurs/dossiers/_expiration_banner.html.haml index 1e5c918cf..5aa622148 100644 --- a/app/views/instructeurs/dossiers/_expiration_banner.html.haml +++ b/app/views/instructeurs/dossiers/_expiration_banner.html.haml @@ -6,8 +6,9 @@ - if dossier.conservation_extension.positive? = t('instructeurs.dossiers.header.banner.expiration_date_extended') - - if dossier.close_to_expiration? - = render Dsfr::CalloutComponent.new(title: t('instructeurs.dossiers.header.banner.title'), theme: :warning) do |c| + - if dossier.close_to_expiration? || dossier.has_expired? + - title = dossier.has_expired? ? 'title_expired' : 'title' + = render Dsfr::CalloutComponent.new(title: t("instructeurs.dossiers.header.banner.#{title}"), theme: :warning) do |c| - c.with_body do - if dossier.brouillon? = t('instructeurs.dossiers.header.banner.states.brouillon') diff --git a/app/views/instructeurs/dossiers/_header_actions.html.haml b/app/views/instructeurs/dossiers/_header_actions.html.haml index f13702df7..69938b91d 100644 --- a/app/views/instructeurs/dossiers/_header_actions.html.haml +++ b/app/views/instructeurs/dossiers/_header_actions.html.haml @@ -8,6 +8,7 @@ dossier_is_followed: current_instructeur&.follow?(dossier), close_to_expiration: dossier.close_to_expiration?, hidden_by_administration: dossier.hidden_by_administration?, + hidden_by_expired: dossier.hidden_by_expired?, has_pending_correction: dossier.pending_correction?, has_blocking_pending_correction: dossier.procedure.feature_enabled?(:blocking_pending_correction) && dossier.pending_correction?, turbo: true, diff --git a/app/views/instructeurs/procedures/_dossier_actions.html.haml b/app/views/instructeurs/procedures/_dossier_actions.html.haml index fb0b1435d..e55c99d00 100644 --- a/app/views/instructeurs/procedures/_dossier_actions.html.haml +++ b/app/views/instructeurs/procedures/_dossier_actions.html.haml @@ -1,7 +1,13 @@ -- if hidden_by_administration +- if hidden_by_administration && hidden_by_expired + %li + = button_to repousser_expiration_and_restore_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: "fr-btn fr-icon-refresh-line" do + = t('views.instructeurs.dossiers.restore_and_extend') + +- elsif hidden_by_administration %li = button_to restore_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: "fr-btn fr-icon-refresh-line" do = t('views.instructeurs.dossiers.restore') + - elsif close_to_expiration || Dossier::TERMINE.include?(state) %li - if close_to_expiration diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index a5bd8de97..d73df00cd 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -144,11 +144,12 @@ - if p.hidden_by_administration_at.present? %span.cell-link = column - = "- #{t('views.instructeurs.dossiers.deleted_by_user')}" if p.hidden_by_user_at.present? + - if p.hidden_by_user_at.present? + = "- #{t("views.instructeurs.dossiers.deleted_reason.#{p.hidden_by_reason}")}" - else %a.cell-link{ href: path } = column - = "- #{t('views.instructeurs.dossiers.deleted_by_user')}" if p.hidden_by_user_at.present? + = "- #{t('views.instructeurs.dossiers.deleted_reason', reason: p.hidden_by_reason)}" if p.hidden_by_user_at.present? %td.status-col - status = [status_badge(p.state)] @@ -172,6 +173,7 @@ dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), close_to_expiration: @statut == 'expirant', hidden_by_administration: @statut == 'supprimes_recemment', + hidden_by_expired: p.hidden_by_reason == 'expired', sva_svr: @procedure.sva_svr_enabled?, has_blocking_pending_correction: @procedure.feature_enabled?(:blocking_pending_correction) && p.pending_correction?, turbo: false, diff --git a/app/views/recherche/index.html.haml b/app/views/recherche/index.html.haml index 7fb4bce78..bb2964eb5 100644 --- a/app/views/recherche/index.html.haml +++ b/app/views/recherche/index.html.haml @@ -102,6 +102,7 @@ dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), close_to_expiration: nil, hidden_by_administration: nil, + hidden_by_expired: nil, sva_svr: p.sva_svr_decision_on.present?, has_blocking_pending_correction: p.pending_correction? && Flipper.enabled?(:blocking_pending_correction, ProcedureFlipperActor.new(procedure_id)), turbo: false, diff --git a/app/views/users/dossiers/_deleted_dossiers_list.html.haml b/app/views/users/dossiers/_deleted_dossiers_list.html.haml index 4166ebb99..55846eba4 100644 --- a/app/views/users/dossiers/_deleted_dossiers_list.html.haml +++ b/app/views/users/dossiers/_deleted_dossiers_list.html.haml @@ -19,8 +19,7 @@ = t('views.users.dossiers.dossiers_list.n_dossier') = dossier.dossier_id - %span.fr-badge.fr-badge--sm.fr-badge--warning - = t('views.users.dossiers.dossiers_list.deleted_badge') + = status_badge(dossier.state, 'fr-mb-1w') = paginate deleted_dossiers, views_prefix: 'shared' diff --git a/app/views/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index 465003f57..7a7ff4c84 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -16,9 +16,12 @@ %p.fr-icon--sm.fr-icon-user-line = demandeur_dossier(dossier) - - if dossier.hidden_by_user? + - if dossier.hidden_by_expired? %p.fr-icon--sm.fr-icon-delete-line - = t('views.users.dossiers.dossiers_list.deleted', date: l(dossier.hidden_by_user_at.to_date)) + = t('views.users.dossiers.dossiers_list.deleted_by_automatic', date: l(dossier.hidden_by_expired_at.to_date)) + - elsif dossier.hidden_by_user? + %p.fr-icon--sm.fr-icon-delete-line + = t('views.users.dossiers.dossiers_list.deleted_by_user', date: l(dossier.hidden_by_user_at.to_date)) - else %p.fr-icon--sm.fr-icon-edit-box-line - if dossier.depose_at.present? @@ -40,11 +43,7 @@ = t('views.users.dossiers.dossiers_list.n_dossier') = number_with_html_delimiter(dossier.id) - - if @statut == "dossiers-supprimes-recemment" - %span.fr-badge.fr-badge--sm.fr-badge--warning - = t('views.users.dossiers.dossiers_list.deleted_badge') - - else - = status_badge_user(dossier, 'fr-mb-1w') + = status_badge_user(dossier, 'fr-mb-1w') - if dossier.pending_correction? %br @@ -103,8 +102,18 @@ - if @statut == "dossiers-supprimes-recemment" .flex.justify-end - = link_to restore_dossier_path(dossier.id), method: :patch, class: "fr-btn fr-btn--sm" do - Restaurer + - if dossier.hidden_by_reason != 'expired' + = link_to restore_dossier_path(dossier.id), method: :patch, class: "fr-btn fr-btn--sm" do + Restaurer + + - else + - if dossier.expiration_can_be_extended? + = button_to users_dossier_repousser_expiration_and_restore_path(dossier), class: 'fr-btn fr-btn--sm' do + Restaurer et étendre la conservation + + + - else + = render(partial: 'users/dossiers/show/download_dossier', locals: { dossier: dossier }) = paginate dossiers, views_prefix: 'shared' diff --git a/app/views/users/dossiers/_expiration_banner.html.haml b/app/views/users/dossiers/_expiration_banner.html.haml index 509d1eb81..908dffa6e 100644 --- a/app/views/users/dossiers/_expiration_banner.html.haml +++ b/app/views/users/dossiers/_expiration_banner.html.haml @@ -3,8 +3,9 @@ %p.expires_at %small= t("shared.dossiers.header.expires_at.#{dossier.state}", date: safe_expiration_date(dossier), duree_conservation_totale: dossier.duree_totale_conservation_in_months) - - if dossier.close_to_expiration? - = render Dsfr::CalloutComponent.new(title: t('users.dossiers.header.banner.title'), theme: :warning) do |c| + - if dossier.close_to_expiration? || dossier.has_expired? + - title = dossier.has_expired? ? 'title_expired' : 'title' + = render Dsfr::CalloutComponent.new(title: t("users.dossiers.header.banner.#{title}"), theme: :warning) do |c| - c.with_body do - if dossier.brouillon? = t('users.dossiers.header.banner.states.brouillon') diff --git a/config/locales/en.yml b/config/locales/en.yml index fe150433f..d03b7d70c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -406,7 +406,6 @@ en: expirant: Records will not expire prior to the data retention period. archived_dossier: "This file will be kept for an additional month" delete_dossier: "Delete file" - deleted_by_user: "File deleted by user" acts_on_behalf: "acts for" deleted_by_administration: "File deleted by administration" restore: "Restore" @@ -523,7 +522,6 @@ en: updated_at: updated at %{date} shared_with: File shared by %{owner} with deleted: Deleted at %{date} - deleted_badge: Deleted procedure_closed: brouillon: internal_procedure_html: This procedure is closed, you cannot submit this file. We invite you to submit a new one on the %{link} which replaces it diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 7a3a5d135..43d3b972d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -405,10 +405,13 @@ fr: expirant: Les dossiers n’expireront pas avant la période de conservation des données. archived_dossier: "Le dossier sera conservé 1 mois supplémentaire" delete_dossier: "Supprimer le dossier" - deleted_by_user: "Dossier supprimé par l’usager" + deleted_reason: + user_request: supprimé par l'usager + expired: a expiré acts_on_behalf: "agit pour" deleted_by_administration: "Dossier supprimé par l’administration" restore: "Restaurer" + restore_and_extend: "Restaurer et étendre la conservation" filters: title: Sélectionner un filtre select_all: Tout selectionner @@ -536,7 +539,8 @@ fr: updated_at: modifié le %{date} shared_with: Dossier partagé par %{owner} avec deleted: Supprimé le %{date} - deleted_badge: Supprimé + deleted_by_user: Supprimé le %{date} par l'usager + deleted_by_automatic: Supprimé le %{date} automatiquement du à la date d'expiration dossier_action: edit_dossier: "Modifier le dossier" start_other_dossier: "Commencer un nouveau dossier" diff --git a/config/locales/views/dossier_mailer/notify_automatic_deletion_to_administration/fr.yml b/config/locales/views/dossier_mailer/notify_automatic_deletion_to_administration/fr.yml index df144cd8c..41115442c 100644 --- a/config/locales/views/dossier_mailer/notify_automatic_deletion_to_administration/fr.yml +++ b/config/locales/views/dossier_mailer/notify_automatic_deletion_to_administration/fr.yml @@ -2,8 +2,11 @@ fr: dossier_mailer: notify_automatic_deletion_to_administration: subject: - one: "Un dossier a été supprimé automatiquement" - other: "Des dossiers ont été supprimés automatiquement" + one: "Un dossier a été supprimé" + other: "Des dossiers ont été supprimés" header: - one: "Le délai maximal de conservation du dossier suivant a été atteint, celui-ci a donc été supprimé :" - other: "Le délai maximal de conservation des dossiers suivants a été atteint, ceux-ci ont donc été supprimés :" + one: "Le délai maximal de conservation du dossier a été atteint, celui-ci a donc été supprimé :" + other: "Le délai maximal de conservation des dossiers a été atteint, ceux-ci ont donc été supprimés :" + footer: + one: Vous pouvez retrouver ce dossier pendant encore une semaine depuis l’onglet « Supprimé » sur la page + other: Vous pouvez retrouver ces dossiers pendant encore une semaine depuis l’onglet « Supprimés » sur la page diff --git a/config/locales/views/dossier_mailer/notify_automatic_deletion_to_user/fr.yml b/config/locales/views/dossier_mailer/notify_automatic_deletion_to_user/fr.yml index 33c9e58de..00b599579 100644 --- a/config/locales/views/dossier_mailer/notify_automatic_deletion_to_user/fr.yml +++ b/config/locales/views/dossier_mailer/notify_automatic_deletion_to_user/fr.yml @@ -2,14 +2,11 @@ fr: dossier_mailer: notify_automatic_deletion_to_user: subject: - one: "Un dossier a été supprimé automatiquement de votre compte" - other: "Des dossiers ont été supprimés automatiquement de votre compte" + one: "Un dossier a été supprimé de votre compte" + other: "Des dossiers ont été supprimés de votre compte" header: - one: "Le délai maximum pour la conservation du dossier suivant a été atteint.\nLe dossier suivant a été automatiquement supprimé :" - other: "Le délai maximum pour la conservation des dossiers suivants a été atteint.\nLes dossiers suivants ont été automatiquement supprimés :" - account_active: - one: Votre compte reste activé sur Démarches Simplifiées, seul le dossier est supprimé. - other: Votre compte reste activé sur Démarches Simplifiées, seuls les dossiers ont été supprimés. - footer_en_construction: - one: "Le dossier ne sera pas traité, nous nous excusons de la gêne occasionnée." - other: "Les dossiers ne seront pas traités, nous nous excusons de la gêne occasionnée." + one: "Le délai maximum pour la conservation du dossier a été atteint.\nLe dossier suivant a été supprimé :" + other: "Le délai maximum pour la conservation des dossiers a été atteint.\nLes dossiers suivants ont été supprimés :" + footer: + one: Vous pouvez retrouver ce dossier pendant encore une semaine depuis l’onglet « Supprimé » sur la page + other: Vous pouvez retrouver ces dossiers pendant encore une semaine depuis l’onglet « Supprimés » sur la page diff --git a/config/locales/views/dossier_mailer/notify_brouillon_deletion/fr.yml b/config/locales/views/dossier_mailer/notify_brouillon_deletion/fr.yml index a06ba5788..e09b7b7bd 100644 --- a/config/locales/views/dossier_mailer/notify_brouillon_deletion/fr.yml +++ b/config/locales/views/dossier_mailer/notify_brouillon_deletion/fr.yml @@ -2,8 +2,8 @@ fr: dossier_mailer: notify_brouillon_deletion: subject: - one: "Un dossier en brouillon a été supprimé automatiquement" - other: "Des dossiers en brouillon ont été supprimés automatiquement" + one: "Un dossier en brouillon a été supprimé" + other: "Des dossiers en brouillon ont été supprimés" header: - one: "Le délai maximum de conservation du dossier en brouillon suivant a été atteint, celui-ci a donc été supprimé :" - other: "Le délai maximum de conservation des dossiers en brouillon suivants a été atteint, ceux-ci ont donc été supprimés :" + one: "Le délai maximum de conservation du dossier en brouillon a été atteint, celui-ci a donc été supprimé :" + other: "Le délai maximum de conservation des dossiers en brouillon a été atteint, ceux-ci ont donc été supprimés :" diff --git a/config/locales/views/dossier_mailer/notify_brouillon_near_deletion/fr.yml b/config/locales/views/dossier_mailer/notify_brouillon_near_deletion/fr.yml index 63859a1b9..0d368850a 100644 --- a/config/locales/views/dossier_mailer/notify_brouillon_near_deletion/fr.yml +++ b/config/locales/views/dossier_mailer/notify_brouillon_near_deletion/fr.yml @@ -5,8 +5,8 @@ fr: one: Un dossier en brouillon va bientôt être supprimé other: Des dossiers en brouillon vont bientôt être supprimés header: - one: "Afin de limiter la conservation de vos données personnelles, le dossier en brouillon suivant sera bientôt automatiquement supprimé :" - other: "Afin de limiter la conservation de vos données personnelles, les dossiers en brouillon suivants seront bientôt automatiquement supprimés :" - footer: - one: "Si vous souhaitez toujours déposer ce dossier, vous pouvez retrouver votre brouillon pendant encore un mois. Si vous souhaitez conserver votre dossier plus longtemps, vous pouvez prolonger sa durée de conservation dans l’interface. Et sinon, vous n’avez rien à faire." - other: "Si vous souhaitez toujours déposer ces dossiers, vous pouvez retrouver vos brouillons pendant encore un mois. Si vous souhaitez conserver vos dossiers plus longtemps, vous pouvez prolonger leur durée de conservation au cas par cas dans l’interface. Et sinon, vous n’avez rien à faire." + one: "Afin de limiter la conservation de vos données personnelles, ce dossier en brouillon sera bientôt supprimé :" + other: "Afin de limiter la conservation de vos données personnelles, ces dossiers en brouillon seront bientôt supprimés :" + account_active: + one: Votre compte reste activé sur Démarches Simplifiées, seul le dossier sera supprimé. + other: Votre compte reste activé sur Démarches Simplifiées, seuls les dossiers seront supprimés. diff --git a/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml b/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml index 42d48bf06..f1ded51a8 100644 --- a/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml +++ b/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml @@ -2,20 +2,15 @@ fr: dossier_mailer: notify_near_deletion_to_administration: subject_en_construction: - one: Un dossier en construction va bientôt être supprimé - other: Des dossiers en construction vont bientôt être supprimés + one: Un dossier en attente d'instruction va bientôt être supprimé + other: Des dossiers en attente d'instruction vont bientôt être supprimés subject_termine: - one: Un dossier dont le traitement est terminé va bientôt être supprimé - other: Des dossiers dont le traitement est terminé vont bientôt être supprimés + one: Un dossier traité va bientôt être supprimé + other: Des dossiers traités vont bientôt être supprimés header_en_construction: - one: "Le dossier en construction suivant sera bientôt automatiquement supprimé :" - other: "Les dossiers en construction suivants seront bientôt automatiquement supprimés :" + one: "il vous reste %{remaining_weeks_before_expiration} pour démarrer l'instruction de ce dossier avant qu'il ne soit supprimé :" + other: "il vous reste %{remaining_weeks_before_expiration} pour démarrer l'instruction de ces dossiers avant qu'ils ne soient supprimés :" header_termine: - one: "Le dossier suivant dont le traitement est terminé sera bientôt automatiquement supprimé :" - other: "Les dossiers suivants dont le traitement est terminé seront bientôt automatiquement supprimés :" - footer_en_construction: - one: "Vous avez %{remaining_weeks_before_expiration} pour commencer l’instruction du dossier." - other: "Vous avez %{remaining_weeks_before_expiration} pour commencer l’instruction des dossiers." - footer_termine: - one: "Vous avez %{remaining_weeks_before_expiration} pour archiver le dossier." - other: "Vous avez %{remaining_weeks_before_expiration} pour archiver les dossiers." + one: "il vous reste %{remaining_weeks_before_expiration} pour archiver ce dossier traité avant qu'il ne soit supprimé :" + other: "il vous reste %{remaining_weeks_before_expiration} pour archiver ces dossier traités avant qu'ils ne soient supprimés :" + footer_en_construction: Vous pouvez tenir informé l'usager, en utilisant la messagerie depuis la page du dossier. diff --git a/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml b/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml index 2f61490d1..f6a52e6f5 100644 --- a/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml +++ b/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml @@ -2,23 +2,23 @@ fr: dossier_mailer: notify_near_deletion_to_user: subject_en_construction: - one: Un dossier en construction va bientôt être supprimé - other: Des dossiers en construction vont bientôt être supprimés + one: Un dossier en attente d'instruction va bientôt être supprimé + other: Des dossiers en attente d'instruction vont bientôt être supprimés subject_termine: - one: Un dossier dont le traitement est terminé va bientôt être supprimé - other: Des dossiers dont le traitement est terminé vont bientôt être supprimés + one: Un dossier traité va bientôt être supprimé + other: Des dossiers traités vont bientôt être supprimés header_en_construction: - one: "Afin de respecter la durée de conservation de vos données personnelles, le dossier en construction suivant sera supprimé automatiquement dans deux semaines :" - other: "Afin de respecter la durée de conservation de vos données personnelles, les dossiers en construction suivants seront supprimés automatiquement dans deux semaines :" + one: "Afin de respecter la durée de conservation de vos données personnelles, le dossier en attente d'instruction suivant sera supprimé automatiquement dans deux semaines :" + other: "Afin de respecter la durée de conservation de vos données personnelles, les dossiers en attente d'instruction suivants seront supprimés automatiquement dans deux semaines :" header_termine: - one: "Afin de respecter la durée de conservation de vos données personnelles, le dossier suivant dont le traitement est terminé sera supprimé automatiquement dans deux semaines :" - other: "Afin de respecter la durée de conservation de vos données personnelles, les dossiers suivants dont le traitement est terminé seront supprimés automatiquement dans deux semaines :" + one: "Afin de respecter la durée de conservation de vos données personnelles, ce dossier traité sera supprimé dans deux semaines :" + other: "Afin de respecter la durée de conservation de vos données personnelles, ces dossiers traités seront supprimés dans deux semaines :" account_active: one: Votre compte reste activé sur Démarches Simplifiées, seul le dossier sera supprimé. other: Votre compte reste activé sur Démarches Simplifiées, seuls les dossiers seront supprimés. footer_termine: - one: "Vous pouvez télécharger votre dossier au format PDF depuis l’onglet « Expirant » sur la page Mes dossiers." - other: "Vous pouvez télécharger vos dossiers au format PDF depuis l’onglet « Expirant » sur la page Mes dossiers." + one: Vous pouvez télécharger votre dossier au format PDF depuis l’onglet « Expirant » sur la page + other: "Vous pouvez télécharger vos dossiers au format PDF depuis l’onglet « Expirant » sur la page " footer_en_construction: - one: "Si vous souhaitez conserver votre dossier plus longtemps, vous pouvez prolonger sa durée de conservation dans l’interface." - other: "Si vous souhaitez conserver vos dossiers plus longtemps, vous pouvez prolonger leur durée de conservation au cas par cas dans l’interface." + one: Depuis la page de votre dossier vous avez la possibilité de :
- prolonger la durée de conservation
- contacter l'administration qui gère votre dossier via la messagerie + other: Depuis la page de vos dossiers vous avez la possibilité de :
- prolonger la durée de conservation
- contacter l'administration qui gère votre dossier via la messagerie diff --git a/config/locales/views/instructeurs/header/fr.yml b/config/locales/views/instructeurs/header/fr.yml index 9b81dfc5f..aad1fe4aa 100644 --- a/config/locales/views/instructeurs/header/fr.yml +++ b/config/locales/views/instructeurs/header/fr.yml @@ -5,10 +5,11 @@ fr: banner: expiration_date_extended: " – la date de conservation a déjà été étendue" title: Ce dossier va expirer + title_expired: Ce dossier a expiré states: brouillon: "" # not applicable, instructeur does not see brouillons en_construction: Ce dossier est en attente de prise en charge. Vous pouvez toutefois étendre cette durée d’un mois en cliquant sur le bouton suivant. - termine: Le traitement de ce dossier est terminé, mais il va bientôt expirer. Cela signifie qu’il va bientôt être supprimé. Si vous souhaitez en conserver une trace, vous pouvez le télécharger au format PDF. + termine: Le traitement de ce dossier est terminé, mais il va bientôt être supprimé. Si vous souhaitez en conserver une trace, vous pouvez le télécharger au format PDF. button_delay_expiration: "Conserver un mois de plus" notification_management: gestion des notifications administrators_list: voir les administrateurs diff --git a/config/locales/views/users/header/fr.yml b/config/locales/views/users/header/fr.yml index 07de1e7a8..cb3e4691d 100644 --- a/config/locales/views/users/header/fr.yml +++ b/config/locales/views/users/header/fr.yml @@ -12,10 +12,11 @@ fr: new_procedure_content: "Une nouvelle démarche est disponible, consultez-la ici :" contact_service_html: Pour plus d’informations, veuillez vous rapprocher du service %{service_name}, disponible au %{service_phone_number} ou par email à %{service_email} title: Votre dossier va expirer + title_expired: Votre dossier a expiré states: - brouillon: Votre dossier est en brouillon, mais va bientôt expirer. Cela signifie qu’il va bientôt être supprimé sans avoir été déposé. Si vous souhaitez le conserver afin de poursuivre la démarche, vous pouvez étendre la durée de conversation en cliquant sur le bouton ci-dessous. + brouillon: Votre dossier est en brouillon, mais va bientôt être supprimé sans avoir été déposé. Si vous souhaitez le conserver afin de poursuivre la démarche, vous pouvez étendre la durée de conversation en cliquant sur le bouton ci-dessous. en_construction: Votre dossier est en attente de prise en charge par l’administration. Le délai de prise en charge maximal est de %{nominal_duration_months} mois. Vous pouvez toutefois étendre cette durée en cliquant sur le bouton ci-dessous. - termine: Le traitement de votre dossier est terminé, mais il va bientôt expirer. Cela signifie qu’il va bientôt être supprimé. Si vous souhaitez en conserver une trace, vous pouvez le télécharger au format PDF. + termine: Le traitement de votre dossier est terminé, mais il va bientôt être supprimé. Si vous souhaitez en conserver une trace, vous pouvez le télécharger au format PDF. button_delay_expiration: one: "Conserver %{count} mois supplémentaire" other: "Conserver %{count} mois supplémentaires" diff --git a/config/routes.rb b/config/routes.rb index 77991c3d6..3a8e72fba 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -268,6 +268,7 @@ Rails.application.routes.draw do get '/carte' => 'carte#show' post '/carte' => 'carte#save' post '/repousser-expiration' => 'dossiers#extend_conservation' + post '/repousser-expiration-and-restore' => 'dossiers#extend_conservation_and_restore' end # Redirection of legacy "/users/dossiers" route to "/dossiers" @@ -489,6 +490,7 @@ Rails.application.routes.draw do member do resources :commentaires, only: [:destroy] post 'repousser-expiration' => 'dossiers#extend_conservation' + post 'repousser-expiration-and-restore' => 'dossiers#extend_conservation_and_restore' get 'geo_data' get 'apercu_attestation' get 'bilans_bdf' diff --git a/db/migrate/20240715144209_add_hidden_by_expired_at_to_dossiers.rb b/db/migrate/20240715144209_add_hidden_by_expired_at_to_dossiers.rb new file mode 100644 index 000000000..870e0a51a --- /dev/null +++ b/db/migrate/20240715144209_add_hidden_by_expired_at_to_dossiers.rb @@ -0,0 +1,5 @@ +class AddHiddenByExpiredAtToDossiers < ActiveRecord::Migration[7.0] + def change + add_column :dossiers, :hidden_by_expired_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index ba11bc0a7..9239db004 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -469,6 +469,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_07_16_091043) do t.datetime "groupe_instructeur_updated_at", precision: nil t.datetime "hidden_at", precision: nil t.datetime "hidden_by_administration_at", precision: nil + t.datetime "hidden_by_expired_at" t.string "hidden_by_reason" t.datetime "hidden_by_user_at", precision: nil t.datetime "identity_updated_at", precision: nil diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 9445a00db..7ee366e49 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1307,6 +1307,71 @@ describe Instructeurs::DossiersController, type: :controller do end end + describe '#extend_conservation and restore' do + subject { post :extend_conservation_and_restore, params: { procedure_id: procedure.id, dossier_id: dossier.id } } + + before do + dossier.update(hidden_by_expired_at: 1.hour.ago, hidden_by_reason: 'expired') + end + + context 'when dossier has expired but was not hidden by anyone' do + it 'works' do + expect(subject).to redirect_to(instructeur_dossier_path(procedure, dossier)) + end + + it 'extends conservation_extension by 1 month and let dossier not hidden' do + subject + expect(dossier.reload.conservation_extension).to eq(1.month) + expect(dossier.reload.hidden_by_reason).to eq(nil) + expect(dossier.reload.hidden_by_expired_at).to eq(nil) + expect(dossier.reload.hidden_by_administration_at).to eq(nil) + expect(dossier.reload.hidden_by_user_at).to eq(nil) + end + + it 'flashed notice success' do + subject + expect(flash[:notice]).to eq(I18n.t('views.instructeurs.dossiers.archived_dossier')) + end + end + + context 'when dossier has expired and was hidden by instructeur' do + let!(:dossier) { create(:dossier, :hidden_by_administration, :accepte, :with_individual, procedure: procedure) } + + it 'extends conservation_extension by 1 month and restore dossier for instructeur' do + subject + expect(dossier.reload.conservation_extension).to eq(1.month) + expect(dossier.reload.hidden_by_reason).to eq(nil) + expect(dossier.reload.hidden_by_expired_at).to eq(nil) + expect(dossier.reload.hidden_by_administration_at).to eq(nil) + expect(dossier.reload.hidden_by_user_at).to eq(nil) + end + end + + context 'when dossier has expired and was hidden by user' do + let!(:dossier) { create(:dossier, :hidden_by_user, :accepte, :with_individual, procedure: procedure) } + it 'extends conservation_extension by 1 month and let dossier hidden for user' do + subject + expect(dossier.reload.conservation_extension).to eq(1.month) + expect(dossier.reload.hidden_by_reason).to eq("user_request") + expect(dossier.reload.hidden_by_expired_at).to eq(nil) + expect(dossier.reload.hidden_by_administration_at).to eq(nil) + expect(dossier.reload.hidden_by_user_at).not_to eq(nil) + end + end + + context 'when dossier has expired and was hidden by user and instructeur' do + let!(:dossier) { create(:dossier, :hidden_by_user, :hidden_by_administration, :accepte, :with_individual, procedure: procedure) } + it 'extends conservation_extension by 1 month and let dossier hidden for user' do + subject + expect(dossier.reload.conservation_extension).to eq(1.month) + expect(dossier.reload.hidden_by_reason).to eq("user_request") + expect(dossier.reload.hidden_by_expired_at).to eq(nil) + expect(dossier.reload.hidden_by_administration_at).to eq(nil) + expect(dossier.reload.hidden_by_user_at).not_to eq(nil) + end + end + end + describe '#reaffectation' do let!(:gi_2) { GroupeInstructeur.create(label: 'deuxième groupe', procedure: procedure) } let!(:gi_3) { GroupeInstructeur.create(label: 'troisième groupe', procedure: procedure) } diff --git a/spec/factories/dossier.rb b/spec/factories/dossier.rb index 1b96ea81a..133f242e1 100644 --- a/spec/factories/dossier.rb +++ b/spec/factories/dossier.rb @@ -114,6 +114,16 @@ FactoryBot.define do hidden_at { Time.zone.now } end + trait :hidden_by_expired do + hidden_by_expired_at { 1.day.ago } + hidden_by_reason { DeletedDossier.reasons.fetch(:expired) } + end + + trait :hidden_by_user do + hidden_by_user_at { 1.day.ago } + hidden_by_reason { DeletedDossier.reasons.fetch(:user_request) } + end + trait :hidden_by_administration do hidden_by_administration_at { 1.day.ago } hidden_by_reason { DeletedDossier.reasons.fetch(:instructeur_request) } diff --git a/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb b/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb index f18ab5a55..c69c54de2 100644 --- a/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb +++ b/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb @@ -2,6 +2,7 @@ RSpec.describe Cron::DiscardedDossiersDeletionJob, type: :job do describe '#perform' do let(:instructeur) { create(:instructeur) } let(:dossier) { create(:dossier, :with_individual, state) } + let(:dossier_2) { create(:dossier, :with_individual, state) } before do # hack to add passer_en_instruction and supprimer to dossier.dossier_operation_logs @@ -9,6 +10,8 @@ RSpec.describe Cron::DiscardedDossiersDeletionJob, type: :job do dossier.send(:log_dossier_operation, instructeur, :supprimer, dossier) dossier.update_columns(hidden_by_user_at: hidden_at, hidden_by_administration_at: hidden_at) dossier.update_column(:hidden_by_reason, "user_request") + dossier_2.update_columns(hidden_by_expired_at: hidden_at) + dossier_2.update_column(:hidden_by_reason, "expired") end subject do @@ -24,6 +27,7 @@ RSpec.describe Cron::DiscardedDossiersDeletionJob, type: :job do it 'does not delete it' do expect { dossier.reload }.not_to raise_error + expect { dossier_2.reload }.not_to raise_error end it 'does not delete its operations logs' do @@ -36,6 +40,7 @@ RSpec.describe Cron::DiscardedDossiersDeletionJob, type: :job do it 'does delete it' do expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect { dossier_2.reload }.to raise_error(ActiveRecord::RecordNotFound) end it 'deletes its operations logs except supprimer' do diff --git a/spec/mailers/dossier_mailer_spec.rb b/spec/mailers/dossier_mailer_spec.rb index e142ddb40..cad8960f6 100644 --- a/spec/mailers/dossier_mailer_spec.rb +++ b/spec/mailers/dossier_mailer_spec.rb @@ -84,23 +84,23 @@ RSpec.describe DossierMailer, type: :mailer do it { expect(subject.perform_deliveries).to be_falsy } end - def notify_deletion_to_administration(deleted_dossier, to_email) - @subject = default_i18n_subject(dossier_id: deleted_dossier.dossier_id) - @deleted_dossier = deleted_dossier + def notify_deletion_to_administration(hidden_dossier, to_email) + @subject = default_i18n_subject(dossier_id: hidden_dossier.id) + @hidden_dossier = hidden_dossier mail(to: to_email, subject: @subject) end describe '.notify_deletion_to_administration' do - let(:deleted_dossier) { build(:deleted_dossier) } + let(:hidden_dossier) { build(:dossier) } - subject { described_class.notify_deletion_to_administration(deleted_dossier, to_email) } + subject { described_class.notify_deletion_to_administration(hidden_dossier, to_email) } it 'verifies subject and body content for deletion notification' do - expect(subject.subject).to eq("Le dossier nº #{deleted_dossier.dossier_id} a été supprimé à la demande de l’usager") + expect(subject.subject).to eq("Le dossier nº #{hidden_dossier.id} a été supprimé à la demande de l’usager") expect(subject.body).to include("À la demande de l’usager") - expect(subject.body).to include(deleted_dossier.dossier_id) - expect(subject.body).to include(deleted_dossier.procedure.libelle) + expect(subject.body).to include(hidden_dossier.id) + expect(subject.body).to include(hidden_dossier.procedure.libelle) end end @@ -121,52 +121,53 @@ RSpec.describe DossierMailer, type: :mailer do subject { described_class.notify_brouillon_deletion([dossier.hash_for_deletion_mail], dossier.user.email) } it 'verifies subject and body content for brouillon deletion notification' do - expect(subject.subject).to eq("Un dossier en brouillon a été supprimé automatiquement") + expect(subject.subject).to eq("Un dossier en brouillon a été supprimé") expect(subject.body).to include("n° #{dossier.id} (#{dossier.procedure.libelle})") end end describe '.notify_automatic_deletion_to_user' do - let(:deleted_dossier) { create(:deleted_dossier, dossier: dossier, reason: :expired) } + # let(:deleted_dossier) { create(:deleted_dossier, dossier: dossier, reason: :expired) } + # let(:hidden_dossier) { build(:dossier, :en_construction, hidden_at: Time.zone.now, hidden_by_reason: 'expired') } describe 'en_construction' do - let(:dossier) { create(:dossier, :en_construction) } + # let(:dossier) { create(:dossier, :en_construction) } + let(:hidden_dossier) { create(:dossier, :en_construction, hidden_at: Time.zone.now, hidden_by_reason: 'expired') } - subject { described_class.notify_automatic_deletion_to_user([deleted_dossier], dossier.user.email) } + subject { described_class.notify_automatic_deletion_to_user([hidden_dossier], hidden_dossier.user.email) } it 'checks email subject, to, and body for correct inclusions and exclusions for en_construction status' do - expect(subject.to).to eq([dossier.user.email]) - expect(subject.subject).to eq("Un dossier a été supprimé automatiquement de votre compte") - expect(subject.body).to include("N° #{dossier.id} ") - expect(subject.body).to include(dossier.procedure.libelle) - expect(subject.body).to include("nous nous excusons de la gêne occasionnée") + expect(subject.to).to eq([hidden_dossier.user.email]) + expect(subject.subject).to eq("Un dossier a été supprimé de votre compte") + expect(subject.body).to include("N° #{hidden_dossier.id} ") + expect(subject.body).to include(hidden_dossier.procedure.libelle) end end describe 'termine' do - let(:dossier) { create(:dossier, :accepte) } + let(:hidden_dossier) { create(:dossier, :accepte, hidden_at: Time.zone.now, hidden_by_reason: 'expired') } - subject { described_class.notify_automatic_deletion_to_user([deleted_dossier], dossier.user.email) } + subject { described_class.notify_automatic_deletion_to_user([hidden_dossier], hidden_dossier.user.email) } it 'checks email subject, to, and body for correct inclusions and exclusions for termine status' do - expect(subject.to).to eq([dossier.user.email]) - expect(subject.subject).to eq("Un dossier a été supprimé automatiquement de votre compte") - expect(subject.body).to include("N° #{dossier.id} ") - expect(subject.body).to include(dossier.procedure.libelle) - expect(subject.body).not_to include("nous nous excusons de la gêne occasionnée") + expect(subject.to).to eq([hidden_dossier.user.email]) + expect(subject.subject).to eq("Un dossier a été supprimé de votre compte") + expect(subject.body).to include("N° #{hidden_dossier.id} ") + expect(subject.body).to include(hidden_dossier.procedure.libelle) end end end describe '.notify_automatic_deletion_to_administration' do - let(:dossier) { create(:dossier, :en_construction) } - let(:deleted_dossier) { create(:deleted_dossier, dossier: dossier, reason: :expired) } + # let(:dossier) { create(:dossier, :en_construction) } + let(:hidden_dossier) { create(:dossier, :accepte, hidden_at: Time.zone.now, hidden_by_reason: 'expired') } + # let(:deleted_dossier) { create(:deleted_dossier, dossier: dossier, reason: :expired) } - subject { described_class.notify_automatic_deletion_to_administration([deleted_dossier], dossier.user.email) } + subject { described_class.notify_automatic_deletion_to_administration([hidden_dossier], hidden_dossier.user.email) } it 'verifies subject and body content for automatic deletion notification' do - expect(subject.subject).to eq("Un dossier a été supprimé automatiquement") - expect(subject.body).to include("n° #{dossier.id} (#{dossier.procedure.libelle})") + expect(subject.subject).to eq("Un dossier a été supprimé") + expect(subject.body).to include("n° #{hidden_dossier.id} (#{hidden_dossier.procedure.libelle})") end end @@ -177,11 +178,11 @@ RSpec.describe DossierMailer, type: :mailer do subject { described_class.notify_near_deletion_to_administration([dossier], dossier.user.email) } it 'checks email subject and body for correct inclusions for en_construction status' do - expect(subject.subject).to eq("Un dossier en construction va bientôt être supprimé") + expect(subject.subject).to eq("Un dossier en attente d'instruction va bientôt être supprimé") expect(subject.body).to include("N° #{dossier.id} ") expect(subject.body).to include(dossier.procedure.libelle) expect(subject.body).to include("PDF") - expect(subject.body).to include("Vous avez 14 jours pour commencer l’instruction du dossier.") + expect(subject.body).to include("il vous reste 14 jours pour démarrer l'instruction ") end end @@ -191,7 +192,7 @@ RSpec.describe DossierMailer, type: :mailer do subject { described_class.notify_near_deletion_to_administration([dossier], dossier.user.email) } it 'verifies subject and body content for near deletion notification of completed cases' do - expect(subject.subject).to eq("Un dossier dont le traitement est terminé va bientôt être supprimé") + expect(subject.subject).to eq("Un dossier traité va bientôt être supprimé") expect(subject.body).to include("N° #{dossier.id} ") expect(subject.body).to include(dossier.procedure.libelle) end @@ -206,11 +207,11 @@ RSpec.describe DossierMailer, type: :mailer do it 'verifies email subject, to, and body for correct inclusions for en_construction status' do expect(subject.to).to eq([dossier.user.email]) - expect(subject.subject).to eq("Un dossier en construction va bientôt être supprimé") + expect(subject.subject).to eq("Un dossier en attente d'instruction va bientôt être supprimé") expect(subject.body).to include("N° #{dossier.id} ") expect(subject.body).to include(dossier.procedure.libelle) expect(subject.body).to include("Votre compte reste activé") - expect(subject.body).to include("Si vous souhaitez conserver votre dossier plus longtemps, vous pouvez prolonger sa durée de conservation dans l’interface.") + expect(subject.body).to include("Depuis la page de votre dossier vous avez la possibilité de :
- prolonger la durée de conservation") end end @@ -221,7 +222,7 @@ RSpec.describe DossierMailer, type: :mailer do it 'checks email subject, to, and body for correct inclusions for termine status' do expect(subject.to).to eq([dossier.user.email]) - expect(subject.subject).to eq("Un dossier dont le traitement est terminé va bientôt être supprimé") + expect(subject.subject).to eq("Un dossier traité va bientôt être supprimé") expect(subject.body).to include("N° #{dossier.id} ") expect(subject.body).to include(dossier.procedure.libelle) expect(subject.body).to include("Votre compte reste activé") @@ -235,7 +236,7 @@ RSpec.describe DossierMailer, type: :mailer do subject { described_class.notify_near_deletion_to_user(dossiers, dossiers[0].user.email) } it 'verifies email subject and body contain correct dossier numbers for multiple termine status' do - expect(subject.subject).to eq("Des dossiers dont le traitement est terminé vont bientôt être supprimés") + expect(subject.subject).to eq("Des dossiers traités vont bientôt être supprimés") dossiers.each do |dossier| expect(subject.body).to include("N° #{dossier.id} ") end diff --git a/spec/mailers/previews/dossier_mailer_preview.rb b/spec/mailers/previews/dossier_mailer_preview.rb index 718d3f152..dae9da998 100644 --- a/spec/mailers/previews/dossier_mailer_preview.rb +++ b/spec/mailers/previews/dossier_mailer_preview.rb @@ -56,15 +56,15 @@ class DossierMailerPreview < ActionMailer::Preview end def notify_deletion_to_administration - DossierMailer.notify_deletion_to_administration(deleted_dossier, administration_email) + DossierMailer.notify_deletion_to_administration(dossier, administration_email) end def notify_automatic_deletion_to_user - DossierMailer.notify_automatic_deletion_to_user([deleted_dossier, deleted_dossier], usager_email) + DossierMailer.notify_automatic_deletion_to_user([dossier, dossier], usager_email) end def notify_automatic_deletion_to_administration - DossierMailer.notify_automatic_deletion_to_administration([deleted_dossier, deleted_dossier], administration_email) + DossierMailer.notify_automatic_deletion_to_administration([dossier, dossier], administration_email) end def notify_brouillon_not_submitted diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index 6d8ff2a20..1b12cfddb 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -724,6 +724,7 @@ describe Instructeur, type: :model do it { expect(subject['traites']).to eq(0) } it { expect(subject['tous']).to eq(0) } it { expect(subject['archives']).to eq(1) } + it { expect(subject['supprimes_recemment']).to eq(0) } it { expect(subject['expirant']).to eq(0) } context 'and terminer dossiers on each of the others groups' do @@ -736,6 +737,7 @@ describe Instructeur, type: :model do context 'with an expirants dossier' do let!(:expiring_dossier_termine_deleted) { create(:dossier, :accepte, procedure: procedure, processed_at: 175.days.ago, hidden_by_administration_at: 2.days.ago) } + let!(:expiring_dossier_termine_auto_deleted) { create(:dossier, :accepte, procedure: procedure, processed_at: 175.days.ago, hidden_by_expired_at: 2.days.ago) } let!(:expiring_dossier_termine) { create(:dossier, :accepte, procedure: procedure, processed_at: 175.days.ago) } let!(:expiring_dossier_en_construction) { create(:dossier, :en_construction, en_construction_at: 175.days.ago, procedure: procedure) } before { subject } @@ -745,6 +747,7 @@ describe Instructeur, type: :model do it { expect(subject['traites']).to eq(1) } it { expect(subject['tous']).to eq(2) } it { expect(subject['archives']).to eq(0) } + it { expect(subject['supprimes_recemment']).to eq(2) } it { expect(subject['expirant']).to eq(2) } end end diff --git a/spec/services/expired/expired_dossiers_deletion_service_spec.rb b/spec/services/expired/expired_dossiers_deletion_service_spec.rb index c15deb7a3..7e201d802 100644 --- a/spec/services/expired/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired/expired_dossiers_deletion_service_spec.rb @@ -217,7 +217,6 @@ describe Expired::DossiersDeletionService do context 'with a single dossier' do let!(:dossier) { create(:dossier, :en_construction, :followed, procedure: procedure, en_construction_close_to_expiration_notice_sent_at: notice_sent_at) } - let(:deleted_dossier) { DeletedDossier.find_by(dossier_id: dossier.id) } before { service.delete_expired_en_construction_and_notify } @@ -240,22 +239,23 @@ describe Expired::DossiersDeletionService do context 'when a notice has been sent a long time ago' do let(:notice_sent_at) { (warning_period + 4.days).ago } - it { expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with([deleted_dossier], dossier.user.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with([dossier], dossier.user.email) } it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).twice } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier], dossier.procedure.administrateurs.first.email) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier], dossier.followers_instructeurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier], dossier.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier], dossier.followers_instructeurs.first.email) } + + it { expect(dossier.reload.hidden_by_user_at).to eq(nil) } + it { expect(dossier.reload.hidden_by_administration_at).to eq(nil) } + it { expect(dossier.reload.hidden_by_expired_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier.reload.hidden_by_reason).to eq('expired') } end end context 'with 2 dossiers to delete' do let!(:dossier_1) { create(:dossier, :en_construction, procedure: procedure, user: user, en_construction_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } let!(:dossier_2) { create(:dossier, :en_construction, procedure: procedure_2, user: user, en_construction_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } - let(:deleted_dossier_1) { DeletedDossier.find_by(dossier_id: dossier_1.id) } - let(:deleted_dossier_2) { DeletedDossier.find_by(dossier_id: dossier_2.id) } let!(:instructeur) { create(:instructeur) } @@ -265,12 +265,17 @@ describe Expired::DossiersDeletionService do end it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with(match_array([deleted_dossier_1, deleted_dossier_2]), user.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with(match_array([dossier_1, dossier_2]), user.email) } it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).thrice } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(match_array([deleted_dossier_1, deleted_dossier_2]), instructeur.email) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_1], dossier_1.procedure.administrateurs.first.email) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_2], dossier_2.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(match_array([dossier_1, dossier_2]), instructeur.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier_1], dossier_1.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier_2], dossier_2.procedure.administrateurs.first.email) } + + it { expect(dossier_1.reload.hidden_by_expired_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_1.reload.hidden_by_reason).to eq('expired') } + it { expect(dossier_2.reload.hidden_by_expired_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_2.reload.hidden_by_reason).to eq('expired') } end end @@ -364,7 +369,6 @@ describe Expired::DossiersDeletionService do context 'with a single dossier' do let!(:dossier) { create(:dossier, :followed, :accepte, procedure: procedure, termine_close_to_expiration_notice_sent_at: notice_sent_at) } - let(:deleted_dossier) { DeletedDossier.find_by(dossier_id: dossier.id) } before { service.delete_expired_termine_and_notify } @@ -387,22 +391,21 @@ describe Expired::DossiersDeletionService do context 'when a notice has been sent a long time ago' do let(:notice_sent_at) { (warning_period + 4.days).ago } - it { expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) } + it { expect(dossier.reload.hidden_by_expired_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier.reload.hidden_by_reason).to eq('expired') } it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with([deleted_dossier], dossier.user.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with([dossier], dossier.user.email) } it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).twice } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier], dossier.procedure.administrateurs.first.email) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier], dossier.followers_instructeurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier], dossier.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier], dossier.followers_instructeurs.first.email) } end end context 'with 2 dossiers to delete' do let!(:dossier_1) { create(:dossier, :accepte, procedure: procedure, user: user, termine_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } let!(:dossier_2) { create(:dossier, :refuse, procedure: procedure_2, user: user, termine_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } - let(:deleted_dossier_1) { DeletedDossier.find_by(dossier_id: dossier_1.id) } - let(:deleted_dossier_2) { DeletedDossier.find_by(dossier_id: dossier_2.id) } let!(:instructeur) { create(:instructeur) } @@ -412,19 +415,22 @@ describe Expired::DossiersDeletionService do end it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with(match_array([deleted_dossier_1, deleted_dossier_2]), user.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with(match_array([dossier_1, dossier_2]), user.email) } it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).thrice } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(match_array([deleted_dossier_1, deleted_dossier_2]), instructeur.email) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_1], dossier_1.procedure.administrateurs.first.email) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_2], dossier_2.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(match_array([dossier_1, dossier_2]), instructeur.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier_1], dossier_1.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier_2], dossier_2.procedure.administrateurs.first.email) } + + it { expect(dossier_1.reload.hidden_by_expired_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_1.reload.hidden_by_reason).to eq('expired') } + it { expect(dossier_2.reload.hidden_by_expired_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_2.reload.hidden_by_reason).to eq('expired') } end context 'with 1 dossier deleted by user and 1 dossier deleted by administration' do let!(:dossier_1) { create(:dossier, :accepte, procedure: procedure, user: user, hidden_by_administration_at: 1.hour.ago, termine_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } let!(:dossier_2) { create(:dossier, :refuse, procedure: procedure_2, user: user, hidden_by_user_at: 1.hour.ago, termine_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } - let(:deleted_dossier_1) { DeletedDossier.find_by(dossier_id: dossier_1.id) } - let(:deleted_dossier_2) { DeletedDossier.find_by(dossier_id: dossier_2.id) } let!(:instructeur) { create(:instructeur) } @@ -434,11 +440,11 @@ describe Expired::DossiersDeletionService do end it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with(match_array([deleted_dossier_1]), user.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with(match_array([dossier_1]), user.email) } it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).twice } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(match_array([deleted_dossier_2]), instructeur.email) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_2], dossier_2.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(match_array([dossier_2]), instructeur.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([dossier_2], dossier_2.procedure.administrateurs.first.email) } end end end diff --git a/spec/system/users/brouillon_spec.rb b/spec/system/users/brouillon_spec.rb index 39ac071cb..06a870cfe 100644 --- a/spec/system/users/brouillon_spec.rb +++ b/spec/system/users/brouillon_spec.rb @@ -294,13 +294,13 @@ describe 'The user' do login_as(user, scope: :user) visit brouillon_dossier_path(user_old_dossier) - expect(page).to have_css('.fr-callout__title', text: 'Votre dossier va expirer', visible: true) + expect(page).to have_css('.fr-callout__title', text: 'Votre dossier a expiré', visible: true) find('#test-user-repousser-expiration').click expect(page).to have_no_selector('#test-user-repousser-expiration') Timecop.freeze(simple_procedure.duree_conservation_dossiers_dans_ds.month.from_now) do visit brouillon_dossier_path(user_old_dossier) - expect(page).to have_css('.fr-callout__title', text: 'Votre dossier va expirer', visible: true) + expect(page).to have_css('.fr-callout__title', text: 'Votre dossier a expiré', visible: true) find('#test-user-repousser-expiration').click expect(page).to have_no_selector('#test-user-repousser-expiration') end diff --git a/spec/system/users/list_dossiers_spec.rb b/spec/system/users/list_dossiers_spec.rb index 982d719d9..116598c05 100644 --- a/spec/system/users/list_dossiers_spec.rb +++ b/spec/system/users/list_dossiers_spec.rb @@ -12,6 +12,9 @@ describe 'user access to the list of their dossiers', js: true do let!(:dossier_for_tiers) { create(:dossier, :en_instruction, :for_tiers_with_notification, user: user) } let!(:dossier_en_construction_with_accuse_lecture) { create(:dossier, :en_construction, user: user, procedure: procedure_accuse_lecture) } let!(:dossier_accepte_with_accuse_lecture) { create(:dossier, :accepte, user: user, procedure: procedure_accuse_lecture) } + let!(:dossier_en_construction_expire) { create(:dossier, :with_individual, :with_populated_champs, :en_construction, :hidden_by_expired, user: user) } + let!(:dossier_traite_expire) { create(:dossier, :accepte, :hidden_by_expired, user: user) } + let!(:dossier_en_construction_supprime) { create(:dossier, :with_individual, :with_populated_champs, :en_construction, :hidden_by_user, user: user) } let(:dossiers_per_page) { 25 } let(:last_updated_dossier) { dossier_en_construction } @@ -193,23 +196,54 @@ describe 'user access to the list of their dossiers', js: true do expect(page).not_to have_content(dossier_en_construction.procedure.libelle) end end + end - describe 'clone' do - it 'should have links to clone dossiers' do - expect(page).to have_link(nil, href: clone_dossier_path(dossier_brouillon)) - expect(page).to have_link(nil, href: clone_dossier_path(dossier_en_construction)) - expect(page).to have_link(nil, href: clone_dossier_path(dossier_en_instruction)) - end + describe 'clone' do + it 'should have links to clone dossiers' do + expect(page).to have_link(nil, href: clone_dossier_path(dossier_brouillon)) + expect(page).to have_link(nil, href: clone_dossier_path(dossier_en_construction)) + expect(page).to have_link(nil, href: clone_dossier_path(dossier_en_instruction)) + end - context 'when user clicks on clone button', js: true do - scenario 'the dossier is cloned' do - within(:css, ".card", match: :first) do - click_on 'Autres actions' - expect { click_on 'Dupliquer ce dossier' }.to change { dossier_brouillon.user.dossiers.count }.by(1) - end - - expect(page).to have_content("Votre dossier a bien été dupliqué. Vous pouvez maintenant le vérifier, l’adapter puis le déposer.") + context 'when user clicks on clone button', js: true do + scenario 'the dossier is cloned' do + within(:css, ".card", match: :first) do + click_on 'Autres actions' + expect { click_on 'Dupliquer ce dossier' }.to change { dossier_brouillon.user.dossiers.count }.by(1) end + + expect(page).to have_content("Votre dossier a bien été dupliqué. Vous pouvez maintenant le vérifier, l’adapter puis le déposer.") + end + end + end + + describe 'restore' do + it 'should have links to restore dossiers' do + click_on "3 supprimés récemment" + expect(page).to have_link('Restaurer', href: restore_dossier_path(dossier_en_construction_supprime)) + expect(page).to have_button('Restaurer et étendre la conservation') + expect(page).to have_link('Télécharger mon dossier', href: dossier_path("#{dossier_traite_expire.id}.pdf")) + end + + context 'when user clicks on restore button', js: true do + scenario 'the dossier is restored' do + click_on "3 supprimés récemment" + expect(page).to have_content(dossier_en_construction_supprime.procedure.libelle) + click_on 'Restaurer' + + expect(page).to have_content('Votre dossier a bien été restauré') + expect(page).to have_content('2 supprimés récemment') + end + end + + context 'when user clicks on restore and extend button', js: true do + scenario 'the dossier is restored and extended' do + click_on "3 supprimés récemment" + expect(page).to have_content(dossier_en_construction_expire.procedure.libelle) + click_on 'Restaurer et étendre la conservation' + + expect(page).to have_content('Votre dossier sera conservé 3 mois supplémentaire') + expect(page).to have_content('2 supprimés récemment') end end end diff --git a/spec/views/users/dossiers/index.html.haml_spec.rb b/spec/views/users/dossiers/index.html.haml_spec.rb index 16af59636..d74726330 100644 --- a/spec/views/users/dossiers/index.html.haml_spec.rb +++ b/spec/views/users/dossiers/index.html.haml_spec.rb @@ -147,7 +147,7 @@ describe 'users/dossiers/index', type: :view do expect(rendered).to have_text(/6\s+en cours/) end - it "cache key dpeends on dossier invites" do + it "cache key depends on dossier invites" do expect(user_dossiers).to receive(:present?).twice render @@ -161,7 +161,7 @@ describe 'users/dossiers/index', type: :view do expect(user_dossiers).to receive(:present?).twice render - dossier_termine.expired_keep_track_and_destroy! + dossier_termine.hide_and_keep_track!(:automatic, :expired) user.reload render