From c2abceaa729075fe1776aae1e092cecce79ac63d Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Tue, 4 Jun 2024 17:52:01 +0200 Subject: [PATCH 01/17] hide expired dossiers instead of delete them --- app/controllers/users/dossiers_controller.rb | 9 ++- app/mailers/dossier_mailer.rb | 22 +++---- app/models/dossier.rb | 39 +++++++----- app/models/dossier_operation_log.rb | 5 ++ app/models/instructeur.rb | 16 ++--- .../expired/dossiers_deletion_service.rb | 15 +++-- ...matic_deletion_to_administration.html.haml | 6 +- ...otify_automatic_deletion_to_user.html.haml | 10 +-- ...otify_deletion_to_administration.html.haml | 2 +- .../dossiers/_expiration_banner.html.haml | 5 +- .../dossiers/_deleted_dossiers_list.html.haml | 2 + .../users/dossiers/_dossiers_list.html.haml | 25 ++++++-- .../dossiers/_expiration_banner.html.haml | 5 +- config/locales/fr.yml | 2 + .../locales/views/instructeurs/header/fr.yml | 3 +- config/locales/views/users/header/fr.yml | 5 +- spec/factories/dossier.rb | 10 +++ .../discarded_dossiers_deletion_job_spec.rb | 5 ++ spec/mailers/dossier_mailer_spec.rb | 49 ++++++++------- .../expired_dossiers_deletion_service_spec.rb | 60 +++++++++--------- spec/system/users/brouillon_spec.rb | 4 +- spec/system/users/list_dossiers_spec.rb | 62 ++++++++++++++----- .../users/dossiers/index.html.haml_spec.rb | 4 +- 23 files changed, 232 insertions(+), 133 deletions(-) diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 437289791..356779e1f 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_automatic)).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 @@ -255,6 +255,11 @@ module Users def extend_conservation dossier.extend_conservation(dossier.procedure.duree_conservation_dossiers_dans_ds.months) + + if dossier.hidden_at.present? + dossier.update!(hidden_at: nil, hidden_by_reason: nil) + end + 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 @@ -530,6 +535,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' + Dossier.visible_by_user.or(Dossier.hidden_by_automatic) 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..c78ca8208 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -208,6 +208,7 @@ class Dossier < ApplicationRecord scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) } scope :state_not_en_construction, -> { where.not(state: states.fetch(:en_construction)) } scope :state_en_instruction, -> { where(state: states.fetch(:en_instruction)) } + scope :state_not_en_instruction, -> { where.not(state: states.fetch(:en_instruction)) } scope :state_en_construction_ou_instruction, -> { where(state: EN_CONSTRUCTION_OU_INSTRUCTION) } scope :state_instruction_commencee, -> { where(state: INSTRUCTION_COMMENCEE) } scope :state_termine, -> { where(state: TERMINE) } @@ -220,11 +221,13 @@ class Dossier < ApplicationRecord scope :not_archived, -> { where(archived: false) } scope :prefilled, -> { where(prefilled: true) } scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) } + scope :hidden_by_automatic, -> { where.not(hidden_at: nil).where(hidden_by_reason: 'expired') } 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 :visible_by_user, -> { where(for_procedure_preview: false).where(hidden_by_user_at: nil, editing_fork_origin_id: nil).where(hidden_at: nil) } scope :visible_by_administration, -> { state_not_brouillon .where(hidden_by_administration_at: nil) + .where(hidden_at: nil) .merge(visible_by_user.or(state_not_en_construction)) } scope :visible_by_user_or_administration, -> { visible_by_user.or(visible_by_administration) } @@ -365,10 +368,12 @@ class Dossier < ApplicationRecord 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_automatic_expired, -> { where('dossiers.hidden_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 :not_en_instruction_expired_to_delete, -> { state_not_en_instruction.deleted_by_automatic_expired } scope :brouillon_near_procedure_closing_date, -> do # select users who have submitted dossier for the given 'procedures.id' @@ -415,7 +420,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_automatic) when 'archives' visible_by_administration.archived when 'expirant' @@ -600,6 +605,10 @@ class Dossier < ApplicationRecord termine? || reason == :procedure_removed end + def can_be_deleted_by_automatic?(reason) + reason == :expired + 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 +654,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 && expiration_notification_date > Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks.ago + end + + def has_expired? + return false if en_instruction? + expiration_notification_date < Time.zone.now && expiration_notification_date < Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks.ago end def after_notification_expiration_date @@ -820,18 +834,6 @@ 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) author.is_a?(User) end @@ -840,12 +842,18 @@ class Dossier < ApplicationRecord author.is_a?(Instructeur) || author.is_a?(Administrateur) || author.is_a?(SuperAdmin) end + def author_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) update(hidden_by_administration_at: Time.zone.now, hidden_by_reason: reason) elsif author_is_user(author) && can_be_deleted_by_user? update(hidden_by_user_at: Time.zone.now, dossier_transfer_id: nil, hidden_by_reason: reason) + elsif author_is_automatic(author) && can_be_deleted_by_automatic?(reason) + update(hidden_at: Time.zone.now, hidden_by_reason: reason) else raise "Unauthorized dossier hide attempt Dossier##{id} by #{author} for reason #{reason}" end @@ -1101,6 +1109,7 @@ class Dossier < ApplicationRecord en_brouillon_expired_to_delete.find_each(&:purge_discarded) en_construction_expired_to_delete.find_each(&:purge_discarded) termine_expired_to_delete.find_each(&:purge_discarded) + not_en_instruction_expired_to_delete.find_each(&:purge_discarded) end def skip_user_notification_email? diff --git a/app/models/dossier_operation_log.rb b/app/models/dossier_operation_log.rb index 902626a85..9cf45552f 100644 --- a/app/models/dossier_operation_log.rb +++ b/app/models/dossier_operation_log.rb @@ -80,6 +80,11 @@ class DossierOperationLog < ApplicationRecord def self.serialize_author(author) if author.nil? nil + elsif author == :automatic + { + id: "Automatic", + email: CONTACT_EMAIL + }.as_json else { id: serialize_author_id(author), diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 5933df7b7..a92059146 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_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_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_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_at IS NULL AND not archived) AS tous, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_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_at IS NOT NULL) AS supprimes_recemment, + COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_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_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/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..dd4c0f9d4 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,9 @@ %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}) = 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..bda84a188 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,15 @@ %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) + %strong= t('.account_active', count: @hidden_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)) + %p= t('.footer_en_construction', count: @hidden_dossiers.size, remaining_weeks_before_expiration: distance_of_time_in_words(Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks)) = 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/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/users/dossiers/_deleted_dossiers_list.html.haml b/app/views/users/dossiers/_deleted_dossiers_list.html.haml index 4166ebb99..dde529b7b 100644 --- a/app/views/users/dossiers/_deleted_dossiers_list.html.haml +++ b/app/views/users/dossiers/_deleted_dossiers_list.html.haml @@ -19,6 +19,8 @@ = t('views.users.dossiers.dossiers_list.n_dossier') = dossier.dossier_id + = status_badge(dossier.state, 'fr-mb-1w') + %br %span.fr-badge.fr-badge--sm.fr-badge--warning = t('views.users.dossiers.dossiers_list.deleted_badge') diff --git a/app/views/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index 465003f57..679c73df7 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -18,7 +18,10 @@ - if dossier.hidden_by_user? %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_user', date: l(dossier.hidden_by_user_at.to_date)) + - elsif dossier.hidden_at? + %p.fr-icon--sm.fr-icon-delete-line + = t('views.users.dossiers.dossiers_list.deleted_by_automatic', date: l(dossier.hidden_at.to_date)) - else %p.fr-icon--sm.fr-icon-edit-box-line - if dossier.depose_at.present? @@ -40,11 +43,13 @@ = t('views.users.dossiers.dossiers_list.n_dossier') = number_with_html_delimiter(dossier.id) + = status_badge_user(dossier, 'fr-mb-1w') + - if @statut == "dossiers-supprimes-recemment" + %br %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') + - if dossier.pending_correction? %br @@ -103,8 +108,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_at.blank? + = 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_path(dossier), class: 'fr-btn fr-btn--sm' do + Restaurer et étendre la conservation + + + - else + = render(partial: 'users/dossiers/show/print_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/fr.yml b/config/locales/fr.yml index 04a6eee5a..5c72b1f50 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -536,6 +536,8 @@ fr: updated_at: modifié le %{date} shared_with: Dossier partagé par %{owner} avec deleted: Supprimé le %{date} + deleted_by_user: Supprimé le %{date} par l'usager + deleted_by_automatic: Supprimé le %{date} automatiquement du à la date d'expiration deleted_badge: Supprimé dossier_action: edit_dossier: "Modifier le dossier" 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/spec/factories/dossier.rb b/spec/factories/dossier.rb index 1b96ea81a..16f6d83f6 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_automatic do + hidden_at { Time.zone.now } + 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..0cd0e5eaf 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_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..c9ed6ade7 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 @@ -127,46 +127,49 @@ RSpec.describe DossierMailer, type: :mailer do 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.to).to eq([hidden_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("N° #{hidden_dossier.id} ") + expect(subject.body).to include(hidden_dossier.procedure.libelle) expect(subject.body).to include("nous nous excusons de la gêne occasionnée") 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.to).to eq([hidden_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("N° #{hidden_dossier.id} ") + expect(subject.body).to include(hidden_dossier.procedure.libelle) expect(subject.body).not_to include("nous nous excusons de la gêne occasionnée") 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.body).to include("n° #{hidden_dossier.id} (#{hidden_dossier.procedure.libelle})") 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..9f03c51e5 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,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(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_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 +263,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_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_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_2.reload.hidden_by_reason).to eq('expired') } end end @@ -364,7 +367,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 +389,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_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 +413,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_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_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 +438,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..ff0d89eb7 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, :en_construction, :hidden_by_automatic, user: user) } + let!(:dossier_traite_expire) { create(:dossier, :accepte, :hidden_by_automatic, 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('imprimer', 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 From 8b88fafc25a797ddc70dce0542f75f2b40b92943 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Tue, 11 Jun 2024 15:54:54 +0200 Subject: [PATCH 02/17] add correct action for instructeur --- app/controllers/instructeurs/dossiers_controller.rb | 4 ++++ app/models/dossier.rb | 4 ++++ app/services/dossier_projection_service.rb | 8 +++++--- .../instructeurs/dossiers/_header_actions.html.haml | 1 + .../procedures/_dossier_actions.html.haml | 8 +++++++- app/views/instructeurs/procedures/show.html.haml | 1 + app/views/recherche/index.html.haml | 1 + config/locales/fr.yml | 1 + .../instructeurs/dossiers_controller_spec.rb | 13 +++++++++++++ 9 files changed, 37 insertions(+), 4 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 1605c4de1..11ff38c6d 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -376,6 +376,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' + Dossier + .where(id: current_instructeur.dossiers.visible_by_administration) + .or(Dossier.where(id: current_instructeur.dossiers.hidden_by_automatic)) else current_instructeur.dossiers.visible_by_administration end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index c78ca8208..4b17b1933 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -689,6 +689,10 @@ class Dossier < ApplicationRecord brouillon_close_to_expiration_notice_sent_at: nil, en_construction_close_to_expiration_notice_sent_at: nil, termine_close_to_expiration_notice_sent_at: nil) + + if hidden_at.present? + update(hidden_at: nil, hidden_by_reason: nil) + end end def show_procedure_state_warning? diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 85521f70f..4eb691c8a 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_at, :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_at_field = { TABLE => 'self', COLUMN => 'hidden_at' } 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_at_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_at_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_at_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/views/instructeurs/dossiers/_header_actions.html.haml b/app/views/instructeurs/dossiers/_header_actions.html.haml index f13702df7..b58a1f496 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_at: dossier.hidden_at.present?, 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..0db82e409 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_at + %li + = button_to repousser_expiration_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..bc9188a5b 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -172,6 +172,7 @@ dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), close_to_expiration: @statut == 'expirant', hidden_by_administration: @statut == 'supprimes_recemment', + hidden_at: p.hidden_at.present?, 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..d4360f8c9 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_at: 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/config/locales/fr.yml b/config/locales/fr.yml index 5c72b1f50..763bf35c2 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -409,6 +409,7 @@ fr: 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 diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 9445a00db..1a4af55d2 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1307,6 +1307,19 @@ describe Instructeurs::DossiersController, type: :controller do end end + describe '#extend_conservation and restore' do + before do + dossier.update(hidden_at: 1.hour.ago, hidden_by_reason: 'expired') + end + subject { post :extend_conservation, params: { procedure_id: procedure.id, dossier_id: dossier.id } } + + it "puts hidden_at to nil and extends conservation_extension by 1 month" do + subject + expect(dossier.reload.hidden_at).to eq(nil) + expect(dossier.reload.conservation_extension).to eq(1.month) + 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) } From 93460208897ef5f7df31c6a545ec59532fce0a9d Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Wed, 12 Jun 2024 16:32:42 +0200 Subject: [PATCH 03/17] dont use depreciated column hidden_at --- .../instructeurs/dossiers_controller.rb | 2 +- app/controllers/users/dossiers_controller.rb | 8 ++++---- app/models/dossier.rb | 20 +++++++------------ app/models/instructeur.rb | 18 ++++++++--------- app/services/dossier_projection_service.rb | 10 +++++----- .../dossiers/_header_actions.html.haml | 2 +- .../procedures/_dossier_actions.html.haml | 2 +- .../instructeurs/procedures/show.html.haml | 7 ++++--- app/views/recherche/index.html.haml | 2 +- .../users/dossiers/_dossiers_list.html.haml | 10 +++++----- config/locales/en.yml | 1 - config/locales/fr.yml | 4 +++- .../instructeurs/dossiers_controller_spec.rb | 7 ++++--- spec/factories/dossier.rb | 5 +++-- .../discarded_dossiers_deletion_job_spec.rb | 2 +- .../expired_dossiers_deletion_service_spec.rb | 18 +++++++++++------ spec/system/users/list_dossiers_spec.rb | 4 ++-- 17 files changed, 63 insertions(+), 59 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 11ff38c6d..e1192274c 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -379,7 +379,7 @@ module Instructeurs elsif action_name == 'extend_conservation' Dossier .where(id: current_instructeur.dossiers.visible_by_administration) - .or(Dossier.where(id: current_instructeur.dossiers.hidden_by_automatic)) + .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 356779e1f..1ea973ece 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.or(current_user.dossiers.hidden_by_automatic)).merge(ordered_dossiers) + @dossiers_supprimes_recemment = current_user.dossiers.hidden_by_user.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 @@ -256,8 +256,8 @@ module Users def extend_conservation dossier.extend_conservation(dossier.procedure.duree_conservation_dossiers_dans_ds.months) - if dossier.hidden_at.present? - dossier.update!(hidden_at: nil, hidden_by_reason: nil) + if dossier.hidden_by_reason == 'expired' + dossier.update!(hidden_by_administration_at: nil, hidden_by_user_at: nil, hidden_by_reason: nil) end flash[:notice] = t('views.users.dossiers.archived_dossier', duree_conservation_dossiers_dans_ds: dossier.procedure.duree_conservation_dossiers_dans_ds) @@ -536,7 +536,7 @@ module Users elsif action_name == 'restore' Dossier.hidden_by_user elsif action_name == 'extend_conservation' - Dossier.visible_by_user.or(Dossier.hidden_by_automatic) + Dossier.visible_by_user.or(Dossier.hidden_by_expired) else Dossier.visible_by_user end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 4b17b1933..84ebd034b 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -208,7 +208,6 @@ class Dossier < ApplicationRecord scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) } scope :state_not_en_construction, -> { where.not(state: states.fetch(:en_construction)) } scope :state_en_instruction, -> { where(state: states.fetch(:en_instruction)) } - scope :state_not_en_instruction, -> { where.not(state: states.fetch(:en_instruction)) } scope :state_en_construction_ou_instruction, -> { where(state: EN_CONSTRUCTION_OU_INSTRUCTION) } scope :state_instruction_commencee, -> { where(state: INSTRUCTION_COMMENCEE) } scope :state_termine, -> { where(state: TERMINE) } @@ -221,13 +220,12 @@ class Dossier < ApplicationRecord scope :not_archived, -> { where(archived: false) } scope :prefilled, -> { where(prefilled: true) } scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) } - scope :hidden_by_automatic, -> { where.not(hidden_at: nil).where(hidden_by_reason: 'expired') } 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).where(hidden_at: nil) } + scope :hidden_by_expired, -> { where(hidden_by_reason: 'expired') } + scope :visible_by_user, -> { where(for_procedure_preview: false).where(hidden_by_user_at: nil, editing_fork_origin_id: nil) } scope :visible_by_administration, -> { state_not_brouillon .where(hidden_by_administration_at: nil) - .where(hidden_at: nil) .merge(visible_by_user.or(state_not_en_construction)) } scope :visible_by_user_or_administration, -> { visible_by_user.or(visible_by_administration) } @@ -366,14 +364,11 @@ 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_automatic_expired, -> { where('dossiers.hidden_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 :not_en_instruction_expired_to_delete, -> { state_not_en_instruction.deleted_by_automatic_expired } scope :brouillon_near_procedure_closing_date, -> do # select users who have submitted dossier for the given 'procedures.id' @@ -420,7 +415,7 @@ class Dossier < ApplicationRecord when 'tous' visible_by_administration.all_state when 'supprimes_recemment' - hidden_by_administration.state_termine.or(hidden_by_automatic) + hidden_by_administration when 'archives' visible_by_administration.archived when 'expirant' @@ -606,7 +601,7 @@ class Dossier < ApplicationRecord end def can_be_deleted_by_automatic?(reason) - reason == :expired + brouillon? || en_construction? || termine? || reason == :expired end def can_terminer_automatiquement_by_sva_svr? @@ -690,8 +685,8 @@ class Dossier < ApplicationRecord en_construction_close_to_expiration_notice_sent_at: nil, termine_close_to_expiration_notice_sent_at: nil) - if hidden_at.present? - update(hidden_at: nil, hidden_by_reason: nil) + if hidden_by_reason == 'expired' + update(hidden_by_administration_at: nil, hidden_by_user_at: nil, hidden_by_reason: nil) end end @@ -857,7 +852,7 @@ class Dossier < ApplicationRecord elsif author_is_user(author) && can_be_deleted_by_user? update(hidden_by_user_at: Time.zone.now, dossier_transfer_id: nil, hidden_by_reason: reason) elsif author_is_automatic(author) && can_be_deleted_by_automatic?(reason) - update(hidden_at: Time.zone.now, hidden_by_reason: reason) + update(hidden_by_administration_at: Time.zone.now, hidden_by_user_at: Time.zone.now, hidden_by_reason: reason) else raise "Unauthorized dossier hide attempt Dossier##{id} by #{author} for reason #{reason}" end @@ -1113,7 +1108,6 @@ class Dossier < ApplicationRecord en_brouillon_expired_to_delete.find_each(&:purge_discarded) en_construction_expired_to_delete.find_each(&:purge_discarded) termine_expired_to_delete.find_each(&:purge_discarded) - not_en_instruction_expired_to_delete.find_each(&:purge_discarded) end def skip_user_notification_email? diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index a92059146..870f9a692 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -227,18 +227,19 @@ 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 dossiers.hidden_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_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_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_at IS NULL AND not archived) AS tous, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_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_at IS NOT NULL) AS supprimes_recemment, - COUNT(DISTINCT dossiers.id) FILTER (where dossiers.hidden_by_administration_at IS NULL AND dossiers.hidden_at IS NULL AND procedures.procedure_expires_when_termine_enabled + 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 ('en_construction', '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 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') AND dossiers.hidden_at IS NULL + dossiers.state in ('en_construction') + AND dossiers.hidden_by_administration_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 @@ -252,7 +253,6 @@ class Instructeur < ApplicationRecord AND follows.unfollowed_at IS NULL WHERE dossiers.state != 'brouillon' AND dossiers.groupe_instructeur_id in (:groupe_instructeur_ids) - AND (dossiers.hidden_by_user_at IS NULL OR dossiers.state != 'en_construction') EOF sanitized_query = ActiveRecord::Base.sanitize_sql([ diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 4eb691c8a..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, :hidden_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,14 +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_at_field = { TABLE => 'self', COLUMN => 'hidden_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, hidden_at_field, for_tiers_field, individual_first_name, individual_last_name, batch_operation_field, dossier_corrections] + fields) + ([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| @@ -74,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, hidden_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 @@ -151,7 +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_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/views/instructeurs/dossiers/_header_actions.html.haml b/app/views/instructeurs/dossiers/_header_actions.html.haml index b58a1f496..84104ebee 100644 --- a/app/views/instructeurs/dossiers/_header_actions.html.haml +++ b/app/views/instructeurs/dossiers/_header_actions.html.haml @@ -8,7 +8,7 @@ dossier_is_followed: current_instructeur&.follow?(dossier), close_to_expiration: dossier.close_to_expiration?, hidden_by_administration: dossier.hidden_by_administration?, - hidden_at: dossier.hidden_at.present?, + hidden_by_expired: dossier.hidden_by_reason == '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 0db82e409..59bb4de63 100644 --- a/app/views/instructeurs/procedures/_dossier_actions.html.haml +++ b/app/views/instructeurs/procedures/_dossier_actions.html.haml @@ -1,4 +1,4 @@ -- if hidden_by_administration && hidden_at +- if hidden_by_administration && hidden_by_expired %li = button_to repousser_expiration_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: "fr-btn fr-icon-refresh-line" do = t('views.instructeurs.dossiers.restore_and_extend') diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index bc9188a5b..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,7 +173,7 @@ dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), close_to_expiration: @statut == 'expirant', hidden_by_administration: @statut == 'supprimes_recemment', - hidden_at: p.hidden_at.present?, + 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 d4360f8c9..bb2964eb5 100644 --- a/app/views/recherche/index.html.haml +++ b/app/views/recherche/index.html.haml @@ -102,7 +102,7 @@ dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), close_to_expiration: nil, hidden_by_administration: nil, - hidden_at: 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/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index 679c73df7..030560ef0 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -16,12 +16,12 @@ %p.fr-icon--sm.fr-icon-user-line = demandeur_dossier(dossier) - - if dossier.hidden_by_user? + - if dossier.hidden_by_reason == 'expired' + %p.fr-icon--sm.fr-icon-delete-line + = t('views.users.dossiers.dossiers_list.deleted_by_automatic', date: l(dossier.hidden_by_user_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)) - - elsif dossier.hidden_at? - %p.fr-icon--sm.fr-icon-delete-line - = t('views.users.dossiers.dossiers_list.deleted_by_automatic', date: l(dossier.hidden_at.to_date)) - else %p.fr-icon--sm.fr-icon-edit-box-line - if dossier.depose_at.present? @@ -108,7 +108,7 @@ - if @statut == "dossiers-supprimes-recemment" .flex.justify-end - - if dossier.hidden_at.blank? + - if dossier.hidden_by_reason != 'expired' = link_to restore_dossier_path(dossier.id), method: :patch, class: "fr-btn fr-btn--sm" do Restaurer diff --git a/config/locales/en.yml b/config/locales/en.yml index fe150433f..96f78d354 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" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 763bf35c2..5de51013a 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -405,7 +405,9 @@ 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" diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 1a4af55d2..ac7d64a87 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1309,13 +1309,14 @@ describe Instructeurs::DossiersController, type: :controller do describe '#extend_conservation and restore' do before do - dossier.update(hidden_at: 1.hour.ago, hidden_by_reason: 'expired') + dossier.update(hidden_by_administration_at: 1.hour.ago, hidden_by_user_at: 1.hour.ago, hidden_by_reason: 'expired') end subject { post :extend_conservation, params: { procedure_id: procedure.id, dossier_id: dossier.id } } - it "puts hidden_at to nil and extends conservation_extension by 1 month" do + it "puts hidden_by to nil and extends conservation_extension by 1 month" do subject - expect(dossier.reload.hidden_at).to eq(nil) + expect(dossier.reload.hidden_by_administration_at).to eq(nil) + expect(dossier.reload.hidden_by_user_at).to eq(nil) expect(dossier.reload.conservation_extension).to eq(1.month) end end diff --git a/spec/factories/dossier.rb b/spec/factories/dossier.rb index 16f6d83f6..392f4c159 100644 --- a/spec/factories/dossier.rb +++ b/spec/factories/dossier.rb @@ -114,8 +114,9 @@ FactoryBot.define do hidden_at { Time.zone.now } end - trait :hidden_by_automatic do - hidden_at { Time.zone.now } + trait :hidden_by_expired do + hidden_by_user_at { 1.day.ago } + hidden_by_administration_at { 1.day.ago } hidden_by_reason { DeletedDossier.reasons.fetch(:expired) } end diff --git a/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb b/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb index 0cd0e5eaf..197daa6c2 100644 --- a/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb +++ b/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb @@ -10,7 +10,7 @@ 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_at: hidden_at) + dossier_2.update_columns(hidden_by_user_at: hidden_at, hidden_by_administration_at: hidden_at) dossier_2.update_column(:hidden_by_reason, "expired") end diff --git a/spec/services/expired/expired_dossiers_deletion_service_spec.rb b/spec/services/expired/expired_dossiers_deletion_service_spec.rb index 9f03c51e5..40dbb92c4 100644 --- a/spec/services/expired/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired/expired_dossiers_deletion_service_spec.rb @@ -246,7 +246,8 @@ describe Expired::DossiersDeletionService do 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_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier.reload.hidden_by_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } it { expect(dossier.reload.hidden_by_reason).to eq('expired') } end end @@ -270,9 +271,11 @@ describe Expired::DossiersDeletionService do 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_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_1.reload.hidden_by_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_1.reload.hidden_by_administration_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_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_2.reload.hidden_by_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_2.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } it { expect(dossier_2.reload.hidden_by_reason).to eq('expired') } end end @@ -389,7 +392,8 @@ 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.hidden_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier.reload.hidden_by_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier.reload.hidden_by_administration_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 } @@ -420,9 +424,11 @@ describe Expired::DossiersDeletionService do 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_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_1.reload.hidden_by_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_1.reload.hidden_by_administration_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_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_2.reload.hidden_by_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + it { expect(dossier_2.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } it { expect(dossier_2.reload.hidden_by_reason).to eq('expired') } end diff --git a/spec/system/users/list_dossiers_spec.rb b/spec/system/users/list_dossiers_spec.rb index ff0d89eb7..87aa2dc91 100644 --- a/spec/system/users/list_dossiers_spec.rb +++ b/spec/system/users/list_dossiers_spec.rb @@ -12,8 +12,8 @@ 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, :en_construction, :hidden_by_automatic, user: user) } - let!(:dossier_traite_expire) { create(:dossier, :accepte, :hidden_by_automatic, user: user) } + let!(:dossier_en_construction_expire) { create(:dossier, :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 } From 2d66a67564b2c41366f33986d68d97a833321467 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Thu, 13 Jun 2024 16:54:55 +0200 Subject: [PATCH 04/17] use automatic flag for dossier operation log --- app/models/dossier.rb | 7 ++++--- app/models/dossier_operation_log.rb | 5 ----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 84ebd034b..3f0582f77 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -601,7 +601,7 @@ class Dossier < ApplicationRecord end def can_be_deleted_by_automatic?(reason) - brouillon? || en_construction? || termine? || reason == :expired + reason == :expired && !en_instruction? end def can_terminer_automatiquement_by_sva_svr? @@ -849,15 +849,16 @@ class Dossier < ApplicationRecord transaction do if author_is_administration(author) && can_be_deleted_by_administration?(reason) update(hidden_by_administration_at: Time.zone.now, hidden_by_reason: reason) + log_dossier_operation(author, :supprimer, self) elsif author_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 author_is_automatic(author) && can_be_deleted_by_automatic?(reason) update(hidden_by_administration_at: Time.zone.now, hidden_by_user_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? diff --git a/app/models/dossier_operation_log.rb b/app/models/dossier_operation_log.rb index 9cf45552f..902626a85 100644 --- a/app/models/dossier_operation_log.rb +++ b/app/models/dossier_operation_log.rb @@ -80,11 +80,6 @@ class DossierOperationLog < ApplicationRecord def self.serialize_author(author) if author.nil? nil - elsif author == :automatic - { - id: "Automatic", - email: CONTACT_EMAIL - }.as_json else { id: serialize_author_id(author), From 1441855fe885caa90501a1fe5ab4713a0235cbdc Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Thu, 13 Jun 2024 17:21:35 +0200 Subject: [PATCH 05/17] fix query for instructeur tabs count --- app/models/instructeur.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 870f9a692..9f3129dc0 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -253,6 +253,7 @@ class Instructeur < ApplicationRecord AND follows.unfollowed_at IS NULL WHERE dossiers.state != 'brouillon' AND dossiers.groupe_instructeur_id in (:groupe_instructeur_ids) + AND (dossiers.hidden_by_user_at IS NULL OR dossiers.state != 'en_construction' OR dossiers.hidden_by_reason = 'expired') EOF sanitized_query = ActiveRecord::Base.sanitize_sql([ From 0bf179068249390426ffa4662464341ff334218f Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Mon, 17 Jun 2024 16:33:19 +0200 Subject: [PATCH 06/17] change wording to clarify emails --- ...matic_deletion_to_administration.html.haml | 5 ++++ ...otify_automatic_deletion_to_user.html.haml | 7 +++--- .../notify_brouillon_near_deletion.html.haml | 4 +++- ..._near_deletion_to_administration.html.haml | 13 +++++----- .../notify_near_deletion_to_user.html.haml | 8 ++++--- .../fr.yml | 11 +++++---- .../notify_automatic_deletion_to_user/fr.yml | 17 ++++++------- .../notify_brouillon_deletion/fr.yml | 8 +++---- .../notify_brouillon_near_deletion/fr.yml | 10 ++++---- .../fr.yml | 23 +++++++----------- .../notify_near_deletion_to_user/fr.yml | 24 +++++++++---------- spec/mailers/dossier_mailer_spec.rb | 24 +++++++++---------- .../previews/dossier_mailer_preview.rb | 6 ++--- 13 files changed, 80 insertions(+), 80 deletions(-) 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 dd4c0f9d4..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 @@ -8,4 +8,9 @@ - @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 bda84a188..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 @@ -9,9 +9,8 @@ %li N° #{d.id} (#{d.procedure.libelle}) %p - %strong= t('.account_active', count: @hidden_dossiers.size) - -- if @state == Dossier.states.fetch(:en_construction) - %p= t('.footer_en_construction', count: @hidden_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_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/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..84479d47a 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 pour un délai de 6 mois
- 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 pour un délai de 6 mois
- contacter l'administration qui gère votre dossier via la messagerie diff --git a/spec/mailers/dossier_mailer_spec.rb b/spec/mailers/dossier_mailer_spec.rb index c9ed6ade7..1cc81b05e 100644 --- a/spec/mailers/dossier_mailer_spec.rb +++ b/spec/mailers/dossier_mailer_spec.rb @@ -121,7 +121,7 @@ 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 @@ -138,10 +138,9 @@ RSpec.describe DossierMailer, type: :mailer do it 'checks email subject, to, and body for correct inclusions and exclusions for en_construction status' do expect(subject.to).to eq([hidden_dossier.user.email]) - expect(subject.subject).to eq("Un dossier a été supprimé automatiquement de votre compte") + 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) - expect(subject.body).to include("nous nous excusons de la gêne occasionnée") end end @@ -152,10 +151,9 @@ RSpec.describe DossierMailer, type: :mailer do it 'checks email subject, to, and body for correct inclusions and exclusions for termine status' do expect(subject.to).to eq([hidden_dossier.user.email]) - expect(subject.subject).to eq("Un dossier a été supprimé automatiquement de votre compte") + 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) - expect(subject.body).not_to include("nous nous excusons de la gêne occasionnée") end end end @@ -168,7 +166,7 @@ RSpec.describe DossierMailer, type: :mailer do 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.subject).to eq("Un dossier a été supprimé") expect(subject.body).to include("n° #{hidden_dossier.id} (#{hidden_dossier.procedure.libelle})") end end @@ -180,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 @@ -194,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 @@ -209,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 pour un délai de 6 mois") end end @@ -224,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é") @@ -238,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 From 954ab39de8e7e1554ddae2776d12be7e1517a53c Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Mon, 17 Jun 2024 17:27:27 +0200 Subject: [PATCH 07/17] =?UTF-8?q?remove=20badge=20supprim=C3=A9=20and=20di?= =?UTF-8?q?splay=20state=20dossier=20badge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/users/dossiers/_deleted_dossiers_list.html.haml | 3 --- app/views/users/dossiers/_dossiers_list.html.haml | 6 ------ config/locales/en.yml | 1 - config/locales/fr.yml | 1 - 4 files changed, 11 deletions(-) diff --git a/app/views/users/dossiers/_deleted_dossiers_list.html.haml b/app/views/users/dossiers/_deleted_dossiers_list.html.haml index dde529b7b..55846eba4 100644 --- a/app/views/users/dossiers/_deleted_dossiers_list.html.haml +++ b/app/views/users/dossiers/_deleted_dossiers_list.html.haml @@ -20,9 +20,6 @@ = dossier.dossier_id = status_badge(dossier.state, 'fr-mb-1w') - %br - %span.fr-badge.fr-badge--sm.fr-badge--warning - = t('views.users.dossiers.dossiers_list.deleted_badge') = 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 030560ef0..214c0e411 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -45,12 +45,6 @@ = status_badge_user(dossier, 'fr-mb-1w') - - if @statut == "dossiers-supprimes-recemment" - %br - %span.fr-badge.fr-badge--sm.fr-badge--warning - = t('views.users.dossiers.dossiers_list.deleted_badge') - - - if dossier.pending_correction? %br = pending_correction_badge(:for_user) diff --git a/config/locales/en.yml b/config/locales/en.yml index 96f78d354..d03b7d70c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -522,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 5de51013a..18cb70dc8 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -541,7 +541,6 @@ fr: deleted: Supprimé le %{date} deleted_by_user: Supprimé le %{date} par l'usager deleted_by_automatic: Supprimé le %{date} automatiquement du à la date d'expiration - deleted_badge: Supprimé dossier_action: edit_dossier: "Modifier le dossier" start_other_dossier: "Commencer un autre dossier vide" From 0dcdcb5643eaa0604ebf597ff24af5c5eadcf167 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Mon, 15 Jul 2024 18:02:54 +0200 Subject: [PATCH 08/17] add column hidden_by_expired_at --- .../instructeurs/dossiers_controller.rb | 2 +- app/controllers/users/dossiers_controller.rb | 9 +-- app/models/batch_operation.rb | 2 +- app/models/dossier.rb | 16 +++-- .../users/dossiers/_dossiers_list.html.haml | 4 +- ...09_add_hidden_by_expired_at_to_dossiers.rb | 5 ++ db/schema.rb | 1 + .../instructeurs/dossiers_controller_spec.rb | 67 ++++++++++++++++--- spec/factories/dossier.rb | 3 +- spec/models/dossier_spec.rb | 12 ++-- .../expired_dossiers_deletion_service_spec.rb | 20 +++--- spec/system/users/list_dossiers_spec.rb | 4 +- 12 files changed, 99 insertions(+), 46 deletions(-) create mode 100644 db/migrate/20240715144209_add_hidden_by_expired_at_to_dossiers.rb diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index e1192274c..3dc179258 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -18,7 +18,7 @@ module Instructeurs after_action :mark_annotations_privees_as_read, only: [:annotations_privees, :update_annotations] def extend_conservation - dossier.extend_conservation(1.month) + dossier.extend_conservation(1.month, current_instructeur) flash[:notice] = t('views.instructeurs.dossiers.archived_dossier') redirect_back(fallback_location: instructeur_dossier_path(@dossier.procedure, @dossier)) end diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 1ea973ece..68d284040 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 @@ -254,12 +254,7 @@ module Users end def extend_conservation - dossier.extend_conservation(dossier.procedure.duree_conservation_dossiers_dans_ds.months) - - if dossier.hidden_by_reason == 'expired' - dossier.update!(hidden_by_administration_at: nil, hidden_by_user_at: nil, hidden_by_reason: nil) - end - + dossier.extend_conservation(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 diff --git a/app/models/batch_operation.rb b/app/models/batch_operation.rb index f6abad9b1..5c9503ec4 100644 --- a/app/models/batch_operation.rb +++ b/app/models/batch_operation.rb @@ -92,7 +92,7 @@ class BatchOperation < ApplicationRecord when BatchOperation.operations.fetch(:follow) instructeur.follow(dossier) when BatchOperation.operations.fetch(:repousser_expiration) - dossier.extend_conservation(1.month) + dossier.extend_conservation(1.month, instructeur) when BatchOperation.operations.fetch(:repasser_en_construction) dossier.repasser_en_construction!(instructeur: instructeur) when BatchOperation.operations.fetch(:unfollow) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 3f0582f77..0c5a74939 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -222,10 +222,11 @@ class Dossier < ApplicationRecord scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) } scope :hidden_by_administration, -> { where.not(hidden_by_administration_at: nil) } scope :hidden_by_expired, -> { where(hidden_by_reason: 'expired') } - scope :visible_by_user, -> { where(for_procedure_preview: false).where(hidden_by_user_at: nil, editing_fork_origin_id: nil) } + scope :visible_by_user, -> { where(for_procedure_preview: false).where(hidden_by_user_at: nil, editing_fork_origin_id: nil).where(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) } @@ -415,7 +416,7 @@ class Dossier < ApplicationRecord when 'tous' visible_by_administration.all_state when 'supprimes_recemment' - hidden_by_administration + hidden_by_administration.state_termine.or(hidden_by_expired) when 'archives' visible_by_administration.archived when 'expirant' @@ -679,14 +680,15 @@ class Dossier < ApplicationRecord brouillon? || en_construction? end - def extend_conservation(conservation_extension) + def extend_conservation(conservation_extension, author) update(conservation_extension: self.conservation_extension + conservation_extension, brouillon_close_to_expiration_notice_sent_at: nil, en_construction_close_to_expiration_notice_sent_at: nil, termine_close_to_expiration_notice_sent_at: nil) if hidden_by_reason == 'expired' - update(hidden_by_administration_at: nil, hidden_by_user_at: nil, hidden_by_reason: nil) + update(hidden_by_expired_at: nil, hidden_by_reason: nil) + restore(author) end end @@ -854,7 +856,7 @@ class Dossier < ApplicationRecord update(hidden_by_user_at: Time.zone.now, dossier_transfer_id: nil, hidden_by_reason: reason) log_dossier_operation(author, :supprimer, self) elsif author_is_automatic(author) && can_be_deleted_by_automatic?(reason) - update(hidden_by_administration_at: Time.zone.now, hidden_by_user_at: Time.zone.now, hidden_by_reason: 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}" @@ -879,6 +881,10 @@ class Dossier < ApplicationRecord 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/views/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index 214c0e411..827581775 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -18,7 +18,7 @@ - if dossier.hidden_by_reason == 'expired' %p.fr-icon--sm.fr-icon-delete-line - = t('views.users.dossiers.dossiers_list.deleted_by_automatic', 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)) @@ -113,7 +113,7 @@ - else - = render(partial: 'users/dossiers/show/print_dossier', locals: { dossier: dossier }) + = render(partial: 'users/dossiers/show/download_dossier', locals: { dossier: dossier }) = paginate dossiers, views_prefix: 'shared' 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 ac7d64a87..a9deb4723 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1308,16 +1308,67 @@ describe Instructeurs::DossiersController, type: :controller do end describe '#extend_conservation and restore' do - before do - dossier.update(hidden_by_administration_at: 1.hour.ago, hidden_by_user_at: 1.hour.ago, hidden_by_reason: 'expired') - end subject { post :extend_conservation, params: { procedure_id: procedure.id, dossier_id: dossier.id } } - it "puts hidden_by to nil and extends conservation_extension by 1 month" do - subject - expect(dossier.reload.hidden_by_administration_at).to eq(nil) - expect(dossier.reload.hidden_by_user_at).to eq(nil) - expect(dossier.reload.conservation_extension).to eq(1.month) + 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 diff --git a/spec/factories/dossier.rb b/spec/factories/dossier.rb index 392f4c159..133f242e1 100644 --- a/spec/factories/dossier.rb +++ b/spec/factories/dossier.rb @@ -115,8 +115,7 @@ FactoryBot.define do end trait :hidden_by_expired do - hidden_by_user_at { 1.day.ago } - hidden_by_administration_at { 1.day.ago } + hidden_by_expired_at { 1.day.ago } hidden_by_reason { DeletedDossier.reasons.fetch(:expired) } end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 16476828c..0627c5f08 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -107,8 +107,8 @@ describe Dossier, type: :model do context 'does not include an expiring dossier that has been postponed' do before do - expiring_dossier.extend_conservation(1.month) - expiring_dossier_with_notification.extend_conservation(1.month) + expiring_dossier.extend_conservation(1.month, user) + expiring_dossier_with_notification.extend_conservation(1.month, user) expiring_dossier.reload expiring_dossier_with_notification.reload end @@ -158,8 +158,8 @@ describe Dossier, type: :model do context 'does not include an expiring dossier that has been postponed' do before do - expiring_dossier.extend_conservation(1.month) - expiring_dossier_with_notification.extend_conservation(1.month) + expiring_dossier.extend_conservation(1.month, user) + expiring_dossier_with_notification.extend_conservation(1.month, user) expiring_dossier.reload expiring_dossier_with_notification.reload end @@ -218,8 +218,8 @@ describe Dossier, type: :model do context 'does not include an expiring dossier that has been postponed' do before do - expiring_dossier.extend_conservation(1.month) - expiring_dossier_with_notification.extend_conservation(1.month) + expiring_dossier.extend_conservation(1.month, user) + expiring_dossier_with_notification.extend_conservation(1.month, user) expiring_dossier.reload expiring_dossier_with_notification.reload end diff --git a/spec/services/expired/expired_dossiers_deletion_service_spec.rb b/spec/services/expired/expired_dossiers_deletion_service_spec.rb index 40dbb92c4..7e201d802 100644 --- a/spec/services/expired/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired/expired_dossiers_deletion_service_spec.rb @@ -246,8 +246,9 @@ describe Expired::DossiersDeletionService do 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 be_an_instance_of(ActiveSupport::TimeWithZone) } - it { expect(dossier.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + 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 @@ -271,11 +272,9 @@ describe Expired::DossiersDeletionService do 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_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } - it { expect(dossier_1.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + 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_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } - it { expect(dossier_2.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + 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 @@ -392,8 +391,7 @@ 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.hidden_by_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } - it { expect(dossier.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + 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 } @@ -424,11 +422,9 @@ describe Expired::DossiersDeletionService do 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_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } - it { expect(dossier_1.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + 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_user_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } - it { expect(dossier_2.reload.hidden_by_administration_at).to be_an_instance_of(ActiveSupport::TimeWithZone) } + 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 diff --git a/spec/system/users/list_dossiers_spec.rb b/spec/system/users/list_dossiers_spec.rb index 87aa2dc91..116598c05 100644 --- a/spec/system/users/list_dossiers_spec.rb +++ b/spec/system/users/list_dossiers_spec.rb @@ -12,7 +12,7 @@ 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, :en_construction, :hidden_by_expired, user: user) } + 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 } @@ -222,7 +222,7 @@ describe 'user access to the list of their dossiers', js: true 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('imprimer', href: dossier_path("#{dossier_traite_expire.id}.pdf")) + 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 From eb3b928cf2942baa2b000e98f0a6405bd5a3bdb0 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Wed, 17 Jul 2024 15:42:26 +0200 Subject: [PATCH 09/17] change scope to include new column for expiring dossiers --- app/models/dossier.rb | 7 ++++--- spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 0c5a74939..0201c14d2 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -367,9 +367,10 @@ class Dossier < ApplicationRecord 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' diff --git a/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb b/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb index 197daa6c2..c69c54de2 100644 --- a/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb +++ b/spec/jobs/cron/discarded_dossiers_deletion_job_spec.rb @@ -10,7 +10,7 @@ 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_user_at: hidden_at, hidden_by_administration_at: hidden_at) + dossier_2.update_columns(hidden_by_expired_at: hidden_at) dossier_2.update_column(:hidden_by_reason, "expired") end From 94e1f048ce3543f501fd7e17a2df1890ebeb42ae Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Wed, 17 Jul 2024 16:03:21 +0200 Subject: [PATCH 10/17] fix tabs count --- app/models/instructeur.rb | 19 +++++++++---------- spec/models/instructeur_spec.rb | 3 +++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 9f3129dc0..bf600c0a6 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -227,19 +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 ('en_construction', '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') - AND dossiers.hidden_by_administration_at IS NULL + 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 @@ -253,7 +252,7 @@ class Instructeur < ApplicationRecord AND follows.unfollowed_at IS NULL WHERE dossiers.state != 'brouillon' AND dossiers.groupe_instructeur_id in (:groupe_instructeur_ids) - AND (dossiers.hidden_by_user_at IS NULL OR dossiers.state != 'en_construction' OR dossiers.hidden_by_reason = 'expired') + AND (dossiers.hidden_by_user_at IS NULL OR dossiers.state != 'en_construction') EOF sanitized_query = ActiveRecord::Base.sanitize_sql([ 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 From df13e5381508302345b7c44089a8b9aef1329a46 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Thu, 18 Jul 2024 09:40:07 +0200 Subject: [PATCH 11/17] small refactos from Sim review --- app/models/dossier.rb | 20 +++++++++---------- .../notify_near_deletion_to_user/fr.yml | 4 ++-- spec/mailers/dossier_mailer_spec.rb | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 0201c14d2..44c7a09e6 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -651,12 +651,12 @@ class Dossier < ApplicationRecord def close_to_expiration? return false if en_instruction? - expiration_notification_date < Time.zone.now && expiration_notification_date > Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks.ago + 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 < Time.zone.now && expiration_notification_date < Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks.ago + expiration_notification_date < Expired::REMAINING_WEEKS_BEFORE_EXPIRATION.weeks.ago end def after_notification_expiration_date @@ -836,27 +836,27 @@ class Dossier < ApplicationRecord end 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 author_is_automatic(author) + 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) log_dossier_operation(author, :supprimer, self) - elsif author_is_user(author) && can_be_deleted_by_user? + 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 author_is_automatic(author) && can_be_deleted_by_automatic?(reason) + 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 @@ -874,9 +874,9 @@ 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 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 84479d47a..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 @@ -20,5 +20,5 @@ fr: 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: Depuis la page de votre dossier vous avez la possibilité de :
- prolonger la durée de conservation pour un délai de 6 mois
- 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 pour un délai de 6 mois
- contacter l'administration qui gère votre dossier via la messagerie + 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/spec/mailers/dossier_mailer_spec.rb b/spec/mailers/dossier_mailer_spec.rb index 1cc81b05e..cad8960f6 100644 --- a/spec/mailers/dossier_mailer_spec.rb +++ b/spec/mailers/dossier_mailer_spec.rb @@ -211,7 +211,7 @@ RSpec.describe DossierMailer, type: :mailer do 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("Depuis la page de votre dossier vous avez la possibilité de :
- prolonger la durée de conservation pour un délai de 6 mois") + expect(subject.body).to include("Depuis la page de votre dossier vous avez la possibilité de :
- prolonger la durée de conservation") end end From 5c26073af7b7a25af868437f50ae8caf8ff1418b Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Tue, 23 Jul 2024 14:31:22 +0200 Subject: [PATCH 12/17] small refacto with hidden_by_expired? method --- app/models/dossier.rb | 6 +++++- app/views/instructeurs/dossiers/_header_actions.html.haml | 2 +- app/views/instructeurs/procedures/show.html.haml | 2 +- app/views/users/dossiers/_dossiers_list.html.haml | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 44c7a09e6..969ecc2fc 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -687,7 +687,7 @@ class Dossier < ApplicationRecord en_construction_close_to_expiration_notice_sent_at: nil, termine_close_to_expiration_notice_sent_at: nil) - if hidden_by_reason == 'expired' + if hidden_by_expired? update(hidden_by_expired_at: nil, hidden_by_reason: nil) restore(author) end @@ -782,6 +782,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 diff --git a/app/views/instructeurs/dossiers/_header_actions.html.haml b/app/views/instructeurs/dossiers/_header_actions.html.haml index 84104ebee..69938b91d 100644 --- a/app/views/instructeurs/dossiers/_header_actions.html.haml +++ b/app/views/instructeurs/dossiers/_header_actions.html.haml @@ -8,7 +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_reason == 'expired', + 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/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index d73df00cd..322017d97 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -173,7 +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', + hidden_by_expired: p.hidden_by_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/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index 827581775..62f8d38d8 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -16,7 +16,7 @@ %p.fr-icon--sm.fr-icon-user-line = demandeur_dossier(dossier) - - if dossier.hidden_by_reason == 'expired' + - if dossier.hidden_by_expired? %p.fr-icon--sm.fr-icon-delete-line = t('views.users.dossiers.dossiers_list.deleted_by_automatic', date: l(dossier.hidden_by_expired_at.to_date)) - elsif dossier.hidden_by_user? From ae1a6e1b3d9197a937f688dfd355fed2fde67628 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Tue, 23 Jul 2024 14:31:59 +0200 Subject: [PATCH 13/17] improve hidden_by_expired scope --- app/models/dossier.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 969ecc2fc..6c46d3b2b 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -221,7 +221,7 @@ 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 :hidden_by_expired, -> { where(hidden_by_reason: 'expired') } + scope :hidden_by_expired, -> { where.not(hidden_by_expired_at: nil) } scope :visible_by_user, -> { where(for_procedure_preview: false).where(hidden_by_user_at: nil, editing_fork_origin_id: nil).where(hidden_by_expired_at: nil) } scope :visible_by_administration, -> { state_not_brouillon From b8205774615a69be291e2cf8e63d1c35ec814b1b Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Tue, 23 Jul 2024 15:06:23 +0200 Subject: [PATCH 14/17] create a method to extend and restore --- app/controllers/instructeurs/dossiers_controller.rb | 6 +++++- app/controllers/users/dossiers_controller.rb | 6 +++++- app/models/batch_operation.rb | 2 +- app/models/dossier.rb | 11 ++++++----- .../procedures/_dossier_actions.html.haml | 2 +- app/views/users/dossiers/_dossiers_list.html.haml | 2 +- config/routes.rb | 2 ++ spec/models/dossier_spec.rb | 12 ++++++------ 8 files changed, 27 insertions(+), 16 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 3dc179258..d7ebd7078 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -18,11 +18,15 @@ module Instructeurs after_action :mark_annotations_privees_as_read, only: [:annotations_privees, :update_annotations] def extend_conservation - dossier.extend_conservation(1.month, current_instructeur) + dossier.extend_conservation(1.month) flash[:notice] = t('views.instructeurs.dossiers.archived_dossier') 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) + end + def geo_data send_data dossier.to_feature_collection.to_json, type: 'application/json', diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 68d284040..79e244ecc 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -254,11 +254,15 @@ module Users end def extend_conservation - dossier.extend_conservation(dossier.procedure.duree_conservation_dossiers_dans_ds.months, current_user) + dossier.extend_conservation(dossier.procedure.duree_conservation_dossiers_dans_ds.months) 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 extend_conservation_and_restore + dossier.extend_conservation_and_restore(conservation_extension, author) + end + def modifier @dossier = dossier_with_champs end diff --git a/app/models/batch_operation.rb b/app/models/batch_operation.rb index 5c9503ec4..f6abad9b1 100644 --- a/app/models/batch_operation.rb +++ b/app/models/batch_operation.rb @@ -92,7 +92,7 @@ class BatchOperation < ApplicationRecord when BatchOperation.operations.fetch(:follow) instructeur.follow(dossier) when BatchOperation.operations.fetch(:repousser_expiration) - dossier.extend_conservation(1.month, instructeur) + dossier.extend_conservation(1.month) when BatchOperation.operations.fetch(:repasser_en_construction) dossier.repasser_en_construction!(instructeur: instructeur) when BatchOperation.operations.fetch(:unfollow) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 6c46d3b2b..6e13231b5 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -681,16 +681,17 @@ class Dossier < ApplicationRecord brouillon? || en_construction? end - def extend_conservation(conservation_extension, author) + def extend_conservation(conservation_extension) update(conservation_extension: self.conservation_extension + conservation_extension, brouillon_close_to_expiration_notice_sent_at: nil, en_construction_close_to_expiration_notice_sent_at: nil, termine_close_to_expiration_notice_sent_at: nil) + end - if hidden_by_expired? - update(hidden_by_expired_at: nil, hidden_by_reason: nil) - restore(author) - end + def extend_conservation_and_restore(conservation_extension, author) + extend_conservation(conservation_extension) + update(hidden_by_expired_at: nil, hidden_by_reason: nil) + restore(current_user) end def show_procedure_state_warning? diff --git a/app/views/instructeurs/procedures/_dossier_actions.html.haml b/app/views/instructeurs/procedures/_dossier_actions.html.haml index 59bb4de63..e55c99d00 100644 --- a/app/views/instructeurs/procedures/_dossier_actions.html.haml +++ b/app/views/instructeurs/procedures/_dossier_actions.html.haml @@ -1,6 +1,6 @@ - if hidden_by_administration && hidden_by_expired %li - = button_to repousser_expiration_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: "fr-btn fr-icon-refresh-line" do + = 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 diff --git a/app/views/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index 62f8d38d8..a7f93a637 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -108,7 +108,7 @@ - else - if dossier.expiration_can_be_extended? - = button_to users_dossier_repousser_expiration_path(dossier), class: 'fr-btn fr-btn--sm' do + = button_to users_dossier_extend_conservation_and_restore_path(dossier), class: 'fr-btn fr-btn--sm' do Restaurer et étendre la conservation 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/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 0627c5f08..16476828c 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -107,8 +107,8 @@ describe Dossier, type: :model do context 'does not include an expiring dossier that has been postponed' do before do - expiring_dossier.extend_conservation(1.month, user) - expiring_dossier_with_notification.extend_conservation(1.month, user) + expiring_dossier.extend_conservation(1.month) + expiring_dossier_with_notification.extend_conservation(1.month) expiring_dossier.reload expiring_dossier_with_notification.reload end @@ -158,8 +158,8 @@ describe Dossier, type: :model do context 'does not include an expiring dossier that has been postponed' do before do - expiring_dossier.extend_conservation(1.month, user) - expiring_dossier_with_notification.extend_conservation(1.month, user) + expiring_dossier.extend_conservation(1.month) + expiring_dossier_with_notification.extend_conservation(1.month) expiring_dossier.reload expiring_dossier_with_notification.reload end @@ -218,8 +218,8 @@ describe Dossier, type: :model do context 'does not include an expiring dossier that has been postponed' do before do - expiring_dossier.extend_conservation(1.month, user) - expiring_dossier_with_notification.extend_conservation(1.month, user) + expiring_dossier.extend_conservation(1.month) + expiring_dossier_with_notification.extend_conservation(1.month) expiring_dossier.reload expiring_dossier_with_notification.reload end From 7da3e05752949b8057fe5f8126162d66e72896ce Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Wed, 24 Jul 2024 17:05:09 +0200 Subject: [PATCH 15/17] small refacto to simplify scope --- app/models/dossier.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 6e13231b5..0d71af6cb 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -222,7 +222,7 @@ class Dossier < ApplicationRecord scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) } scope :hidden_by_administration, -> { where.not(hidden_by_administration_at: nil) } scope :hidden_by_expired, -> { where.not(hidden_by_expired_at: nil) } - scope :visible_by_user, -> { where(for_procedure_preview: false).where(hidden_by_user_at: nil, editing_fork_origin_id: nil).where(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) From 4b1e743ecf5e3985b966655503d203b69d41727f Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Wed, 24 Jul 2024 17:19:59 +0200 Subject: [PATCH 16/17] fix wrong method on projected dossier --- app/views/instructeurs/procedures/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index 322017d97..d73df00cd 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -173,7 +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_expired?, + 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, From 4f7b0c93d03d82e3c08d1ea24125d8a2b2063cb8 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Thu, 25 Jul 2024 14:40:22 +0200 Subject: [PATCH 17/17] fix multiple errors from creation of dedicated method to restore and extend --- app/controllers/instructeurs/dossiers_controller.rb | 4 +++- app/controllers/users/dossiers_controller.rb | 6 ++++-- app/models/dossier.rb | 2 +- app/views/users/dossiers/_dossiers_list.html.haml | 2 +- spec/controllers/instructeurs/dossiers_controller_spec.rb | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index d7ebd7078..ae148d258 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -25,6 +25,8 @@ module Instructeurs 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 @@ -380,7 +382,7 @@ 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' + 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)) diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 79e244ecc..63776d16c 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -260,7 +260,9 @@ module Users end def extend_conservation_and_restore - dossier.extend_conservation_and_restore(conservation_extension, author) + 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 @@ -534,7 +536,7 @@ 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' + elsif action_name == 'extend_conservation_and_restore' Dossier.visible_by_user.or(Dossier.hidden_by_expired) else Dossier.visible_by_user diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 0d71af6cb..63bbb2c59 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -691,7 +691,7 @@ class Dossier < ApplicationRecord def extend_conservation_and_restore(conservation_extension, author) extend_conservation(conservation_extension) update(hidden_by_expired_at: nil, hidden_by_reason: nil) - restore(current_user) + restore(author) end def show_procedure_state_warning? diff --git a/app/views/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index a7f93a637..7a7ff4c84 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -108,7 +108,7 @@ - else - if dossier.expiration_can_be_extended? - = button_to users_dossier_extend_conservation_and_restore_path(dossier), class: 'fr-btn fr-btn--sm' do + = button_to users_dossier_repousser_expiration_and_restore_path(dossier), class: 'fr-btn fr-btn--sm' do Restaurer et étendre la conservation diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index a9deb4723..7ee366e49 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1308,7 +1308,7 @@ describe Instructeurs::DossiersController, type: :controller do end describe '#extend_conservation and restore' do - subject { post :extend_conservation, params: { procedure_id: procedure.id, dossier_id: dossier.id } } + 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')