hide expired dossiers instead of delete them

This commit is contained in:
Lisa Durand 2024-06-04 17:52:01 +02:00
parent 3dd6a59101
commit c2abceaa72
No known key found for this signature in database
GPG key ID: 0DF91F2CA1E8B816
23 changed files with 232 additions and 133 deletions

View file

@ -57,7 +57,7 @@ module Users
@user_dossiers = current_user.dossiers.state_not_termine.merge(@dossiers_visibles) @user_dossiers = current_user.dossiers.state_not_termine.merge(@dossiers_visibles)
@dossiers_traites = current_user.dossiers.state_termine.merge(@dossiers_visibles) @dossiers_traites = current_user.dossiers.state_termine.merge(@dossiers_visibles)
@dossiers_invites = current_user.dossiers_invites.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)) @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_close_to_expiration = current_user.dossiers.close_to_expiration.merge(@dossiers_visibles)
@dossiers_supprimes_definitivement = deleted_dossiers @dossiers_supprimes_definitivement = deleted_dossiers
@ -255,6 +255,11 @@ module Users
def extend_conservation def extend_conservation
dossier.extend_conservation(dossier.procedure.duree_conservation_dossiers_dans_ds.months) 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) 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)) redirect_back(fallback_location: dossier_path(@dossier))
end end
@ -530,6 +535,8 @@ module Users
Dossier.visible_by_user.or(Dossier.for_procedure_preview).or(Dossier.for_editing_fork) Dossier.visible_by_user.or(Dossier.for_procedure_preview).or(Dossier.for_editing_fork)
elsif action_name == 'restore' elsif action_name == 'restore'
Dossier.hidden_by_user Dossier.hidden_by_user
elsif action_name == 'extend_conservation'
Dossier.visible_by_user.or(Dossier.hidden_by_automatic)
else else
Dossier.visible_by_user Dossier.visible_by_user
end end

View file

@ -129,32 +129,32 @@ class DossierMailer < ApplicationMailer
mail(to: to_email, subject: @subject) mail(to: to_email, subject: @subject)
end 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) configure_defaults_for_email(to_email)
@subject = default_i18n_subject(dossier_id: deleted_dossier.dossier_id) @subject = default_i18n_subject(dossier_id: hidden_dossier.id)
@deleted_dossier = deleted_dossier @hidden_dossier = hidden_dossier
mail(to: to_email, subject: @subject) mail(to: to_email, subject: @subject)
end 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) configure_defaults_for_email(to_email)
I18n.with_locale(deleted_dossiers.first.user_locale) do I18n.with_locale(hidden_dossiers.first.user_locale) do
@state = deleted_dossiers.first.state @state = hidden_dossiers.first.state
@subject = default_i18n_subject(count: deleted_dossiers.size) @subject = default_i18n_subject(count: hidden_dossiers.size)
@deleted_dossiers = deleted_dossiers @hidden_dossiers = hidden_dossiers
mail(to: to_email, subject: @subject) mail(to: to_email, subject: @subject)
end end
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) configure_defaults_for_email(to_email)
@subject = default_i18n_subject(count: deleted_dossiers.size) @subject = default_i18n_subject(count: hidden_dossiers.size)
@deleted_dossiers = deleted_dossiers @hidden_dossiers = hidden_dossiers
mail(to: to_email, subject: @subject) mail(to: to_email, subject: @subject)
end end

View file

@ -208,6 +208,7 @@ class Dossier < ApplicationRecord
scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) } scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) }
scope :state_not_en_construction, -> { where.not(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_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_en_construction_ou_instruction, -> { where(state: EN_CONSTRUCTION_OU_INSTRUCTION) }
scope :state_instruction_commencee, -> { where(state: INSTRUCTION_COMMENCEE) } scope :state_instruction_commencee, -> { where(state: INSTRUCTION_COMMENCEE) }
scope :state_termine, -> { where(state: TERMINE) } scope :state_termine, -> { where(state: TERMINE) }
@ -220,11 +221,13 @@ class Dossier < ApplicationRecord
scope :not_archived, -> { where(archived: false) } scope :not_archived, -> { where(archived: false) }
scope :prefilled, -> { where(prefilled: true) } scope :prefilled, -> { where(prefilled: true) }
scope :hidden_by_user, -> { where.not(hidden_by_user_at: nil) } 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 :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, -> { scope :visible_by_administration, -> {
state_not_brouillon state_not_brouillon
.where(hidden_by_administration_at: nil) .where(hidden_by_administration_at: nil)
.where(hidden_at: nil)
.merge(visible_by_user.or(state_not_en_construction)) .merge(visible_by_user.or(state_not_en_construction))
} }
scope :visible_by_user_or_administration, -> { visible_by_user.or(visible_by_administration) } 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 :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_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 :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_brouillon_expired_to_delete, -> { state_brouillon.deleted_by_user_expired }
scope :en_construction_expired_to_delete, -> { state_en_construction.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 :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 scope :brouillon_near_procedure_closing_date, -> do
# select users who have submitted dossier for the given 'procedures.id' # select users who have submitted dossier for the given 'procedures.id'
@ -415,7 +420,7 @@ class Dossier < ApplicationRecord
when 'tous' when 'tous'
visible_by_administration.all_state visible_by_administration.all_state
when 'supprimes_recemment' when 'supprimes_recemment'
hidden_by_administration.state_termine hidden_by_administration.state_termine.or(hidden_by_automatic)
when 'archives' when 'archives'
visible_by_administration.archived visible_by_administration.archived
when 'expirant' when 'expirant'
@ -600,6 +605,10 @@ class Dossier < ApplicationRecord
termine? || reason == :procedure_removed termine? || reason == :procedure_removed
end end
def can_be_deleted_by_automatic?(reason)
reason == :expired
end
def can_terminer_automatiquement_by_sva_svr? 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?) sva_svr_decision_triggered_at.nil? && !pending_correction? && (sva_svr_decision_on.today? || sva_svr_decision_on.past?)
end end
@ -645,7 +654,12 @@ class Dossier < ApplicationRecord
def close_to_expiration? def close_to_expiration?
return false if en_instruction? 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 end
def after_notification_expiration_date def after_notification_expiration_date
@ -820,18 +834,6 @@ class Dossier < ApplicationRecord
end end
end end
def expired_keep_track_and_destroy!
transaction do
DeletedDossier.create_from_dossier(self, :expired)
log_automatic_dossier_operation(:supprimer, self)
dossier_operation_logs.purge_discarded
destroy!
end
true
rescue
false
end
def author_is_user(author) def author_is_user(author)
author.is_a?(User) author.is_a?(User)
end end
@ -840,12 +842,18 @@ class Dossier < ApplicationRecord
author.is_a?(Instructeur) || author.is_a?(Administrateur) || author.is_a?(SuperAdmin) author.is_a?(Instructeur) || author.is_a?(Administrateur) || author.is_a?(SuperAdmin)
end end
def author_is_automatic(author)
author == :automatic
end
def hide_and_keep_track!(author, reason) def hide_and_keep_track!(author, reason)
transaction do transaction do
if author_is_administration(author) && can_be_deleted_by_administration?(reason) if author_is_administration(author) && can_be_deleted_by_administration?(reason)
update(hidden_by_administration_at: Time.zone.now, hidden_by_reason: reason) update(hidden_by_administration_at: Time.zone.now, hidden_by_reason: reason)
elsif author_is_user(author) && can_be_deleted_by_user? 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) 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 else
raise "Unauthorized dossier hide attempt Dossier##{id} by #{author} for reason #{reason}" raise "Unauthorized dossier hide attempt Dossier##{id} by #{author} for reason #{reason}"
end end
@ -1101,6 +1109,7 @@ class Dossier < ApplicationRecord
en_brouillon_expired_to_delete.find_each(&:purge_discarded) en_brouillon_expired_to_delete.find_each(&:purge_discarded)
en_construction_expired_to_delete.find_each(&:purge_discarded) en_construction_expired_to_delete.find_each(&:purge_discarded)
termine_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 end
def skip_user_notification_email? def skip_user_notification_email?

View file

@ -80,6 +80,11 @@ class DossierOperationLog < ApplicationRecord
def self.serialize_author(author) def self.serialize_author(author)
if author.nil? if author.nil?
nil nil
elsif author == :automatic
{
id: "Automatic",
email: CONTACT_EMAIL
}.as_json
else else
{ {
id: serialize_author_id(author), id: serialize_author_id(author),

View file

@ -227,18 +227,18 @@ class Instructeur < ApplicationRecord
def dossiers_count_summary(groupe_instructeur_ids) def dossiers_count_summary(groupe_instructeur_ids)
query = <<~EOF query = <<~EOF
SELECT 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 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 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 ('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 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 not archived) AS tous, 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 archived) AS archives, 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 AND dossiers.state in ('accepte', 'refuse', 'sans_suite')) AS supprimes_recemment, 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 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 procedures.procedure_expires_when_termine_enabled
AND ( AND (
dossiers.state in ('accepte', 'refuse', 'sans_suite') 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 AND dossiers.processed_at + dossiers.conservation_extension + (procedures.duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now
) OR ( ) 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 AND dossiers.en_construction_at + dossiers.conservation_extension + (duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now
) )
) AS expirant ) AS expirant

View file

@ -93,27 +93,26 @@ class Expired::DossiersDeletionService < Expired::MailRateLimiter
administration_notifications = group_by_fonctionnaire_email(dossiers_to_remove) administration_notifications = group_by_fonctionnaire_email(dossiers_to_remove)
.map { |(email, dossiers)| [email, dossiers.map(&:id)] } .map { |(email, dossiers)| [email, dossiers.map(&:id)] }
deleted_dossier_ids = [] hidden_dossier_ids = []
dossiers_to_remove.find_each do |dossier| dossiers_to_remove.find_each do |dossier|
if dossier.expired_keep_track_and_destroy! dossier.hide_and_keep_track!(:automatic, :expired)
deleted_dossier_ids << dossier.id hidden_dossier_ids << dossier.id
end
end end
user_notifications.each do |(email, dossier_ids)| 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? if dossier_ids.present?
mail = DossierMailer.notify_automatic_deletion_to_user( mail = DossierMailer.notify_automatic_deletion_to_user(
DeletedDossier.where(dossier_id: dossier_ids).to_a, Dossier.where(id: dossier_ids).to_a,
email email
) )
send_with_delay(mail) send_with_delay(mail)
end end
end end
administration_notifications.each do |(email, dossier_ids)| 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? if dossier_ids.present?
mail = DossierMailer.notify_automatic_deletion_to_administration( mail = DossierMailer.notify_automatic_deletion_to_administration(
DeletedDossier.where(dossier_id: dossier_ids).to_a, Dossier.where(id: dossier_ids).to_a,
email email
) )
send_with_delay(mail) send_with_delay(mail)

View file

@ -3,9 +3,9 @@
%p= t(:hello, scope: [:views, :shared, :greetings]) %p= t(:hello, scope: [:views, :shared, :greetings])
%p %p
= t('.header', count: @deleted_dossiers.size) = t('.header', count: @hidden_dossiers.size)
%ul %ul
- @deleted_dossiers.each do |d| - @hidden_dossiers.each do |d|
%li n° #{d.dossier_id} (#{d.procedure.libelle}) %li n° #{d.id} (#{d.procedure.libelle})
= render partial: "layouts/mailers/signature" = render partial: "layouts/mailers/signature"

View file

@ -3,15 +3,15 @@
%p= t(:hello, scope: [:views, :shared, :greetings]) %p= t(:hello, scope: [:views, :shared, :greetings])
%p %p
= t('.header', count: @deleted_dossiers.size) = t('.header', count: @hidden_dossiers.size)
%ul %ul
- @deleted_dossiers.each do |d| - @hidden_dossiers.each do |d|
%li N° #{d.dossier_id} (#{d.procedure.libelle}) %li N° #{d.id} (#{d.procedure.libelle})
%p %p
%strong= t('.account_active', count: @deleted_dossiers.size) %strong= t('.account_active', count: @hidden_dossiers.size)
- if @state == Dossier.states.fetch(:en_construction) - 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" = render partial: "layouts/mailers/signature"

View file

@ -3,6 +3,6 @@
%p= t(:hello, scope: [:views, :shared, :greetings]) %p= t(:hello, scope: [:views, :shared, :greetings])
%p %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" = render partial: "layouts/mailers/signature"

View file

@ -6,8 +6,9 @@
- if dossier.conservation_extension.positive? - if dossier.conservation_extension.positive?
= t('instructeurs.dossiers.header.banner.expiration_date_extended') = t('instructeurs.dossiers.header.banner.expiration_date_extended')
- if dossier.close_to_expiration? - if dossier.close_to_expiration? || dossier.has_expired?
= render Dsfr::CalloutComponent.new(title: t('instructeurs.dossiers.header.banner.title'), theme: :warning) do |c| - 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 - c.with_body do
- if dossier.brouillon? - if dossier.brouillon?
= t('instructeurs.dossiers.header.banner.states.brouillon') = t('instructeurs.dossiers.header.banner.states.brouillon')

View file

@ -19,6 +19,8 @@
= t('views.users.dossiers.dossiers_list.n_dossier') = t('views.users.dossiers.dossiers_list.n_dossier')
= dossier.dossier_id = dossier.dossier_id
= status_badge(dossier.state, 'fr-mb-1w')
%br
%span.fr-badge.fr-badge--sm.fr-badge--warning %span.fr-badge.fr-badge--sm.fr-badge--warning
= t('views.users.dossiers.dossiers_list.deleted_badge') = t('views.users.dossiers.dossiers_list.deleted_badge')

View file

@ -18,7 +18,10 @@
- if dossier.hidden_by_user? - if dossier.hidden_by_user?
%p.fr-icon--sm.fr-icon-delete-line %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 - else
%p.fr-icon--sm.fr-icon-edit-box-line %p.fr-icon--sm.fr-icon-edit-box-line
- if dossier.depose_at.present? - if dossier.depose_at.present?
@ -40,11 +43,13 @@
= t('views.users.dossiers.dossiers_list.n_dossier') = t('views.users.dossiers.dossiers_list.n_dossier')
= number_with_html_delimiter(dossier.id) = number_with_html_delimiter(dossier.id)
= status_badge_user(dossier, 'fr-mb-1w')
- if @statut == "dossiers-supprimes-recemment" - if @statut == "dossiers-supprimes-recemment"
%br
%span.fr-badge.fr-badge--sm.fr-badge--warning %span.fr-badge.fr-badge--sm.fr-badge--warning
= t('views.users.dossiers.dossiers_list.deleted_badge') = t('views.users.dossiers.dossiers_list.deleted_badge')
- else
= status_badge_user(dossier, 'fr-mb-1w')
- if dossier.pending_correction? - if dossier.pending_correction?
%br %br
@ -103,8 +108,18 @@
- if @statut == "dossiers-supprimes-recemment" - if @statut == "dossiers-supprimes-recemment"
.flex.justify-end .flex.justify-end
= link_to restore_dossier_path(dossier.id), method: :patch, class: "fr-btn fr-btn--sm" do - if dossier.hidden_at.blank?
Restaurer = 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' = paginate dossiers, views_prefix: 'shared'

View file

@ -3,8 +3,9 @@
%p.expires_at %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) %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? - if dossier.close_to_expiration? || dossier.has_expired?
= render Dsfr::CalloutComponent.new(title: t('users.dossiers.header.banner.title'), theme: :warning) do |c| - 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 - c.with_body do
- if dossier.brouillon? - if dossier.brouillon?
= t('users.dossiers.header.banner.states.brouillon') = t('users.dossiers.header.banner.states.brouillon')

View file

@ -536,6 +536,8 @@ fr:
updated_at: modifié le %{date} updated_at: modifié le %{date}
shared_with: Dossier partagé par %{owner} avec shared_with: Dossier partagé par %{owner} avec
deleted: Supprimé le %{date} 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é deleted_badge: Supprimé
dossier_action: dossier_action:
edit_dossier: "Modifier le dossier" edit_dossier: "Modifier le dossier"

View file

@ -5,10 +5,11 @@ fr:
banner: banner:
expiration_date_extended: " la date de conservation a déjà été étendue" expiration_date_extended: " la date de conservation a déjà été étendue"
title: Ce dossier va expirer title: Ce dossier va expirer
title_expired: Ce dossier a expiré
states: states:
brouillon: "" # not applicable, instructeur does not see brouillons 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 dun mois en cliquant sur le bouton suivant. en_construction: Ce dossier est en attente de prise en charge. Vous pouvez toutefois étendre cette durée dun mois en cliquant sur le bouton suivant.
termine: Le traitement de ce dossier est terminé, mais il va bientôt expirer. Cela signifie quil 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" button_delay_expiration: "Conserver un mois de plus"
notification_management: gestion des notifications notification_management: gestion des notifications
administrators_list: voir les administrateurs administrators_list: voir les administrateurs

View file

@ -12,10 +12,11 @@ fr:
new_procedure_content: "Une nouvelle démarche est disponible, consultez-la ici :" new_procedure_content: "Une nouvelle démarche est disponible, consultez-la ici :"
contact_service_html: Pour plus dinformations, veuillez vous rapprocher du service %{service_name}, disponible au %{service_phone_number} ou par email à <a href="mailto:%{service_email}">%{service_email}</a> contact_service_html: Pour plus dinformations, veuillez vous rapprocher du service %{service_name}, disponible au %{service_phone_number} ou par email à <a href="mailto:%{service_email}">%{service_email}</a>
title: Votre dossier va expirer title: Votre dossier va expirer
title_expired: Votre dossier a expiré
states: states:
brouillon: Votre dossier est en brouillon, mais va bientôt expirer. Cela signifie quil 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 ladministration. 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. en_construction: Votre dossier est en attente de prise en charge par ladministration. 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 quil 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: button_delay_expiration:
one: "Conserver %{count} mois supplémentaire" one: "Conserver %{count} mois supplémentaire"
other: "Conserver %{count} mois supplémentaires" other: "Conserver %{count} mois supplémentaires"

View file

@ -114,6 +114,16 @@ FactoryBot.define do
hidden_at { Time.zone.now } hidden_at { Time.zone.now }
end 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 trait :hidden_by_administration do
hidden_by_administration_at { 1.day.ago } hidden_by_administration_at { 1.day.ago }
hidden_by_reason { DeletedDossier.reasons.fetch(:instructeur_request) } hidden_by_reason { DeletedDossier.reasons.fetch(:instructeur_request) }

View file

@ -2,6 +2,7 @@ RSpec.describe Cron::DiscardedDossiersDeletionJob, type: :job do
describe '#perform' do describe '#perform' do
let(:instructeur) { create(:instructeur) } let(:instructeur) { create(:instructeur) }
let(:dossier) { create(:dossier, :with_individual, state) } let(:dossier) { create(:dossier, :with_individual, state) }
let(:dossier_2) { create(:dossier, :with_individual, state) }
before do before do
# hack to add passer_en_instruction and supprimer to dossier.dossier_operation_logs # 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.send(:log_dossier_operation, instructeur, :supprimer, dossier)
dossier.update_columns(hidden_by_user_at: hidden_at, hidden_by_administration_at: hidden_at) dossier.update_columns(hidden_by_user_at: hidden_at, hidden_by_administration_at: hidden_at)
dossier.update_column(:hidden_by_reason, "user_request") 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 end
subject do subject do
@ -24,6 +27,7 @@ RSpec.describe Cron::DiscardedDossiersDeletionJob, type: :job do
it 'does not delete it' do it 'does not delete it' do
expect { dossier.reload }.not_to raise_error expect { dossier.reload }.not_to raise_error
expect { dossier_2.reload }.not_to raise_error
end end
it 'does not delete its operations logs' do it 'does not delete its operations logs' do
@ -36,6 +40,7 @@ RSpec.describe Cron::DiscardedDossiersDeletionJob, type: :job do
it 'does delete it' do it 'does delete it' do
expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { dossier_2.reload }.to raise_error(ActiveRecord::RecordNotFound)
end end
it 'deletes its operations logs except supprimer' do it 'deletes its operations logs except supprimer' do

View file

@ -84,23 +84,23 @@ RSpec.describe DossierMailer, type: :mailer do
it { expect(subject.perform_deliveries).to be_falsy } it { expect(subject.perform_deliveries).to be_falsy }
end end
def notify_deletion_to_administration(deleted_dossier, to_email) def notify_deletion_to_administration(hidden_dossier, to_email)
@subject = default_i18n_subject(dossier_id: deleted_dossier.dossier_id) @subject = default_i18n_subject(dossier_id: hidden_dossier.id)
@deleted_dossier = deleted_dossier @hidden_dossier = hidden_dossier
mail(to: to_email, subject: @subject) mail(to: to_email, subject: @subject)
end end
describe '.notify_deletion_to_administration' do 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 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 lusager") expect(subject.subject).to eq("Le dossier nº #{hidden_dossier.id} a été supprimé à la demande de lusager")
expect(subject.body).to include("À la demande de lusager") expect(subject.body).to include("À la demande de lusager")
expect(subject.body).to include(deleted_dossier.dossier_id) expect(subject.body).to include(hidden_dossier.id)
expect(subject.body).to include(deleted_dossier.procedure.libelle) expect(subject.body).to include(hidden_dossier.procedure.libelle)
end end
end end
@ -127,46 +127,49 @@ RSpec.describe DossierMailer, type: :mailer do
end end
describe '.notify_automatic_deletion_to_user' do 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 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 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.subject).to eq("Un dossier a été supprimé automatiquement de votre compte")
expect(subject.body).to include("#{dossier.id} ") expect(subject.body).to include("#{hidden_dossier.id} ")
expect(subject.body).to include(dossier.procedure.libelle) expect(subject.body).to include(hidden_dossier.procedure.libelle)
expect(subject.body).to include("nous nous excusons de la gêne occasionnée") expect(subject.body).to include("nous nous excusons de la gêne occasionnée")
end end
end end
describe 'termine' do 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 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.subject).to eq("Un dossier a été supprimé automatiquement de votre compte")
expect(subject.body).to include("#{dossier.id} ") expect(subject.body).to include("#{hidden_dossier.id} ")
expect(subject.body).to include(dossier.procedure.libelle) expect(subject.body).to include(hidden_dossier.procedure.libelle)
expect(subject.body).not_to include("nous nous excusons de la gêne occasionnée") expect(subject.body).not_to include("nous nous excusons de la gêne occasionnée")
end end
end end
end end
describe '.notify_automatic_deletion_to_administration' do describe '.notify_automatic_deletion_to_administration' do
let(:dossier) { create(:dossier, :en_construction) } # let(:dossier) { create(:dossier, :en_construction) }
let(:deleted_dossier) { create(:deleted_dossier, dossier: dossier, reason: :expired) } 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 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é automatiquement")
expect(subject.body).to include("#{dossier.id} (#{dossier.procedure.libelle})") expect(subject.body).to include("#{hidden_dossier.id} (#{hidden_dossier.procedure.libelle})")
end end
end end

View file

@ -217,7 +217,6 @@ describe Expired::DossiersDeletionService do
context 'with a single dossier' 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!(: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 } 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 context 'when a notice has been sent a long time ago' do
let(:notice_sent_at) { (warning_period + 4.days).ago } 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).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).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([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.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
end end
context 'with 2 dossiers to delete' do 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_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!(: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) } let!(:instructeur) { create(:instructeur) }
@ -265,12 +263,17 @@ describe Expired::DossiersDeletionService do
end end
it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } 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).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(match_array([dossier_1, 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([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([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
end end
@ -364,7 +367,6 @@ describe Expired::DossiersDeletionService do
context 'with a single dossier' 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!(: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 } 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 context 'when a notice has been sent a long time ago' do
let(:notice_sent_at) { (warning_period + 4.days).ago } 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).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).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([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.followers_instructeurs.first.email) }
end end
end end
context 'with 2 dossiers to delete' do 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_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!(: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) } let!(:instructeur) { create(:instructeur) }
@ -412,19 +413,22 @@ describe Expired::DossiersDeletionService do
end end
it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } 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).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(match_array([dossier_1, 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([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([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
context 'with 1 dossier deleted by user and 1 dossier deleted by administration' do 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_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!(: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) } let!(:instructeur) { create(:instructeur) }
@ -434,11 +438,11 @@ describe Expired::DossiersDeletionService do
end end
it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } 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).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(match_array([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([dossier_2], dossier_2.procedure.administrateurs.first.email) }
end end
end end
end end

View file

@ -294,13 +294,13 @@ describe 'The user' do
login_as(user, scope: :user) login_as(user, scope: :user)
visit brouillon_dossier_path(user_old_dossier) 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 find('#test-user-repousser-expiration').click
expect(page).to have_no_selector('#test-user-repousser-expiration') expect(page).to have_no_selector('#test-user-repousser-expiration')
Timecop.freeze(simple_procedure.duree_conservation_dossiers_dans_ds.month.from_now) do Timecop.freeze(simple_procedure.duree_conservation_dossiers_dans_ds.month.from_now) do
visit brouillon_dossier_path(user_old_dossier) 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 find('#test-user-repousser-expiration').click
expect(page).to have_no_selector('#test-user-repousser-expiration') expect(page).to have_no_selector('#test-user-repousser-expiration')
end end

View file

@ -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_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_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_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(:dossiers_per_page) { 25 }
let(:last_updated_dossier) { dossier_en_construction } 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) expect(page).not_to have_content(dossier_en_construction.procedure.libelle)
end end
end end
end
describe 'clone' do describe 'clone' do
it 'should have links to clone dossiers' 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_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_construction))
expect(page).to have_link(nil, href: clone_dossier_path(dossier_en_instruction)) expect(page).to have_link(nil, href: clone_dossier_path(dossier_en_instruction))
end end
context 'when user clicks on clone button', js: true do context 'when user clicks on clone button', js: true do
scenario 'the dossier is cloned' do scenario 'the dossier is cloned' do
within(:css, ".card", match: :first) do within(:css, ".card", match: :first) do
click_on 'Autres actions' click_on 'Autres actions'
expect { click_on 'Dupliquer ce dossier' }.to change { dossier_brouillon.user.dossiers.count }.by(1) 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, ladapter puis le déposer.")
end end
expect(page).to have_content("Votre dossier a bien été dupliqué. Vous pouvez maintenant le vérifier, ladapter 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 end
end end

View file

@ -147,7 +147,7 @@ describe 'users/dossiers/index', type: :view do
expect(rendered).to have_text(/6\s+en cours/) expect(rendered).to have_text(/6\s+en cours/)
end end
it "cache key dpeends on dossier invites" do it "cache key depends on dossier invites" do
expect(user_dossiers).to receive(:present?).twice expect(user_dossiers).to receive(:present?).twice
render render
@ -161,7 +161,7 @@ describe 'users/dossiers/index', type: :view do
expect(user_dossiers).to receive(:present?).twice expect(user_dossiers).to receive(:present?).twice
render render
dossier_termine.expired_keep_track_and_destroy! dossier_termine.hide_and_keep_track!(:automatic, :expired)
user.reload user.reload
render render