diff --git a/Gemfile.lock b/Gemfile.lock index 3256d54dc..43e8b9b5e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -556,7 +556,7 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.2.4) + rexml (3.2.5) rgeo (2.2.0) rgeo-geojson (2.1.1) rgeo (>= 1.0.0) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index e6fb16d21..0a2d6f8ea 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -211,7 +211,7 @@ module Instructeurs end def telecharger_pjs - return head(:forbidden) if !dossier.attachments_downloadable? + return head(:forbidden) if !dossier.export_and_attachments_downloadable? files = ActiveStorage::DownloadableFile.create_list_from_dossier(dossier) diff --git a/app/controllers/manager/procedures_controller.rb b/app/controllers/manager/procedures_controller.rb index dd0dcf0f1..9ca75b503 100644 --- a/app/controllers/manager/procedures_controller.rb +++ b/app/controllers/manager/procedures_controller.rb @@ -41,7 +41,7 @@ module Manager def export_mail_brouillons dossiers = procedure.dossiers.state_brouillon.includes(:user) - emails = dossiers.map { |d| d.user.email }.sort.uniq + emails = dossiers.map { |dossier| dossier.user_email_for(:display) }.sort.uniq date = Time.zone.now.strftime('%d-%m-%Y') send_data(emails.join("\n"), :filename => "brouillons-#{procedure.id}-au-#{date}.csv") end diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index f03d28f19..987939cc6 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -143,7 +143,7 @@ module Users if passage_en_construction? && errors.blank? @dossier.passer_en_construction! - NotificationMailer.send_initiated_notification(@dossier).deliver_later + NotificationMailer.send_en_construction_notification(@dossier).deliver_later @dossier.groupe_instructeur.instructeurs.with_instant_email_dossier_notifications.each do |instructeur| DossierMailer.notify_new_dossier_depose_to_instructeur(@dossier, instructeur.email).deliver_later end diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb index aea9ca2a8..652046a06 100644 --- a/app/graphql/mutations/base_mutation.rb +++ b/app/graphql/mutations/base_mutation.rb @@ -5,6 +5,8 @@ module Mutations def validate_blob(blob_id) begin blob = ActiveStorage::Blob.find_signed(blob_id) + raise ActiveSupport::MessageVerifier::InvalidSignature if blob.nil? + # open downloads the file and checks its hash blob.open { |f| } true diff --git a/app/graphql/types/dossier_type.rb b/app/graphql/types/dossier_type.rb index 7f340ffc3..57811a75e 100644 --- a/app/graphql/types/dossier_type.rb +++ b/app/graphql/types/dossier_type.rb @@ -54,7 +54,11 @@ module Types end def usager - Loaders::Record.for(User).load(object.user_id) + if object.user_deleted? + { email: object.user_email_for(:display), id: -1 } + else + Loaders::Record.for(User).load(object.user_id) + end end def groupe_instructeur diff --git a/app/lib/active_job/retry_on_transient_errors.rb b/app/lib/active_job/retry_on_transient_errors.rb index b3790359c..cf714174a 100644 --- a/app/lib/active_job/retry_on_transient_errors.rb +++ b/app/lib/active_job/retry_on_transient_errors.rb @@ -4,7 +4,8 @@ module ActiveJob::RetryOnTransientErrors TRANSIENT_ERRORS = [ Excon::Error::InternalServerError, Excon::Error::GatewayTimeout, - Excon::Error::BadRequest + Excon::Error::BadRequest, + Excon::Error::Socket ] included do diff --git a/app/lib/active_storage/downloadable_file.rb b/app/lib/active_storage/downloadable_file.rb index 25813202b..bdfe5760b 100644 --- a/app/lib/active_storage/downloadable_file.rb +++ b/app/lib/active_storage/downloadable_file.rb @@ -1,7 +1,7 @@ class ActiveStorage::DownloadableFile def self.create_list_from_dossier(dossier) dossier_export = PiecesJustificativesService.generate_dossier_export(dossier) - pjs = [dossier_export] + PiecesJustificativesService.liste_pieces_justificatives(dossier) + pjs = [dossier_export] + PiecesJustificativesService.liste_documents(dossier) pjs.map do |piece_justificative| [ piece_justificative, diff --git a/app/mailers/dossier_mailer.rb b/app/mailers/dossier_mailer.rb index 285802797..29e035ffc 100644 --- a/app/mailers/dossier_mailer.rb +++ b/app/mailers/dossier_mailer.rb @@ -13,7 +13,7 @@ class DossierMailer < ApplicationMailer subject = "Retrouvez votre brouillon pour la démarche « #{dossier.procedure.libelle} »" - mail(from: NO_REPLY_EMAIL, to: dossier.user.email, subject: subject) do |format| + mail(from: NO_REPLY_EMAIL, to: dossier.user_email_for(:notification), subject: subject) do |format| format.html { render layout: 'mailers/notifications_layout' } end end @@ -25,7 +25,7 @@ class DossierMailer < ApplicationMailer subject = "Nouveau message pour votre dossier nº #{dossier.id} (#{dossier.procedure.libelle})" - mail(from: NO_REPLY_EMAIL, to: dossier.user.email, subject: subject) do |format| + mail(from: NO_REPLY_EMAIL, to: dossier.user_email_for(:notification), subject: subject) do |format| format.html { render layout: 'mailers/notifications_layout' } end end @@ -49,7 +49,7 @@ class DossierMailer < ApplicationMailer subject = "Votre dossier nº #{@dossier.id} est en train d'être réexaminé" - mail(from: NO_REPLY_EMAIL, to: dossier.user.email, subject: subject) do |format| + mail(from: NO_REPLY_EMAIL, to: dossier.user_email_for(:notification), subject: subject) do |format| format.html { render layout: 'mailers/notifications_layout' } end end @@ -139,7 +139,7 @@ class DossierMailer < ApplicationMailer @subject = "Attention : votre dossier n'est pas déposé." @dossier = dossier - mail(to: dossier.user.email, subject: @subject) + mail(to: dossier.user_email_for(:notification), subject: @subject) end protected diff --git a/app/mailers/new_attestation_mailer.rb b/app/mailers/new_attestation_mailer.rb deleted file mode 100644 index 20c645b2b..000000000 --- a/app/mailers/new_attestation_mailer.rb +++ /dev/null @@ -1,32 +0,0 @@ -# Preview all emails at http://localhost:3000/rails/mailers/new_attestation_mailer -class NewAttestationMailer < ApplicationMailer - include Rails.application.routes.url_helpers - - def new_attestation(dossier) - to = dossier.user.email - subject = "Nouvelle attestation pour votre dossier nº #{dossier.id}" - - mail(to: to, subject: subject, body: body(dossier)) - end - - private - - def body(dossier) - <<~HEREDOC - Bonjour, - - Votre dossier nº #{dossier.id} (démarche "#{dossier.procedure.libelle}") a subi, à un moment, un "aller-retour" : - - Acceptation de votre dossier - - Passage en instruction du dossier car besoin de le modifier - - Seconde acceptation de votre dossier - - Suite à cette opération, l'attestation liée à votre dossier n'a pas été regénérée. - Ce problème est désormais reglé, votre nouvelle attestation est disponible à l'adresse suivante : - #{attestation_dossier_url(dossier)} - - Cordialement, - - L’équipe #{APPLICATION_NAME} - HEREDOC - end -end diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index 829c7ce47..056240dc2 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -8,54 +8,63 @@ class NotificationMailer < ApplicationMailer include ActionView::Helpers::SanitizeHelper + before_action :set_dossier + after_action :create_commentaire_for_notification + helper ServiceHelper helper MailerHelper layout 'mailers/notifications_layout' default from: NO_REPLY_EMAIL - def send_dossier_received(dossier) - send_notification(dossier, dossier.procedure.received_mail_template) + def send_notification + @service = @dossier.procedure.service + @logo_url = attach_logo(@dossier.procedure) + @rendered_template = sanitize(@body) + + mail(subject: @subject, to: @email, template_name: 'send_notification') end - def send_initiated_notification(dossier) - send_notification(dossier, dossier.procedure.initiated_mail_template) + def self.send_en_construction_notification(dossier) + with(dossier: dossier, state: Dossier.states.fetch(:en_construction)).send_notification end - def send_closed_notification(dossier) - send_notification(dossier, dossier.procedure.closed_mail_template) + def self.send_en_instruction_notification(dossier) + with(dossier: dossier, state: Dossier.states.fetch(:en_instruction)).send_notification end - def send_refused_notification(dossier) - send_notification(dossier, dossier.procedure.refused_mail_template) + def self.send_accepte_notification(dossier) + with(dossier: dossier, state: Dossier.states.fetch(:accepte)).send_notification end - def send_without_continuation_notification(dossier) - send_notification(dossier, dossier.procedure.without_continuation_mail_template) + def self.send_refuse_notification(dossier) + with(dossier: dossier, state: Dossier.states.fetch(:refuse)).send_notification + end + + def self.send_sans_suite_notification(dossier) + with(dossier: dossier, state: Dossier.states.fetch(:sans_suite)).send_notification end private - def send_notification(dossier, mail_template) - email = dossier.user.email + def set_dossier + @dossier = params[:dossier] - subject = mail_template.subject_for_dossier(dossier) - body = mail_template.body_for_dossier(dossier) + if @dossier.user_deleted? + mail.perform_deliveries = false + else + mail_template = @dossier.procedure.mail_template_for(params[:state]) - create_commentaire_for_notification(dossier, subject, body) - - @dossier = dossier - @service = dossier.procedure.service - @logo_url = attach_logo(dossier.procedure) - @rendered_template = sanitize(body) - @actions = mail_template.actions_for_dossier(dossier) - - mail(subject: subject, to: email, template_name: 'send_notification') + @email = @dossier.user_email_for(:notification) + @subject = mail_template.subject_for_dossier(@dossier) + @body = mail_template.body_for_dossier(@dossier) + @actions = mail_template.actions_for_dossier(@dossier) + end end - def create_commentaire_for_notification(dossier, subject, body) - params = { body: ["[#{subject}]", body].join("

") } - commentaire = CommentaireService.build_with_email(CONTACT_EMAIL, dossier, params) + def create_commentaire_for_notification + body = ["[#{@subject}]", @body].join("

") + commentaire = CommentaireService.build_with_email(CONTACT_EMAIL, @dossier, body: body) commentaire.save! end end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 8b8a1e60e..9d7b53986 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -7,6 +7,7 @@ # archived :boolean default(FALSE) # autorisation_donnees :boolean # brouillon_close_to_expiration_notice_sent_at :datetime +# deleted_user_email_never_send :string # en_construction_at :datetime # en_construction_close_to_expiration_notice_sent_at :datetime # en_construction_conservation_extension :interval default(0 seconds) @@ -136,9 +137,9 @@ class Dossier < ApplicationRecord end event :repasser_en_instruction, after: :after_repasser_en_instruction do - transitions from: :refuse, to: :en_instruction - transitions from: :sans_suite, to: :en_instruction - transitions from: :accepte, to: :en_instruction + transitions from: :refuse, to: :en_instruction, guard: :can_repasser_en_instruction? + transitions from: :sans_suite, to: :en_instruction, guard: :can_repasser_en_instruction? + transitions from: :accepte, to: :en_instruction, guard: :can_repasser_en_instruction? end end @@ -248,6 +249,7 @@ class Dossier < ApplicationRecord states = opts[:notify_on_closed] ? [:publiee, :close, :depubliee] : [:publiee, :depubliee] joins(:procedure) .where(procedures: { aasm_state: states }) + .where.not(user_id: nil) end scope :brouillon_close_to_expiration, -> do @@ -340,7 +342,7 @@ class Dossier < ApplicationRecord before_save :build_default_champs, if: Proc.new { revision_id_was.nil? } before_save :update_search_terms - after_save :send_dossier_received + after_save :send_dossier_en_instruction after_save :send_web_hook after_create_commit :send_draft_notification_email @@ -348,6 +350,22 @@ class Dossier < ApplicationRecord validates :individual, presence: true, if: -> { revision.procedure.for_individual? } validates :groupe_instructeur, presence: true, if: -> { !brouillon? } + def user_deleted? + user_id.nil? + end + + def user_email_for(use) + if user_deleted? + if use == :display + deleted_user_email_never_send + else + raise "Can not send email to discarded user" + end + else + user.email + end + end + def motivation return nil if !termine? traitements.any? ? traitements.last.motivation : read_attribute(:motivation) @@ -414,6 +432,10 @@ class Dossier < ApplicationRecord brouillon? && procedure.dossier_can_transition_to_en_construction? end + def can_repasser_en_instruction? + termine? && !user_deleted? + end + def can_be_updated_by_user? brouillon? || en_construction? end @@ -427,7 +449,7 @@ class Dossier < ApplicationRecord end def messagerie_available? - !brouillon? && !archived + !brouillon? && !user_deleted? && !archived end def en_construction_close_to_expiration? @@ -580,13 +602,18 @@ class Dossier < ApplicationRecord administration_emails.each do |email| DossierMailer.notify_deletion_to_administration(deleted_dossier, email).deliver_later end - DossierMailer.notify_deletion_to_user(deleted_dossier, user.email).deliver_later + + if !user_deleted? + DossierMailer.notify_deletion_to_user(deleted_dossier, user_email_for(:notification)).deliver_later + end log_dossier_operation(author, :supprimer, self) elsif termine? deleted_dossier = DeletedDossier.create_from_dossier(self, reason) - DossierMailer.notify_instructeur_deletion_to_user(deleted_dossier, user.email).deliver_later + if !user_deleted? + DossierMailer.notify_instructeur_deletion_to_user(deleted_dossier, user_email_for(:notification)).deliver_later + end log_dossier_operation(author, :supprimer, self) end @@ -651,7 +678,7 @@ class Dossier < ApplicationRecord save! remove_titres_identite! - NotificationMailer.send_closed_notification(self).deliver_later + NotificationMailer.send_accepte_notification(self).deliver_later send_dossier_decision_to_experts(self) log_dossier_operation(instructeur, :accepter, self) end @@ -666,7 +693,7 @@ class Dossier < ApplicationRecord save! remove_titres_identite! - NotificationMailer.send_closed_notification(self).deliver_later + NotificationMailer.send_accepte_notification(self).deliver_later log_automatic_dossier_operation(:accepter, self) end @@ -679,7 +706,7 @@ class Dossier < ApplicationRecord save! remove_titres_identite! - NotificationMailer.send_refused_notification(self).deliver_later + NotificationMailer.send_refuse_notification(self).deliver_later send_dossier_decision_to_experts(self) log_dossier_operation(instructeur, :refuser, self) end @@ -693,7 +720,7 @@ class Dossier < ApplicationRecord save! remove_titres_identite! - NotificationMailer.send_without_continuation_notification(self).deliver_later + NotificationMailer.send_sans_suite_notification(self).deliver_later send_dossier_decision_to_experts(self) log_dossier_operation(instructeur, :classer_sans_suite, self) end @@ -739,7 +766,7 @@ class Dossier < ApplicationRecord def spreadsheet_columns(with_etablissement: false, types_de_champ:, types_de_champ_private:) columns = [ ['ID', id.to_s], - ['Email', user.email] + ['Email', user_email_for(:display)] ] if procedure.for_individual? @@ -834,9 +861,8 @@ class Dossier < ApplicationRecord end end - def attachments_downloadable? - PiecesJustificativesService.liste_pieces_justificatives(self).present? \ - && PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP + def export_and_attachments_downloadable? + PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP end def linked_dossiers_for(instructeur_or_expert) @@ -910,9 +936,9 @@ class Dossier < ApplicationRecord end end - def send_dossier_received + def send_dossier_en_instruction if saved_change_to_state? && en_instruction? && !procedure.declarative_accepte? - NotificationMailer.send_dossier_received(self).deliver_later + NotificationMailer.send_en_instruction_notification(self).deliver_later end end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index b4760c353..0e6a11783 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -500,6 +500,23 @@ class Procedure < ApplicationRecord without_continuation_mail || Mails::WithoutContinuationMail.default_for_procedure(self) end + def mail_template_for(state) + case state + when Dossier.states.fetch(:en_construction) + initiated_mail_template + when Dossier.states.fetch(:en_instruction) + received_mail_template + when Dossier.states.fetch(:accepte) + closed_mail_template + when Dossier.states.fetch(:refuse) + refused_mail_template + when Dossier.states.fetch(:sans_suite) + without_continuation_mail_template + else + raise "Unknown dossier state: #{state}" + end + end + def self.default_sort { 'table' => 'self', diff --git a/app/models/user.rb b/app/models/user.rb index f9f6fa372..1e40adb85 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -170,18 +170,24 @@ class User < ApplicationRecord end def can_be_deleted? - !administrateur? && !instructeur? && !expert? && dossiers.with_discarded.state_instruction_commencee.empty? + !administrateur? && !instructeur? && !expert? end def delete_and_keep_track_dossiers(administration) if !can_be_deleted? - raise "Cannot delete this user because instruction has started for some dossiers" + raise "Cannot delete this user because they are also instructeur, expert or administrateur" end - dossiers.each do |dossier| + Invite.where(dossier: dossiers.with_discarded).destroy_all + dossiers.state_en_construction.each do |dossier| dossier.discard_and_keep_track!(administration, :user_removed) end - dossiers.with_discarded.destroy_all + DossierOperationLog + .where(dossier: dossiers.with_discarded.discarded) + .where.not(operation: DossierOperationLog.operations.fetch(:supprimer)) + .destroy_all + dossiers.with_discarded.discarded.destroy_all + dossiers.update_all(deleted_user_email_never_send: email, user_id: nil) destroy! end diff --git a/app/services/pieces_justificatives_service.rb b/app/services/pieces_justificatives_service.rb index 3c20ab32d..03c173599 100644 --- a/app/services/pieces_justificatives_service.rb +++ b/app/services/pieces_justificatives_service.rb @@ -1,5 +1,5 @@ class PiecesJustificativesService - def self.liste_pieces_justificatives(dossier) + def self.liste_documents(dossier) pjs_champs = pjs_for_champs(dossier) pjs_commentaires = pjs_for_commentaires(dossier) pjs_dossier = pjs_for_dossier(dossier) @@ -8,6 +8,14 @@ class PiecesJustificativesService .filter(&:attached?) end + def self.liste_pieces_justificatives(dossier) + pjs_champs = pjs_for_champs(dossier) + pjs_commentaires = pjs_for_commentaires(dossier) + + (pjs_champs + pjs_commentaires) + .filter(&:attached?) + end + def self.pieces_justificatives_total_size(dossier) liste_pieces_justificatives(dossier) .sum(&:byte_size) diff --git a/app/views/dossiers/show.pdf.prawn b/app/views/dossiers/show.pdf.prawn index da28de24d..087502214 100644 --- a/app/views/dossiers/show.pdf.prawn +++ b/app/views/dossiers/show.pdf.prawn @@ -174,7 +174,7 @@ def add_message(pdf, message) if message.sent_by_system? sender = 'Email automatique' elsif message.sent_by?(@dossier.user) - sender = @dossier.user.email + sender = @dossier.user_email_for(:display) end format_in_2_lines(pdf, "#{sender}, #{try_format_date(message.created_at)}", @@ -233,7 +233,7 @@ prawn_document(page_size: "A4") do |pdf| format_in_2_columns(pdf, 'Informations France Connect', "Le dossier a été déposé par le compte de #{@dossier.france_connect_information.given_name} #{@dossier.france_connect_information.family_name}, authentifié par France Connect le #{@dossier.france_connect_information.updated_at.strftime('%d/%m/%Y')}") end - format_in_2_columns(pdf, "Email", @dossier.user.email) + format_in_2_columns(pdf, "Email", @dossier.user_email_for(:display)) if @dossier.individual.present? add_identite_individual(pdf, @dossier.individual) diff --git a/app/views/experts/avis/procedure.html.haml b/app/views/experts/avis/procedure.html.haml index fc79795d2..8abe0f3d4 100644 --- a/app/views/experts/avis/procedure.html.haml +++ b/app/views/experts/avis/procedure.html.haml @@ -38,7 +38,7 @@ = link_to(instructeur_avis_path(avis.procedure, avis), class: 'cell-link') do %span.icon.folder #{avis.dossier.id} - %td= link_to(avis.dossier.user.email, instructeur_avis_path(avis.procedure, avis), class: 'cell-link') + %td= link_to(avis.dossier.user_email_for(:display), instructeur_avis_path(avis.procedure, avis), class: 'cell-link') %td= link_to(avis.procedure.libelle, instructeur_avis_path(avis.procedure, avis), class: 'cell-link') = paginate(@avis) - else diff --git a/app/views/instructeurs/avis/procedure.html.haml b/app/views/instructeurs/avis/procedure.html.haml index f38d6cde3..1505eef58 100644 --- a/app/views/instructeurs/avis/procedure.html.haml +++ b/app/views/instructeurs/avis/procedure.html.haml @@ -38,7 +38,7 @@ = link_to(instructeur_avis_path(avis.procedure, avis), class: 'cell-link') do %span.icon.folder #{avis.dossier.id} - %td= link_to(avis.dossier.user.email, instructeur_avis_path(avis.procedure, avis), class: 'cell-link') + %td= link_to(avis.dossier.user_email_for(:display), instructeur_avis_path(avis.procedure, avis), class: 'cell-link') %td= link_to(avis.procedure.libelle, instructeur_avis_path(avis.procedure, avis), class: 'cell-link') = paginate(@avis) - else diff --git a/app/views/instructeurs/dossiers/_header_actions.html.haml b/app/views/instructeurs/dossiers/_header_actions.html.haml index 9a5e871ea..ca50a1164 100644 --- a/app/views/instructeurs/dossiers/_header_actions.html.haml +++ b/app/views/instructeurs/dossiers/_header_actions.html.haml @@ -12,16 +12,15 @@ %li = link_to "Export GeoJSON", geo_data_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link" -- if PiecesJustificativesService.liste_pieces_justificatives(dossier).present? - %span.dropdown.print-menu-opener - %button.button.dropdown-button.icon-only{ 'aria-expanded' => 'false', 'aria-controls' => 'print-pj-menu' } - %span.icon.attached - %ul#print-pj-menu.print-menu.dropdown-content - %li - - if PiecesJustificativesService.pieces_justificatives_total_size(dossier) < Dossier::TAILLE_MAX_ZIP - = link_to "Télécharger le dossier et toutes ses pièces jointes", telecharger_pjs_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link" - - else - %p.menu-item Le téléchargement des pièces jointes est désactivé pour les dossiers de plus de #{number_to_human_size Dossier::TAILLE_MAX_ZIP}. +%span.dropdown.print-menu-opener + %button.button.dropdown-button.icon-only{ 'aria-expanded' => 'false', 'aria-controls' => 'print-pj-menu' } + %span.icon.attached + %ul#print-pj-menu.print-menu.dropdown-content + %li + - if dossier.export_and_attachments_downloadable? + = link_to "Télécharger le dossier et toutes ses pièces jointes", telecharger_pjs_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link" + - else + %p.menu-item Le téléchargement des pièces jointes est désactivé pour les dossiers de plus de #{number_to_human_size Dossier::TAILLE_MAX_ZIP}. = render partial: "instructeurs/procedures/dossier_actions", locals: { procedure_id: dossier.procedure.id, diff --git a/app/views/instructeurs/dossiers/_state_button.html.haml b/app/views/instructeurs/dossiers/_state_button.html.haml index 2b4d5851c..3d7b8e7bc 100644 --- a/app/views/instructeurs/dossiers/_state_button.html.haml +++ b/app/views/instructeurs/dossiers/_state_button.html.haml @@ -99,17 +99,24 @@ %h4 Voir l’attestation %p Cette attestation a été envoyée automatiquement au demandeur. - %li - = link_to repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Voulez vous remettre le dossier #{dossier.id} en instruction ?" } do - %span.icon.in-progress - .dropdown-description - %h4 Repasser en instruction - L’usager sera notifié que son dossier est réexaminé. - - if dossier.termine? + - if dossier.can_repasser_en_instruction? %li - = link_to supprimer_dossier_instructeur_dossier_path(dossier.procedure, dossier), method: :patch, data: { confirm: "Voulez vous vraiment supprimer le dossier #{dossier.id} ? Cette action est irréversible. \nNous vous suggérons de télécharger le dossier au format PDF au préalable." } do - %span.icon.delete + = link_to repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Voulez vous remettre le dossier #{dossier.id} en instruction ?" } do + %span.icon.in-progress .dropdown-description - %h4 Supprimer le dossier - L’usager sera notifié que son dossier est supprimé. + %h4 Repasser en instruction + L’usager sera notifié que son dossier est réexaminé. + - elsif dossier.user_deleted? + %li + %span.icon.info + .dropdown-description + %h4 En attente d‘archivage + L'usager a supprimé son compte. Vous pouvez archiver puis supprimer le dossier. + + %li + = link_to supprimer_dossier_instructeur_dossier_path(dossier.procedure, dossier), method: :patch, data: { confirm: "Voulez vous vraiment supprimer le dossier #{dossier.id} ? Cette action est irréversible. \nNous vous suggérons de télécharger le dossier au format PDF au préalable." } do + %span.icon.delete + .dropdown-description + %h4 Supprimer le dossier + L’usager sera notifié que son dossier est supprimé. diff --git a/app/views/instructeurs/recherche/index.html.haml b/app/views/instructeurs/recherche/index.html.haml index 7c7c3ce89..b08a849b5 100644 --- a/app/views/instructeurs/recherche/index.html.haml +++ b/app/views/instructeurs/recherche/index.html.haml @@ -27,7 +27,7 @@ = link_to(dossier_linked_path(current_instructeur, dossier), class: 'cell-link') do = dossier.id %td= link_to(dossier.procedure.libelle, dossier_linked_path(current_instructeur, dossier), class: 'cell-link') - %td= link_to(dossier.user.email, dossier_linked_path(current_instructeur, dossier), class: 'cell-link') + %td= link_to(dossier.user_email_for(:display), dossier_linked_path(current_instructeur, dossier), class: 'cell-link') %td.status-col = link_to(dossier_linked_path(current_instructeur, dossier), class: 'cell-link') do = status_badge(dossier.state) diff --git a/db/migrate/20210419100831_add_deleted_user_email_never_send_to_dossiers.rb b/db/migrate/20210419100831_add_deleted_user_email_never_send_to_dossiers.rb new file mode 100644 index 000000000..8238f3e9c --- /dev/null +++ b/db/migrate/20210419100831_add_deleted_user_email_never_send_to_dossiers.rb @@ -0,0 +1,5 @@ +class AddDeletedUserEmailNeverSendToDossiers < ActiveRecord::Migration[6.1] + def change + add_column :dossiers, :deleted_user_email_never_send, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index eefe0112f..c33baa8f5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_04_27_124500) do +ActiveRecord::Schema.define(version: 2021_04_28_114228) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -274,6 +274,7 @@ ActiveRecord::Schema.define(version: 2021_04_27_124500) do t.datetime "last_avis_updated_at" t.datetime "last_commentaire_updated_at" t.string "api_entreprise_job_exceptions", array: true + t.string "deleted_user_email_never_send" t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin t.index ["archived"], name: "index_dossiers_on_archived" diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index ab6d9ff5a..1521c7dd3 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -210,7 +210,7 @@ describe Instructeurs::DossiersController, type: :controller do end it 'Notification email is sent' do - expect(NotificationMailer).to receive(:send_refused_notification) + expect(NotificationMailer).to receive(:send_refuse_notification) .with(dossier).and_return(NotificationMailer) expect(NotificationMailer).to receive(:deliver_later) @@ -250,7 +250,7 @@ describe Instructeurs::DossiersController, type: :controller do end it 'Notification email is sent' do - expect(NotificationMailer).to receive(:send_without_continuation_notification) + expect(NotificationMailer).to receive(:send_sans_suite_notification) .with(dossier).and_return(NotificationMailer) expect(NotificationMailer).to receive(:deliver_later) @@ -280,7 +280,7 @@ describe Instructeurs::DossiersController, type: :controller do dossier.passer_en_instruction!(instructeur) sign_in(instructeur.user) - expect(NotificationMailer).to receive(:send_closed_notification) + expect(NotificationMailer).to receive(:send_accepte_notification) .with(dossier) .and_return(NotificationMailer) diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index d69c83670..fd3a0c73d 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -476,12 +476,12 @@ describe Users::DossiersController, type: :controller do delivery = double expect(delivery).to receive(:deliver_later).with(no_args) - expect(NotificationMailer).to receive(:send_initiated_notification) + expect(NotificationMailer).to receive(:send_en_construction_notification) .and_return(delivery) subject - expect(NotificationMailer).not_to receive(:send_initiated_notification) + expect(NotificationMailer).not_to receive(:send_en_construction_notification) subject end @@ -499,7 +499,7 @@ describe Users::DossiersController, type: :controller do it { expect(flash.alert).to eq(['nop']) } it 'does not send an email' do - expect(NotificationMailer).not_to receive(:send_initiated_notification) + expect(NotificationMailer).not_to receive(:send_en_construction_notification) subject end @@ -687,7 +687,7 @@ describe Users::DossiersController, type: :controller do end it 'does not send an email' do - expect(NotificationMailer).not_to receive(:send_initiated_notification) + expect(NotificationMailer).not_to receive(:send_en_construction_notification) subject end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index 667fc4eaf..95e66b4db 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -1,19 +1,21 @@ RSpec.describe NotificationMailer, type: :mailer do + let(:administrateur) { create(:administrateur) } let(:user) { create(:user) } let(:procedure) { create(:simple_procedure) } - let(:dossier) { create(:dossier, :en_construction, :with_individual, :with_service, user: user, procedure: procedure) } - describe '.send_dossier_received' do + describe 'send_en_instruction_notification' do + let(:dossier) { create(:dossier, :en_construction, :with_individual, :with_service, user: user, procedure: procedure) } let(:email_template) { create(:received_mail, subject: 'Email subject', body: 'Your dossier was processed. Thanks.') } before do dossier.procedure.received_mail = email_template end - subject(:mail) { described_class.send_dossier_received(dossier) } + subject(:mail) { described_class.send_en_instruction_notification(dossier) } it 'creates a commentaire in the messagerie' do expect { subject.deliver_now }.to change { Commentaire.count }.by(1) + expect(subject.perform_deliveries).to be_truthy commentaire = Commentaire.last expect(commentaire.body).to include(email_template.subject_for_dossier(dossier), email_template.body_for_dossier(dossier)) @@ -59,4 +61,27 @@ RSpec.describe NotificationMailer, type: :mailer do expect(subject.from.first).to eq(Mail::Address.new(NO_REPLY_EMAIL).address) end end + + describe 'send_accepte_notification' do + let(:dossier) { create(:dossier, :en_instruction, :with_individual, :with_service, user: user, procedure: procedure) } + let(:email_template) { create(:closed_mail, subject: 'Email subject', body: 'Your dossier was accepted. Thanks.') } + + before do + dossier.procedure.closed_mail = email_template + end + + subject(:mail) { described_class.send_accepte_notification(dossier) } + + context 'when dossier user is deleted' do + before do + dossier.user.delete_and_keep_track_dossiers(administrateur) + dossier.reload + end + + it 'should not send notification' do + expect { subject.deliver_now }.not_to change { Commentaire.count } + expect(subject.perform_deliveries).to be_falsey + end + end + end end diff --git a/spec/mailers/previews/notification_mailer_preview.rb b/spec/mailers/previews/notification_mailer_preview.rb index dff8bbed9..8d7dbf075 100644 --- a/spec/mailers/previews/notification_mailer_preview.rb +++ b/spec/mailers/previews/notification_mailer_preview.rb @@ -1,23 +1,36 @@ class NotificationMailerPreview < ActionMailer::Preview - def send_initiated_notification - p = Procedure.where(id: Mails::InitiatedMail.where("body like ?", "%