From 7930bf8bf6155fd83f7b49fa6c67d92ee16aa1f6 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 12 Feb 2020 17:41:04 +0100 Subject: [PATCH 01/26] Add en_construction_close_to_expiration_notice_sent_at column --- ...36_add_en_construction_close_to_expiration_to_dossiers.rb | 5 +++++ db/schema.rb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20191211153436_add_en_construction_close_to_expiration_to_dossiers.rb diff --git a/db/migrate/20191211153436_add_en_construction_close_to_expiration_to_dossiers.rb b/db/migrate/20191211153436_add_en_construction_close_to_expiration_to_dossiers.rb new file mode 100644 index 000000000..4fba9525d --- /dev/null +++ b/db/migrate/20191211153436_add_en_construction_close_to_expiration_to_dossiers.rb @@ -0,0 +1,5 @@ +class AddEnConstructionCloseToExpirationToDossiers < ActiveRecord::Migration[5.2] + def change + add_column :dossiers, :en_construction_close_to_expiration_notice_sent_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index fe75b1601..46388538c 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: 2020_03_04_155418) do +ActiveRecord::Schema.define(version: 2020_03_05_155418) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -253,6 +253,7 @@ ActiveRecord::Schema.define(version: 2020_03_04_155418) do 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.datetime "groupe_instructeur_updated_at" + t.datetime "en_construction_close_to_expiration_notice_sent_at" t.index ["archived"], name: "index_dossiers_on_archived" t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id" t.index ["hidden_at"], name: "index_dossiers_on_hidden_at" From f35ccc9d92f849c3f016f4247b6023e06a0f135f Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 26 Feb 2020 17:28:39 +0100 Subject: [PATCH 02/26] Move process_expired_dossiers_brouillon to a service --- app/models/dossier.rb | 32 ----------- .../expired_dossiers_deletion_service.rb | 54 +++++++++++++++++++ spec/models/dossier_spec.rb | 54 ------------------- .../expired_dossiers_deletion_service_spec.rb | 43 +++++++++++++++ 4 files changed, 97 insertions(+), 86 deletions(-) create mode 100644 app/services/expired_dossiers_deletion_service.rb create mode 100644 spec/services/expired_dossiers_deletion_service_spec.rb diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 8e3734e5b..70ecc58f7 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -669,36 +669,4 @@ class Dossier < ApplicationRecord end end end - - def self.send_brouillon_expiration_notices - brouillons = Dossier - .brouillon_close_to_expiration - .without_notice_sent - - brouillons - .includes(:user) - .group_by(&:user) - .each do |(user, dossiers)| - DossierMailer.notify_brouillon_near_deletion(user, dossiers).deliver_later - end - - brouillons.update_all(brouillon_close_to_expiration_notice_sent_at: Time.zone.now) - end - - def self.destroy_brouillons_and_notify - expired_brouillons = Dossier.expired_brouillon - - expired_brouillons - .includes(:procedure, :user) - .group_by(&:user) - .each do |(user, dossiers)| - dossier_hashes = dossiers.map(&:hash_for_deletion_mail) - DossierMailer.notify_brouillon_deletion(user, dossier_hashes).deliver_later - - dossiers.each do |dossier| - DeletedDossier.create_from_dossier(dossier) - dossier.destroy - end - end - end end diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb new file mode 100644 index 000000000..fa5efd9f7 --- /dev/null +++ b/app/services/expired_dossiers_deletion_service.rb @@ -0,0 +1,54 @@ +class ExpiredDossiersDeletionService + def self.process_expired_dossiers_brouillon + send_brouillon_expiration_notices + delete_expired_brouillons_and_notify + end + + private + + def self.send_brouillon_expiration_notices + dossiers_close_to_expiration = Dossier.brouillon_close_to_expiration + .without_brouillon_expiration_notice_sent + + users_to_notify = {} + + dossiers_close_to_expiration + .includes(:user, :procedure) + .find_each do |dossier| + users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] + users_to_notify[dossier.user.email].last.add(dossier) + end + + users_to_notify.each_value do |(user, dossiers)| + DossierMailer.notify_brouillon_near_deletion(user, dossiers).deliver_later + end + + dossiers_close_to_expiration.update_all(brouillon_close_to_expiration_notice_sent_at: Time.zone.now) + end + + def self.delete_expired_brouillons_and_notify + dossier_to_remove = [] + users_to_notify = {} + + Dossier.brouillon_expired + .includes(:user, :procedure) + .find_each do |dossier| + dossier_to_remove << dossier + + users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] + users_to_notify[dossier.user.email].last.add(dossier) + end + + users_to_notify.each_value do |(user, dossiers)| + DossierMailer.notify_brouillon_deletion( + user, + dossiers.map(&:hash_for_deletion_mail) + ).deliver_later + end + + dossier_to_remove.each do |dossier| + DeletedDossier.create_from_dossier(dossier) + dossier.destroy + end + end +end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index f1cad93d2..7cb71f88b 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -1072,60 +1072,6 @@ describe Dossier do it { expect(Dossier.for_procedure(procedure_2)).to contain_exactly(dossier_2_1) } end - describe '#send_brouillon_expiration_notices' do - before { Timecop.freeze(Time.zone.parse('12/12/2012 15:00:00')) } - - let!(:procedure) { create(:procedure, duree_conservation_dossiers_dans_ds: 6) } - let!(:date_close_to_expiration) { Time.zone.now - procedure.duree_conservation_dossiers_dans_ds.months + 1.month } - let!(:date_expired) { Time.zone.now - procedure.duree_conservation_dossiers_dans_ds.months - 6.days } - let!(:date_not_expired) { Time.zone.now - procedure.duree_conservation_dossiers_dans_ds.months + 2.months } - - after { Timecop.return } - - context "Envoi de message pour les dossiers expirant dans - d'un mois" do - let!(:expired_brouillon) { create(:dossier, procedure: procedure, created_at: date_expired) } - let!(:brouillon_close_to_expiration) { create(:dossier, procedure: procedure, created_at: date_close_to_expiration) } - let!(:brouillon_close_but_with_notice_sent) { create(:dossier, procedure: procedure, created_at: date_close_to_expiration, brouillon_close_to_expiration_notice_sent_at: Time.zone.now) } - let!(:valid_brouillon) { create(:dossier, procedure: procedure, created_at: date_not_expired) } - - before do - allow(DossierMailer).to receive(:notify_brouillon_near_deletion).and_return(double(deliver_later: nil)) - Dossier.send_brouillon_expiration_notices - end - - it 'verification de la creation de mail' do - expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(brouillon_close_to_expiration.user, [brouillon_close_to_expiration]) - expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(expired_brouillon.user, [expired_brouillon]) - end - - it 'Verification du changement d etat du champ' do - expect(brouillon_close_to_expiration.reload.brouillon_close_to_expiration_notice_sent_at).not_to be_nil - end - end - end - - describe '#destroy_brouillons_and_notify' do - let!(:today) { Time.zone.now.at_midnight } - - let!(:expired_brouillon) { create(:dossier, brouillon_close_to_expiration_notice_sent_at: today - (Dossier::DRAFT_EXPIRATION + 1.day)) } - let!(:other_brouillon) { create(:dossier, brouillon_close_to_expiration_notice_sent_at: today - (Dossier::DRAFT_EXPIRATION - 1.day)) } - - before do - allow(DossierMailer).to receive(:notify_brouillon_deletion).and_return(double(deliver_later: nil)) - Dossier.destroy_brouillons_and_notify - end - - it 'notifies deletion' do - expect(DossierMailer).to have_received(:notify_brouillon_deletion).once - expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(expired_brouillon.user, [expired_brouillon.hash_for_deletion_mail]) - end - - it 'deletes the expired brouillon' do - expect(DeletedDossier.find_by(dossier_id: expired_brouillon.id)).to be_present - expect { expired_brouillon.reload }.to raise_error(ActiveRecord::RecordNotFound) - end - end - describe '#geo_position' do let(:lat) { "46.538192" } let(:lon) { "2.428462" } diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb new file mode 100644 index 000000000..1f7fc1f1d --- /dev/null +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe ExpiredDossiersDeletionService do + describe '#process_expired_dossiers_brouillon' do + let(:draft_expiration) { 1.month + 5.days } + let!(:today) { Time.zone.now.at_midnight } + let!(:procedure) { create(:procedure, duree_conservation_dossiers_dans_ds: 6) } + let!(:date_close_to_expiration) { Date.today - procedure.duree_conservation_dossiers_dans_ds.months + 1.month } + let!(:date_expired) { Date.today - procedure.duree_conservation_dossiers_dans_ds.months - 6.days } + let!(:date_not_expired) { Date.today - procedure.duree_conservation_dossiers_dans_ds.months + 2.months } + + context 'send messages for dossiers expiring soon and delete expired' do + let!(:expired_brouillon) { create(:dossier, procedure: procedure, created_at: date_expired, brouillon_close_to_expiration_notice_sent_at: today - (draft_expiration + 1.day)) } + let!(:brouillon_close_to_expiration) { create(:dossier, procedure: procedure, created_at: date_close_to_expiration) } + let!(:brouillon_close_but_with_notice_sent) { create(:dossier, procedure: procedure, created_at: date_close_to_expiration, brouillon_close_to_expiration_notice_sent_at: Time.zone.now) } + let!(:valid_brouillon) { create(:dossier, procedure: procedure, created_at: date_not_expired) } + + before do + allow(DossierMailer).to receive(:notify_brouillon_near_deletion).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_brouillon_deletion).and_return(double(deliver_later: nil)) + + ExpiredDossiersDeletionService.process_expired_dossiers_brouillon + end + + it 'emails should be sent' do + expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).once + expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(brouillon_close_to_expiration.user, [brouillon_close_to_expiration]) + end + + it 'dossier state should change' do + expect(brouillon_close_to_expiration.reload.brouillon_close_to_expiration_notice_sent_at).not_to be_nil + end + + it 'deletes and notify expired brouillon' do + expect(DossierMailer).to have_received(:notify_brouillon_deletion).once + expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(expired_brouillon.user, [expired_brouillon.hash_for_deletion_mail]) + + expect(DeletedDossier.find_by(dossier_id: expired_brouillon.id)).to be_present + expect { expired_brouillon.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + end +end From 77018b9e2bf2e41acd551d27834e3a0c4f9b81ba Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 26 Feb 2020 17:36:24 +0100 Subject: [PATCH 03/26] Add expiration scopes to dossier --- app/models/dossier.rb | 23 +++++++++++---- spec/models/dossier_spec.rb | 57 ++++++++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 70ecc58f7..f0eef0d1d 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -22,8 +22,6 @@ class Dossier < ApplicationRecord TAILLE_MAX_ZIP = 50.megabytes - DRAFT_EXPIRATION = 1.month + 5.days - has_one :etablissement, dependent: :destroy has_one :individual, validate: false, dependent: :destroy has_one :attestation, dependent: :destroy @@ -140,7 +138,6 @@ class Dossier < ApplicationRecord scope :en_cours, -> { not_archived.state_en_construction_ou_instruction } scope :without_followers, -> { left_outer_joins(:follows).where(follows: { id: nil }) } scope :with_champs, -> { includes(champs: :type_de_champ) } - scope :nearing_end_of_retention, -> (duration = '1 month') { joins(:procedure).where("en_instruction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - now() < interval ?", duration) } scope :for_api, -> { includes(commentaires: { piece_jointe_attachment: :blob }, champs: [ @@ -170,10 +167,24 @@ class Dossier < ApplicationRecord scope :brouillon_close_to_expiration, -> do brouillon .joins(:procedure) - .where("dossiers.created_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - (1 * interval '1 month') <= now()") + .where("dossiers.created_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - INTERVAL '1 month' <= now()") end - scope :expired_brouillon, -> { brouillon.where("brouillon_close_to_expiration_notice_sent_at < ?", (Time.zone.now - (DRAFT_EXPIRATION))) } - scope :without_notice_sent, -> { where(brouillon_close_to_expiration_notice_sent_at: nil) } + scope :en_construction_close_to_expiration, -> do + en_construction + .joins(:procedure) + .where("dossiers.en_construction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - INTERVAL '1 month' <= now()") + end + scope :en_instruction_close_to_expiration, -> do + en_instruction + .joins(:procedure) + .where("dossiers.en_instruction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - INTERVAL '1 month' <= now()") + end + + scope :brouillon_expired, -> { brouillon.where("brouillon_close_to_expiration_notice_sent_at < (now() - INTERVAL '1 month 5 days')") } + scope :en_construction_expired, -> { en_construction.where("en_construction_close_to_expiration_notice_sent_at < (now() - INTERVAL '1 month 5 days')") } + + 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 :for_procedure, -> (procedure) { includes(:user, :groupe_instructeur).where(groupe_instructeurs: { procedure: procedure }) } scope :for_api_v2, -> { includes(procedure: [:administrateurs], etablissement: [], individual: []) } diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 7cb71f88b..b620ad968 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -45,29 +45,54 @@ describe Dossier do end end - describe 'nearing_end_of_retention' do + describe 'brouillon_close_to_expiration' do + let(:procedure) { create(:procedure, duree_conservation_dossiers_dans_ds: 6) } + let!(:young_dossier) { create(:dossier, :en_construction, procedure: procedure) } + let!(:expiring_dossier) { create(:dossier, created_at: 170.days.ago, procedure: procedure) } + let!(:just_expired_dossier) { create(:dossier, created_at: (6.months + 1.hour + 10.seconds).ago, procedure: procedure) } + let!(:long_expired_dossier) { create(:dossier, created_at: 1.year.ago, procedure: procedure) } + + subject { Dossier.brouillon_close_to_expiration } + + it do + is_expected.not_to include(young_dossier) + is_expected.to include(expiring_dossier) + is_expected.to include(just_expired_dossier) + is_expected.to include(long_expired_dossier) + end + end + + describe 'en_construction_close_to_expiration' do + let(:procedure) { create(:procedure, duree_conservation_dossiers_dans_ds: 6) } + let!(:young_dossier) { create(:dossier, procedure: procedure) } + let!(:expiring_dossier) { create(:dossier, :en_construction, en_construction_at: 170.days.ago, procedure: procedure) } + let!(:just_expired_dossier) { create(:dossier, :en_construction, en_construction_at: (6.months + 1.hour + 10.seconds).ago, procedure: procedure) } + let!(:long_expired_dossier) { create(:dossier, :en_construction, en_construction_at: 1.year.ago, procedure: procedure) } + + subject { Dossier.en_construction_close_to_expiration } + + it do + is_expected.not_to include(young_dossier) + is_expected.to include(expiring_dossier) + is_expected.to include(just_expired_dossier) + is_expected.to include(long_expired_dossier) + end + end + + describe 'en_instruction_close_to_expiration' do let(:procedure) { create(:procedure, duree_conservation_dossiers_dans_ds: 6) } let!(:young_dossier) { create(:dossier, procedure: procedure) } let!(:expiring_dossier) { create(:dossier, :en_instruction, en_instruction_at: 170.days.ago, procedure: procedure) } let!(:just_expired_dossier) { create(:dossier, :en_instruction, en_instruction_at: (6.months + 1.hour + 10.seconds).ago, procedure: procedure) } let!(:long_expired_dossier) { create(:dossier, :en_instruction, en_instruction_at: 1.year.ago, procedure: procedure) } - context 'with default delay to end of retention' do - subject { Dossier.nearing_end_of_retention } + subject { Dossier.en_instruction_close_to_expiration } - it { is_expected.not_to include(young_dossier) } - it { is_expected.to include(expiring_dossier) } - it { is_expected.to include(just_expired_dossier) } - it { is_expected.to include(long_expired_dossier) } - end - - context 'with custom delay to end of retention' do - subject { Dossier.nearing_end_of_retention('0') } - - it { is_expected.not_to include(young_dossier) } - it { is_expected.not_to include(expiring_dossier) } - it { is_expected.to include(just_expired_dossier) } - it { is_expected.to include(long_expired_dossier) } + it do + is_expected.not_to include(young_dossier) + is_expected.to include(expiring_dossier) + is_expected.to include(just_expired_dossier) + is_expected.to include(long_expired_dossier) end end From 6a5a83d5558f12db0aa3145c442b33a0d46fa589 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 26 Feb 2020 17:43:37 +0100 Subject: [PATCH 04/26] update WarnExpiringDossiersJob to use new scope --- app/jobs/warn_expiring_dossiers_job.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/jobs/warn_expiring_dossiers_job.rb b/app/jobs/warn_expiring_dossiers_job.rb index c20789133..b8926662d 100644 --- a/app/jobs/warn_expiring_dossiers_job.rb +++ b/app/jobs/warn_expiring_dossiers_job.rb @@ -3,8 +3,7 @@ class WarnExpiringDossiersJob < ApplicationJob def perform(*args) expiring, expired = Dossier - .includes(:procedure) - .nearing_end_of_retention + .en_instruction_close_to_expiration .partition(&:retention_expired?) AdministrationMailer.dossier_expiration_summary(expiring, expired).deliver_later From 85580ce34ee58a4e0187ec558fdbc91432cea363 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 26 Feb 2020 17:44:06 +0100 Subject: [PATCH 05/26] rename SeekAndDestroyExpiredDossiersJob to ExpiredDossiersDeletionJob --- app/jobs/expired_dossiers_deletion_job.rb | 7 +++++++ app/jobs/seek_and_destroy_expired_dossiers_job.rb | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 app/jobs/expired_dossiers_deletion_job.rb delete mode 100644 app/jobs/seek_and_destroy_expired_dossiers_job.rb diff --git a/app/jobs/expired_dossiers_deletion_job.rb b/app/jobs/expired_dossiers_deletion_job.rb new file mode 100644 index 000000000..65e478192 --- /dev/null +++ b/app/jobs/expired_dossiers_deletion_job.rb @@ -0,0 +1,7 @@ +class ExpiredDossiersDeletionJob < ApplicationJob + queue_as :cron + + def perform(*args) + ExpiredDossiersDeletionService.process_dossiers_brouillon + end +end diff --git a/app/jobs/seek_and_destroy_expired_dossiers_job.rb b/app/jobs/seek_and_destroy_expired_dossiers_job.rb deleted file mode 100644 index d720873bf..000000000 --- a/app/jobs/seek_and_destroy_expired_dossiers_job.rb +++ /dev/null @@ -1,8 +0,0 @@ -class SeekAndDestroyExpiredDossiersJob < ApplicationJob - queue_as :cron - - def perform(*args) - Dossier.send_brouillon_expiration_notices - Dossier.destroy_brouillons_and_notify - end -end From fe1cd2a47b9781df79efc756a364864e9eefd792 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 26 Feb 2020 17:45:17 +0100 Subject: [PATCH 06/26] Delete and notify en_construction dossiers --- .../expired_dossiers_deletion_service.rb | 82 +++++++++++++++++++ .../expired_dossiers_deletion_service_spec.rb | 57 +++++++++++++ 2 files changed, 139 insertions(+) diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb index fa5efd9f7..dbf90af69 100644 --- a/app/services/expired_dossiers_deletion_service.rb +++ b/app/services/expired_dossiers_deletion_service.rb @@ -4,6 +4,11 @@ class ExpiredDossiersDeletionService delete_expired_brouillons_and_notify end + def self.process_expired_dossiers_en_construction + send_en_construction_expiration_notices + delete_expired_en_construction_and_notify + end + private def self.send_brouillon_expiration_notices @@ -26,6 +31,44 @@ class ExpiredDossiersDeletionService dossiers_close_to_expiration.update_all(brouillon_close_to_expiration_notice_sent_at: Time.zone.now) end + def self.send_en_construction_expiration_notices + dossiers_close_to_expiration = Dossier.en_construction_close_to_expiration + .without_en_construction_expiration_notice_sent + + users_to_notify = {} + administrations_to_notify = {} + + dossiers_close_to_expiration + .includes(:user, :followers_instructeurs, procedure: [:administrateurs]) + .find_each do |dossier| + users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] + users_to_notify[dossier.user.email].last.add(dossier) + + (dossier.followers_instructeurs + dossier.procedure.administrateurs).each do |destinataire| + administrations_to_notify[destinataire.email] ||= [destinataire, Set.new] + administrations_to_notify[destinataire.email].last.add(dossier) + end + end + + users_to_notify.each_value do |(user, dossiers)| + DossierMailer.notify_en_construction_near_deletion( + user, + dossiers, + true + ).deliver_later + end + + administrations_to_notify.each_value do |(destinataire, dossiers)| + DossierMailer.notify_en_construction_near_deletion( + destinataire, + dossiers, + false + ).deliver_later + end + + dossiers_close_to_expiration.update_all(en_construction_close_to_expiration_notice_sent_at: Time.zone.now) + end + def self.delete_expired_brouillons_and_notify dossier_to_remove = [] users_to_notify = {} @@ -51,4 +94,43 @@ class ExpiredDossiersDeletionService dossier.destroy end end + + def self.delete_expired_en_construction_and_notify + dossier_to_remove = [] + users_to_notify = {} + administrations_to_notify = {} + + Dossier.en_construction_expired + .includes(:user, :followers_instructeurs, procedure: [:administrateurs]) + .find_each do |dossier| + dossier_to_remove << dossier + + users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] + users_to_notify[dossier.user.email].last.add(dossier) + + (dossier.followers_instructeurs + dossier.procedure.administrateurs).each do |destinataire| + administrations_to_notify[destinataire.email] ||= [destinataire, Set.new] + administrations_to_notify[destinataire.email].last.add(dossier) + end + end + + users_to_notify.each_value do |(user, dossiers)| + DossierMailer.notify_deletion_to_user( + user, + dossiers.map(&:hash_for_deletion_mail) + ).deliver_later + end + + administrations_to_notify.each_value do |(destinataire, dossiers)| + DossierMailer.notify_deletion_to_administration( + destinataire, + dossiers.map(&:hash_for_deletion_mail) + ).deliver_later + end + + dossier_to_remove.each do |dossier| + DeletedDossier.create_from_dossier(dossier) + dossier.destroy + end + end end diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb index 1f7fc1f1d..55dc54af5 100644 --- a/spec/services/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -40,4 +40,61 @@ describe ExpiredDossiersDeletionService do end end end + + describe '#process_expired_dossiers_en_constuction' do + let(:draft_expiration) { 1.month + 5.days } + let!(:today) { Time.zone.now.at_midnight } + let!(:administrateur) { create(:administrateur) } + let!(:procedure1) { create(:procedure, :with_instructeur, duree_conservation_dossiers_dans_ds: 6, administrateur: administrateur) } + let!(:date_near_expiring) { Date.today - procedure1.duree_conservation_dossiers_dans_ds.months + 1.month } + let!(:date_close_to_expiration) { Date.today - procedure1.duree_conservation_dossiers_dans_ds.months - 6.days } + let!(:date_not_expired) { Date.today - procedure1.duree_conservation_dossiers_dans_ds.months + 2.months } + + context 'send messages for dossiers expiring soon and delete expired' do + let!(:expired_en_construction) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_close_to_expiration) } + let!(:en_construction_close_to_expiration) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_near_expiring) } + let!(:en_construction_close_but_with_notice_sent) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_near_expiring, en_construction_close_to_expiration_notice_sent_at: Time.zone.now) } + let!(:en_construction_close_but_with_notice_sent2) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_near_expiring, en_construction_close_to_expiration_notice_sent_at: today - (draft_expiration + 1.day)) } + let!(:valid_en_construction) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_not_expired) } + + before do + allow(DossierMailer).to receive(:notify_en_construction_near_deletion).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_deletion_to_administration).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_deletion_to_user).and_return(double(deliver_later: nil)) + + ExpiredDossiersDeletionService.process_expired_dossiers_en_construction + end + + it 'not expired dossiers should reload' do + expired_en_construction.reload + en_construction_close_to_expiration.reload + en_construction_close_but_with_notice_sent.reload + valid_en_construction.reload + end + + it 'expired dossier should be deleted' do + expect { en_construction_close_but_with_notice_sent2.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + + it 'emails should be sent' do + expect(DossierMailer).to have_received(:notify_deletion_to_user).once + expect(DossierMailer).to have_received(:notify_deletion_to_user).with(en_construction_close_but_with_notice_sent2.user, [en_construction_close_but_with_notice_sent2.hash_for_deletion_mail]) + + expect(DossierMailer).to have_received(:notify_deletion_to_administration).once + expect(DossierMailer).to have_received(:notify_deletion_to_administration).with(administrateur, [en_construction_close_but_with_notice_sent2].map(&:hash_for_deletion_mail)) + + expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).thrice + expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(en_construction_close_to_expiration.user, [en_construction_close_to_expiration], true) + expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(expired_en_construction.user, [expired_en_construction], true) + end + + it 'dossiers soon to expire should be marked' do + expired_en_construction.reload + expect(expired_en_construction.en_construction_close_to_expiration_notice_sent_at).not_to be_nil + + en_construction_close_to_expiration.reload + expect(en_construction_close_to_expiration.en_construction_close_to_expiration_notice_sent_at).not_to be_nil + end + end + end end From 043847ae6ee406235b0bca4bc4ea73b48796cdc0 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 5 Mar 2020 16:41:08 +0100 Subject: [PATCH 07/26] change notify_automatic_deletion_to_administration signature --- app/mailers/dossier_mailer.rb | 12 ++++++------ spec/mailers/dossier_mailer_spec.rb | 8 +++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/mailers/dossier_mailer.rb b/app/mailers/dossier_mailer.rb index c2294ee67..96ae6b1b3 100644 --- a/app/mailers/dossier_mailer.rb +++ b/app/mailers/dossier_mailer.rb @@ -69,26 +69,26 @@ class DossierMailer < ApplicationMailer mail(to: user.email, subject: @subject) end - def notify_automatic_deletion_to_user(user, dossier_hashes) + def notify_automatic_deletion_to_user(email, dossier_hashes) @subject = default_i18n_subject(count: dossier_hashes.count) @dossier_hashes = dossier_hashes - mail(to: user.email, subject: @subject) + mail(to: email, subject: @subject) end - def notify_automatic_deletion_to_administration(user, dossier_hashes) + def notify_automatic_deletion_to_administration(email, dossier_hashes) @subject = default_i18n_subject(count: dossier_hashes.count) @dossier_hashes = dossier_hashes - mail(to: user.email, subject: @subject) + mail(to: email, subject: @subject) end - def notify_en_construction_near_deletion(user, dossiers, for_user) + def notify_en_construction_near_deletion(email, dossiers, for_user) @subject = default_i18n_subject(count: dossiers.count) @dossiers = dossiers @for_user = for_user - mail(to: user.email, subject: @subject) + mail(to: email, subject: @subject) end def notify_groupe_instructeur_changed(instructeur, dossier) diff --git a/spec/mailers/dossier_mailer_spec.rb b/spec/mailers/dossier_mailer_spec.rb index c18b2ebb4..4dec70856 100644 --- a/spec/mailers/dossier_mailer_spec.rb +++ b/spec/mailers/dossier_mailer_spec.rb @@ -104,8 +104,9 @@ RSpec.describe DossierMailer, type: :mailer do @date_suppression = dossier.created_at + duree.months end - subject { described_class.notify_automatic_deletion_to_user(dossier.user, [dossier.hash_for_deletion_mail]) } + subject { described_class.notify_automatic_deletion_to_user(dossier.user.email, [dossier.hash_for_deletion_mail]) } + it { expect(subject.to).to eq([dossier.user.email]) } it { expect(subject.subject).to eq("Un dossier a été supprimé automatiquement") } it { expect(subject.body).to include("n° #{dossier.id} ") } it { expect(subject.body).to include(dossier.procedure.libelle) } @@ -129,7 +130,7 @@ RSpec.describe DossierMailer, type: :mailer do @date_suppression = dossier.created_at + duree.months end - subject { described_class.notify_en_construction_near_deletion(dossier.user, [dossier], true) } + subject { described_class.notify_en_construction_near_deletion(dossier.user.email, [dossier], true) } it { expect(subject.subject).to eq("Un dossier en construction va bientôt être supprimé") } it { expect(subject.body).to include("n° #{dossier.id} ") } @@ -146,8 +147,9 @@ RSpec.describe DossierMailer, type: :mailer do @date_suppression = dossier.created_at + duree.months end - subject { described_class.notify_en_construction_near_deletion(dossier.user, [dossier], false) } + subject { described_class.notify_en_construction_near_deletion(dossier.user.email, [dossier], false) } + it { expect(subject.to).to eq([dossier.user.email]) } it { expect(subject.subject).to eq("Un dossier en construction va bientôt être supprimé") } it { expect(subject.body).to include("n° #{dossier.id} ") } it { expect(subject.body).to include(dossier.procedure.libelle) } From f35c0518b714e244ee9461648efc2cbd0052d9a6 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 4 Mar 2020 17:35:25 +0100 Subject: [PATCH 08/26] test for #delete_expired_en_construction_and_notify --- .../expired_dossiers_deletion_service.rb | 2 - .../expired_dossiers_deletion_service_spec.rb | 68 +++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb index dbf90af69..9bf884b5f 100644 --- a/app/services/expired_dossiers_deletion_service.rb +++ b/app/services/expired_dossiers_deletion_service.rb @@ -9,8 +9,6 @@ class ExpiredDossiersDeletionService delete_expired_en_construction_and_notify end - private - def self.send_brouillon_expiration_notices dossiers_close_to_expiration = Dossier.brouillon_close_to_expiration .without_brouillon_expiration_notice_sent diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb index 55dc54af5..93637f858 100644 --- a/spec/services/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -41,6 +41,74 @@ describe ExpiredDossiersDeletionService do end end + describe '#delete_expired_en_construction_and_notify' do + let!(:warning_period) { 1.month + 5.days } + + before { Timecop.freeze(Time.zone.now) } + after { Timecop.return } + + before do + allow(DossierMailer).to receive(:notify_automatic_deletion_to_user).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_automatic_deletion_to_administration).and_return(double(deliver_later: nil)) + end + + context 'with a single dossier' do + let!(:dossier) { create(:dossier, :en_construction, :followed, en_construction_close_to_expiration_notice_sent_at: notice_sent_at) } + + before { ExpiredDossiersDeletionService.delete_expired_en_construction_and_notify } + + context 'when no notice has been sent' do + let(:notice_sent_at) { nil } + + it { expect { dossier.reload }.not_to raise_error } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_user) } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_administration) } + end + + context 'when a notice has been sent not so long ago' do + let(:notice_sent_at) { (warning_period - 1.day).ago } + + it { expect { dossier.reload }.not_to raise_error } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_user) } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_administration) } + end + + context 'when a notice has been sent a long time ago' do + let(:notice_sent_at) { (warning_period + 1.day).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(dossier.user.email, [dossier.hash_for_deletion_mail]) } + + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).twice } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier.procedure.administrateurs.first.email, [dossier.hash_for_deletion_mail]) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier.followers_instructeurs.first.email, [dossier.hash_for_deletion_mail]) } + end + end + + context 'with 2 dossiers to delete' do + let!(:user) { create(:user) } + let!(:dossier_1) { create(:dossier, :en_construction, user: user, en_construction_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } + let!(:dossier_2) { create(:dossier, :en_construction, user: user, en_construction_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } + + let!(:instructeur) { create(:instructeur) } + + before do + instructeur.followed_dossiers << dossier_1 << dossier_2 + ExpiredDossiersDeletionService.delete_expired_en_construction_and_notify + 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(user.email, match_array([dossier_1, dossier_2].map(&:hash_for_deletion_mail))) } + + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).thrice } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(instructeur.email, match_array([dossier_1, dossier_2].map(&:hash_for_deletion_mail))) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier_1.procedure.administrateurs.first.email, [dossier_1.hash_for_deletion_mail]) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier_2.procedure.administrateurs.first.email, [dossier_2.hash_for_deletion_mail]) } + end + end + describe '#process_expired_dossiers_en_constuction' do let(:draft_expiration) { 1.month + 5.days } let!(:today) { Time.zone.now.at_midnight } From 74db7ab14620c422b192e0e85954f72d9f85ca74 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 4 Mar 2020 18:33:32 +0100 Subject: [PATCH 09/26] test for #send_en_construction_expiration_notices --- .../expired_dossiers_deletion_service_spec.rb | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb index 93637f858..d939c7e04 100644 --- a/spec/services/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -41,6 +41,75 @@ describe ExpiredDossiersDeletionService do end end + describe '#send_en_construction_expiration_notices' do + let!(:conservation_par_defaut) { 3.months } + + before { Timecop.freeze(Time.zone.now) } + after { Timecop.return } + + before do + allow(DossierMailer).to receive(:notify_en_construction_near_deletion).and_return(double(deliver_later: nil)) + end + + context 'with a single dossier' do + let!(:dossier) { create(:dossier, :en_construction, :followed, en_construction_at: en_construction_at) } + + before { ExpiredDossiersDeletionService.send_en_construction_expiration_notices } + + context 'when the dossier is not near deletion' do + let(:en_construction_at) { (conservation_par_defaut - 1.month - 1.day).ago } + + it { expect(dossier.reload.en_construction_close_to_expiration_notice_sent_at).to be_nil } + it { expect(DossierMailer).not_to have_received(:notify_en_construction_near_deletion) } + end + + context 'when the dossier is near deletion' do + let(:en_construction_at) { (conservation_par_defaut - 1.month + 1.day).ago } + + it { expect(dossier.reload.en_construction_close_to_expiration_notice_sent_at).not_to be_nil } + + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).thrice } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.user.email, [dossier], true) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.procedure.administrateurs.first.email, [dossier], false) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.followers_instructeurs.first.email, [dossier], false) } + end + end + + context 'with 2 dossiers to notice' do + let!(:user) { create(:user) } + let!(:dossier_1) { create(:dossier, :en_construction, user: user, en_construction_at: (conservation_par_defaut - 1.month + 1.day).ago) } + let!(:dossier_2) { create(:dossier, :en_construction, user: user, en_construction_at: (conservation_par_defaut - 1.month + 1.day).ago) } + + let!(:instructeur) { create(:instructeur) } + + before do + instructeur.followed_dossiers << dossier_1 << dossier_2 + ExpiredDossiersDeletionService.send_en_construction_expiration_notices + end + + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).exactly(4).times } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(user.email, match_array([dossier_1, dossier_2]), true) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(instructeur.email, match_array([dossier_1, dossier_2]), false) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier_1.procedure.administrateurs.first.email, [dossier_1], false) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier_2.procedure.administrateurs.first.email, [dossier_2], false) } + end + + context 'when an instructeur is also administrateur' do + let!(:procedure) { create(:procedure) } + let!(:administrateur) { procedure.administrateurs.first } + let!(:dossier) { create(:dossier, :en_construction, procedure: procedure, en_construction_at: (conservation_par_defaut - 1.month + 1.day).ago) } + + before do + administrateur.instructeur.followed_dossiers << dossier + ExpiredDossiersDeletionService.send_en_construction_expiration_notices + end + + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).exactly(2).times } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.user.email, [dossier], true) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(administrateur.email, [dossier], false) } + end + end + describe '#delete_expired_en_construction_and_notify' do let!(:warning_period) { 1.month + 5.days } From 3f6012bff5822c30ac8512bdb598fd7b4cfaae93 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 4 Mar 2020 18:35:05 +0100 Subject: [PATCH 10/26] Delete complicated test --- .../expired_dossiers_deletion_service_spec.rb | 57 ------------------- 1 file changed, 57 deletions(-) diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb index d939c7e04..2bd3f53d2 100644 --- a/spec/services/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -177,61 +177,4 @@ describe ExpiredDossiersDeletionService do it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier_2.procedure.administrateurs.first.email, [dossier_2.hash_for_deletion_mail]) } end end - - describe '#process_expired_dossiers_en_constuction' do - let(:draft_expiration) { 1.month + 5.days } - let!(:today) { Time.zone.now.at_midnight } - let!(:administrateur) { create(:administrateur) } - let!(:procedure1) { create(:procedure, :with_instructeur, duree_conservation_dossiers_dans_ds: 6, administrateur: administrateur) } - let!(:date_near_expiring) { Date.today - procedure1.duree_conservation_dossiers_dans_ds.months + 1.month } - let!(:date_close_to_expiration) { Date.today - procedure1.duree_conservation_dossiers_dans_ds.months - 6.days } - let!(:date_not_expired) { Date.today - procedure1.duree_conservation_dossiers_dans_ds.months + 2.months } - - context 'send messages for dossiers expiring soon and delete expired' do - let!(:expired_en_construction) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_close_to_expiration) } - let!(:en_construction_close_to_expiration) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_near_expiring) } - let!(:en_construction_close_but_with_notice_sent) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_near_expiring, en_construction_close_to_expiration_notice_sent_at: Time.zone.now) } - let!(:en_construction_close_but_with_notice_sent2) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_near_expiring, en_construction_close_to_expiration_notice_sent_at: today - (draft_expiration + 1.day)) } - let!(:valid_en_construction) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure1, en_construction_at: date_not_expired) } - - before do - allow(DossierMailer).to receive(:notify_en_construction_near_deletion).and_return(double(deliver_later: nil)) - allow(DossierMailer).to receive(:notify_deletion_to_administration).and_return(double(deliver_later: nil)) - allow(DossierMailer).to receive(:notify_deletion_to_user).and_return(double(deliver_later: nil)) - - ExpiredDossiersDeletionService.process_expired_dossiers_en_construction - end - - it 'not expired dossiers should reload' do - expired_en_construction.reload - en_construction_close_to_expiration.reload - en_construction_close_but_with_notice_sent.reload - valid_en_construction.reload - end - - it 'expired dossier should be deleted' do - expect { en_construction_close_but_with_notice_sent2.reload }.to raise_error(ActiveRecord::RecordNotFound) - end - - it 'emails should be sent' do - expect(DossierMailer).to have_received(:notify_deletion_to_user).once - expect(DossierMailer).to have_received(:notify_deletion_to_user).with(en_construction_close_but_with_notice_sent2.user, [en_construction_close_but_with_notice_sent2.hash_for_deletion_mail]) - - expect(DossierMailer).to have_received(:notify_deletion_to_administration).once - expect(DossierMailer).to have_received(:notify_deletion_to_administration).with(administrateur, [en_construction_close_but_with_notice_sent2].map(&:hash_for_deletion_mail)) - - expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).thrice - expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(en_construction_close_to_expiration.user, [en_construction_close_to_expiration], true) - expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(expired_en_construction.user, [expired_en_construction], true) - end - - it 'dossiers soon to expire should be marked' do - expired_en_construction.reload - expect(expired_en_construction.en_construction_close_to_expiration_notice_sent_at).not_to be_nil - - en_construction_close_to_expiration.reload - expect(en_construction_close_to_expiration.en_construction_close_to_expiration_notice_sent_at).not_to be_nil - end - end - end end From 50bb2e6a08154a640322cb988ad203262dc8361c Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 4 Mar 2020 20:01:01 +0100 Subject: [PATCH 11/26] refacto --- .../expired_dossiers_deletion_service.rb | 80 ++++++++----------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb index 9bf884b5f..b67e2ac00 100644 --- a/app/services/expired_dossiers_deletion_service.rb +++ b/app/services/expired_dossiers_deletion_service.rb @@ -30,33 +30,22 @@ class ExpiredDossiersDeletionService end def self.send_en_construction_expiration_notices - dossiers_close_to_expiration = Dossier.en_construction_close_to_expiration + dossiers_close_to_expiration = Dossier + .en_construction_close_to_expiration .without_en_construction_expiration_notice_sent - users_to_notify = {} - administrations_to_notify = {} - dossiers_close_to_expiration - .includes(:user, :followers_instructeurs, procedure: [:administrateurs]) - .find_each do |dossier| - users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] - users_to_notify[dossier.user.email].last.add(dossier) - - (dossier.followers_instructeurs + dossier.procedure.administrateurs).each do |destinataire| - administrations_to_notify[destinataire.email] ||= [destinataire, Set.new] - administrations_to_notify[destinataire.email].last.add(dossier) - end + .includes(:user) + .group_by(&:user) + .each do |(user, dossiers)| + DossierMailer.notify_en_construction_near_deletion( + user.email, + dossiers, + true + ).deliver_later end - users_to_notify.each_value do |(user, dossiers)| - DossierMailer.notify_en_construction_near_deletion( - user, - dossiers, - true - ).deliver_later - end - - administrations_to_notify.each_value do |(destinataire, dossiers)| + group_by_fonctionnaire_email(dossiers_close_to_expiration).each do |(destinataire, dossiers)| DossierMailer.notify_en_construction_near_deletion( destinataire, dossiers, @@ -94,41 +83,38 @@ class ExpiredDossiersDeletionService end def self.delete_expired_en_construction_and_notify - dossier_to_remove = [] - users_to_notify = {} - administrations_to_notify = {} + dossiers_to_remove = Dossier.en_construction_expired - Dossier.en_construction_expired - .includes(:user, :followers_instructeurs, procedure: [:administrateurs]) - .find_each do |dossier| - dossier_to_remove << dossier - - users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] - users_to_notify[dossier.user.email].last.add(dossier) - - (dossier.followers_instructeurs + dossier.procedure.administrateurs).each do |destinataire| - administrations_to_notify[destinataire.email] ||= [destinataire, Set.new] - administrations_to_notify[destinataire.email].last.add(dossier) - end + dossiers_to_remove + .includes(:user) + .group_by(&:user) + .each do |(user, dossiers)| + DossierMailer.notify_automatic_deletion_to_user( + user.email, + dossiers.map(&:hash_for_deletion_mail) + ).deliver_later end - users_to_notify.each_value do |(user, dossiers)| - DossierMailer.notify_deletion_to_user( - user, - dossiers.map(&:hash_for_deletion_mail) - ).deliver_later - end - - administrations_to_notify.each_value do |(destinataire, dossiers)| - DossierMailer.notify_deletion_to_administration( + self.group_by_fonctionnaire_email(dossiers_to_remove).each do |(destinataire, dossiers)| + DossierMailer.notify_automatic_deletion_to_administration( destinataire, dossiers.map(&:hash_for_deletion_mail) ).deliver_later end - dossier_to_remove.each do |dossier| + dossiers_to_remove.each do |dossier| DeletedDossier.create_from_dossier(dossier) dossier.destroy end end + + private + + def self.group_by_fonctionnaire_email(dossiers) + dossiers + .includes(:followers_instructeurs, procedure: [:administrateurs]) + .each_with_object(Hash.new { |h, k| h[k] = Set.new }) do |dossier, h| + (dossier.followers_instructeurs + dossier.procedure.administrateurs).each { |destinataire| h[destinataire.email] << dossier } + end + end end From 3dd4ea26c7bdd106007e0029626f55479d78d6c3 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 5 Mar 2020 10:17:59 +0100 Subject: [PATCH 12/26] add similar tests for send_brouillon_expiration_notices and delete_expired_brouillon_and_notify --- .../expired_dossiers_deletion_service_spec.rb | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb index 2bd3f53d2..c927755d8 100644 --- a/spec/services/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -41,6 +41,100 @@ describe ExpiredDossiersDeletionService do end end + describe '#send_brouillon_expiration_notices' do + let!(:conservation_par_defaut) { 3.months } + + before { Timecop.freeze(Time.zone.now) } + after { Timecop.return } + + before do + allow(DossierMailer).to receive(:notify_brouillon_near_deletion).and_return(double(deliver_later: nil)) + end + + context 'with a single dossier' do + let!(:dossier) { create(:dossier, created_at: created_at) } + + before { ExpiredDossiersDeletionService.send_brouillon_expiration_notices } + + context 'when the dossier is not closed to expiration' do + let(:created_at) { (conservation_par_defaut - 1.month - 1.day).ago } + + it { expect(dossier.reload.brouillon_close_to_expiration_notice_sent_at).to be_nil } + it { expect(DossierMailer).not_to have_received(:notify_brouillon_near_deletion) } + end + + context 'when the dossier is closed to expiration' do + let(:created_at) { (conservation_par_defaut - 1.month + 1.day).ago } + + it { expect(dossier.reload.brouillon_close_to_expiration_notice_sent_at).not_to be_nil } + it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).once } + it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(dossier.user, [dossier]) } + end + end + + context 'with 2 dossiers to notice' do + let!(:user) { create(:user) } + let!(:dossier_1) { create(:dossier, user: user, created_at: (conservation_par_defaut - 1.month + 1.day).ago) } + let!(:dossier_2) { create(:dossier, user: user, created_at: (conservation_par_defaut - 1.month + 1.day).ago) } + + before { ExpiredDossiersDeletionService.send_brouillon_expiration_notices } + + it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).once } + it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(user, match_array([dossier_1, dossier_2])) } + end + end + + describe '#delete_expired_brouillons_and_notify' do + let!(:warning_period) { 1.month + 5.days } + + before { Timecop.freeze(Time.zone.now) } + after { Timecop.return } + + before do + allow(DossierMailer).to receive(:notify_brouillon_deletion).and_return(double(deliver_later: nil)) + end + + context 'with a single dossier' do + let!(:dossier) { create(:dossier, brouillon_close_to_expiration_notice_sent_at: notice_sent_at) } + + before { ExpiredDossiersDeletionService.delete_expired_brouillons_and_notify } + + context 'when no notice has been sent' do + let(:notice_sent_at) { nil } + + it { expect { dossier.reload }.not_to raise_error } + it { expect(DossierMailer).not_to have_received(:notify_brouillon_deletion) } + end + + context 'when a notice has been sent not so long ago' do + let(:notice_sent_at) { (warning_period - 1.day).ago } + + it { expect { dossier.reload }.not_to raise_error } + it { expect(DossierMailer).not_to have_received(:notify_brouillon_deletion) } + end + + context 'when a notice has been sent a long time ago' do + let(:notice_sent_at) { (warning_period + 1.day).ago } + + it { expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) } + + it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).once } + it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(dossier.user, [dossier.hash_for_deletion_mail]) } + end + end + + context 'with 2 dossiers to delete' do + let!(:user) { create(:user) } + let!(:dossier_1) { create(:dossier, user: user, brouillon_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } + let!(:dossier_2) { create(:dossier, user: user, brouillon_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } + + before { ExpiredDossiersDeletionService.delete_expired_brouillons_and_notify } + + it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).once } + it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(user, match_array([dossier_1, dossier_2].map(&:hash_for_deletion_mail))) } + end + end + describe '#send_en_construction_expiration_notices' do let!(:conservation_par_defaut) { 3.months } From ede61ee22b5a71bdee3ebf6cb146383fbab9833a Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 5 Mar 2020 10:24:15 +0100 Subject: [PATCH 13/26] refacto --- .../expired_dossiers_deletion_service.rb | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb index b67e2ac00..1a7383ca9 100644 --- a/app/services/expired_dossiers_deletion_service.rb +++ b/app/services/expired_dossiers_deletion_service.rb @@ -10,22 +10,17 @@ class ExpiredDossiersDeletionService end def self.send_brouillon_expiration_notices - dossiers_close_to_expiration = Dossier.brouillon_close_to_expiration + dossiers_close_to_expiration = Dossier + .brouillon_close_to_expiration .without_brouillon_expiration_notice_sent - users_to_notify = {} - dossiers_close_to_expiration .includes(:user, :procedure) - .find_each do |dossier| - users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] - users_to_notify[dossier.user.email].last.add(dossier) + .group_by(&:user) + .each do |(user, dossiers)| + DossierMailer.notify_brouillon_near_deletion(user, dossiers).deliver_later end - users_to_notify.each_value do |(user, dossiers)| - DossierMailer.notify_brouillon_near_deletion(user, dossiers).deliver_later - end - dossiers_close_to_expiration.update_all(brouillon_close_to_expiration_notice_sent_at: Time.zone.now) end @@ -57,26 +52,16 @@ class ExpiredDossiersDeletionService end def self.delete_expired_brouillons_and_notify - dossier_to_remove = [] - users_to_notify = {} + dossiers_to_remove = Dossier.brouillon_expired - Dossier.brouillon_expired + dossiers_to_remove .includes(:user, :procedure) - .find_each do |dossier| - dossier_to_remove << dossier - - users_to_notify[dossier.user.email] ||= [dossier.user, Set.new] - users_to_notify[dossier.user.email].last.add(dossier) + .group_by(&:user) + .each do |(user, dossiers)| + DossierMailer.notify_brouillon_deletion(user, dossiers.map(&:hash_for_deletion_mail)).deliver_later end - users_to_notify.each_value do |(user, dossiers)| - DossierMailer.notify_brouillon_deletion( - user, - dossiers.map(&:hash_for_deletion_mail) - ).deliver_later - end - - dossier_to_remove.each do |dossier| + dossiers_to_remove.each do |dossier| DeletedDossier.create_from_dossier(dossier) dossier.destroy end From 3e7cef63c65ee0d60a4c2d73d0fbce1878129b9b Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 5 Mar 2020 17:17:58 +0100 Subject: [PATCH 14/26] add mailer preview --- spec/mailers/previews/dossier_mailer_preview.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/mailers/previews/dossier_mailer_preview.rb b/spec/mailers/previews/dossier_mailer_preview.rb index f1fc2dab7..38c22902f 100644 --- a/spec/mailers/previews/dossier_mailer_preview.rb +++ b/spec/mailers/previews/dossier_mailer_preview.rb @@ -37,6 +37,16 @@ class DossierMailerPreview < ActionMailer::Preview DossierMailer.notify_brouillon_deletion(User.new(email: "usager@example.com"), dossier_hashes) end + def notify_automatic_deletion_to_user + dossier_hashes = [dossier, dossier].map(&:hash_for_deletion_mail) + DossierMailer.notify_automatic_deletion_to_user("usager@example.com", dossier_hashes) + end + + def notify_automatic_deletion_to_administration + dossier_hashes = [dossier, dossier].map(&:hash_for_deletion_mail) + DossierMailer.notify_automatic_deletion_to_administration("admin@example.com", dossier_hashes) + end + private def deleted_dossier From a10aa9602ab083d13dd85075a4a0c6f17eb6288b Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 5 Mar 2020 17:18:07 +0100 Subject: [PATCH 15/26] do not link to deleted dossier --- .../dossier_mailer/notify_automatic_deletion_to_user.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 337151682..213e26009 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 @@ -7,7 +7,7 @@ %ul - @dossier_hashes.each do |d| - %li= link_to("n° #{d[:id]} (#{d[:procedure_libelle]})", dossier_url(d)) + %li= "n° #{d[:id]} (#{d[:procedure_libelle]})" %p= t('.dossier_will_not_be_processed', count: @dossier_hashes.count) From 6b83998e28b91a387aa243908b20c02f08b5b06d Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Thu, 19 Mar 2020 16:34:40 +0100 Subject: [PATCH 16/26] db: fix diff in schema.rb --- db/schema.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 46388538c..a7a596376 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: 2020_03_05_155418) do +ActiveRecord::Schema.define(version: 2020_03_04_155418) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -250,10 +250,10 @@ ActiveRecord::Schema.define(version: 2020_03_05_155418) do t.text "private_search_terms" t.bigint "groupe_instructeur_id" t.datetime "brouillon_close_to_expiration_notice_sent_at" - 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.datetime "groupe_instructeur_updated_at" t.datetime "en_construction_close_to_expiration_notice_sent_at" + 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" t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id" t.index ["hidden_at"], name: "index_dossiers_on_hidden_at" From cd0acb13449214123878b07d3c1f34b304af3b17 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 19 Mar 2020 09:49:25 +0100 Subject: [PATCH 17/26] Cleanup dossier mailers --- app/mailers/dossier_mailer.rb | 64 ++++++++++--------- .../expired_dossiers_deletion_service.rb | 41 ++++++------ ...matic_deletion_to_administration.html.haml | 10 +-- ...otify_automatic_deletion_to_user.html.haml | 12 ++-- .../notify_brouillon_deletion.html.haml | 10 +-- .../notify_brouillon_near_deletion.html.haml | 6 +- ...otify_deletion_to_administration.html.haml | 6 +- .../notify_deletion_to_user.html.haml | 6 +- ...fy_en_construction_near_deletion.html.haml | 27 -------- ..._near_deletion_to_administration.html.haml | 16 +++++ ...nstruction_near_deletion_to_user.html.haml | 16 +++++ .../fr.yml | 2 +- .../notify_automatic_deletion_to_user/fr.yml | 4 +- .../notify_brouillon_deletion/fr.yml | 2 +- .../notify_brouillon_near_deletion/fr.yml | 12 ++-- .../notify_deletion_to_administration/fr.yml | 5 ++ .../notify_deletion_to_user/fr.yml | 5 ++ .../fr.yml | 15 ----- .../fr.yml | 12 ++++ .../fr.yml | 12 ++++ spec/mailers/dossier_mailer_spec.rb | 22 ++++--- .../previews/dossier_mailer_preview.rb | 48 +++++++++----- .../expired_dossiers_deletion_service_spec.rb | 62 ++++++++++-------- 23 files changed, 233 insertions(+), 182 deletions(-) delete mode 100644 app/views/dossier_mailer/notify_en_construction_near_deletion.html.haml create mode 100644 app/views/dossier_mailer/notify_en_construction_near_deletion_to_administration.html.haml create mode 100644 app/views/dossier_mailer/notify_en_construction_near_deletion_to_user.html.haml create mode 100644 config/locales/views/dossier_mailer/notify_deletion_to_administration/fr.yml create mode 100644 config/locales/views/dossier_mailer/notify_deletion_to_user/fr.yml delete mode 100644 config/locales/views/dossier_mailer/notify_en_construction_near_deletion/fr.yml create mode 100644 config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_administration/fr.yml create mode 100644 config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_user/fr.yml diff --git a/app/mailers/dossier_mailer.rb b/app/mailers/dossier_mailer.rb index 96ae6b1b3..b3fcd9a94 100644 --- a/app/mailers/dossier_mailer.rb +++ b/app/mailers/dossier_mailer.rb @@ -29,20 +29,6 @@ class DossierMailer < ApplicationMailer end end - def notify_deletion_to_user(deleted_dossier, to_email) - @deleted_dossier = deleted_dossier - subject = "Votre dossier nº #{@deleted_dossier.dossier_id} a bien été supprimé" - - mail(to: to_email, subject: subject) - end - - def notify_deletion_to_administration(deleted_dossier, to_email) - @deleted_dossier = deleted_dossier - subject = "Le dossier nº #{@deleted_dossier.dossier_id} a été supprimé à la demande de l'usager" - - mail(to: to_email, subject: subject) - end - def notify_revert_to_instruction(dossier) @dossier = dossier @service = dossier.procedure.service @@ -55,40 +41,60 @@ class DossierMailer < ApplicationMailer end end - def notify_brouillon_near_deletion(user, dossiers) + def notify_brouillon_near_deletion(dossiers, to_email) @subject = default_i18n_subject(count: dossiers.count) @dossiers = dossiers - mail(to: user.email, subject: @subject) + mail(to: to_email, subject: @subject) end - def notify_brouillon_deletion(user, dossier_hashes) + def notify_brouillon_deletion(dossier_hashes, to_email) @subject = default_i18n_subject(count: dossier_hashes.count) @dossier_hashes = dossier_hashes - mail(to: user.email, subject: @subject) + mail(to: to_email, subject: @subject) end - def notify_automatic_deletion_to_user(email, dossier_hashes) - @subject = default_i18n_subject(count: dossier_hashes.count) - @dossier_hashes = dossier_hashes + def notify_deletion_to_user(deleted_dossier, to_email) + @subject = default_i18n_subject(dossier_id: deleted_dossier.dossier_id) + @deleted_dossier = deleted_dossier - mail(to: email, subject: @subject) + mail(to: to_email, subject: @subject) end - def notify_automatic_deletion_to_administration(email, dossier_hashes) - @subject = default_i18n_subject(count: dossier_hashes.count) - @dossier_hashes = dossier_hashes + def notify_deletion_to_administration(deleted_dossier, to_email) + @subject = default_i18n_subject(dossier_id: deleted_dossier.dossier_id) + @deleted_dossier = deleted_dossier - mail(to: email, subject: @subject) + mail(to: to_email, subject: @subject) end - def notify_en_construction_near_deletion(email, dossiers, for_user) + def notify_automatic_deletion_to_user(deleted_dossiers, to_email) + @subject = default_i18n_subject(count: deleted_dossiers.count) + @deleted_dossiers = deleted_dossiers + + mail(to: to_email, subject: @subject) + end + + def notify_automatic_deletion_to_administration(deleted_dossiers, to_email) + @subject = default_i18n_subject(count: deleted_dossiers.count) + @deleted_dossiers = deleted_dossiers + + mail(to: to_email, subject: @subject) + end + + def notify_en_construction_near_deletion_to_user(dossiers, to_email) @subject = default_i18n_subject(count: dossiers.count) @dossiers = dossiers - @for_user = for_user - mail(to: email, subject: @subject) + mail(to: to_email, subject: @subject) + end + + def notify_en_construction_near_deletion_to_administration(dossiers, to_email) + @subject = default_i18n_subject(count: dossiers.count) + @dossiers = dossiers + + mail(to: to_email, subject: @subject) end def notify_groupe_instructeur_changed(instructeur, dossier) diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb index 1a7383ca9..6129b5331 100644 --- a/app/services/expired_dossiers_deletion_service.rb +++ b/app/services/expired_dossiers_deletion_service.rb @@ -18,7 +18,10 @@ class ExpiredDossiersDeletionService .includes(:user, :procedure) .group_by(&:user) .each do |(user, dossiers)| - DossierMailer.notify_brouillon_near_deletion(user, dossiers).deliver_later + DossierMailer.notify_brouillon_near_deletion( + dossiers, + user.email + ).deliver_later end dossiers_close_to_expiration.update_all(brouillon_close_to_expiration_notice_sent_at: Time.zone.now) @@ -33,18 +36,16 @@ class ExpiredDossiersDeletionService .includes(:user) .group_by(&:user) .each do |(user, dossiers)| - DossierMailer.notify_en_construction_near_deletion( - user.email, + DossierMailer.notify_en_construction_near_deletion_to_user( dossiers, - true + user.email ).deliver_later end - group_by_fonctionnaire_email(dossiers_close_to_expiration).each do |(destinataire, dossiers)| - DossierMailer.notify_en_construction_near_deletion( - destinataire, + group_by_fonctionnaire_email(dossiers_close_to_expiration).each do |(email, dossiers)| + DossierMailer.notify_en_construction_near_deletion_to_administration( dossiers, - false + email ).deliver_later end @@ -58,7 +59,10 @@ class ExpiredDossiersDeletionService .includes(:user, :procedure) .group_by(&:user) .each do |(user, dossiers)| - DossierMailer.notify_brouillon_deletion(user, dossiers.map(&:hash_for_deletion_mail)).deliver_later + DossierMailer.notify_brouillon_deletion( + dossiers.map(&:hash_for_deletion_mail), + user.email + ).deliver_later end dossiers_to_remove.each do |dossier| @@ -70,27 +74,28 @@ class ExpiredDossiersDeletionService def self.delete_expired_en_construction_and_notify dossiers_to_remove = Dossier.en_construction_expired + dossiers_to_remove.each do |dossier| + DeletedDossier.create_from_dossier(dossier) + end + dossiers_to_remove .includes(:user) .group_by(&:user) .each do |(user, dossiers)| DossierMailer.notify_automatic_deletion_to_user( - user.email, - dossiers.map(&:hash_for_deletion_mail) + DeletedDossier.where(dossier_id: dossiers.map(&:id)), + user.email ).deliver_later end - self.group_by_fonctionnaire_email(dossiers_to_remove).each do |(destinataire, dossiers)| + self.group_by_fonctionnaire_email(dossiers_to_remove).each do |(email, dossiers)| DossierMailer.notify_automatic_deletion_to_administration( - destinataire, - dossiers.map(&:hash_for_deletion_mail) + DeletedDossier.where(dossier_id: dossiers.map(&:id)), + email ).deliver_later end - dossiers_to_remove.each do |dossier| - DeletedDossier.create_from_dossier(dossier) - dossier.destroy - end + dossiers_to_remove.destroy_all end private 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 e466b459b..373b78d11 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,10 +3,10 @@ %p Bonjour, -%p= t('.automatic_dossier_deletion', count: @dossier_hashes.count) - -%ul - - @dossier_hashes.each do |d| - %li= "n° #{d[:id]} (#{d[:procedure_libelle]})" +%p + = t('.header', count: @deleted_dossiers.count) + %ul + - @deleted_dossiers.each do |d| + %li n° #{d.dossier_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 213e26009..8a824675c 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,12 +3,12 @@ %p Bonjour, -%p= t('.automatic_dossier_deletion', count: @dossier_hashes.count) +%p + = t('.header', count: @deleted_dossiers.count) + %ul + - @deleted_dossiers.each do |d| + %li n° #{d.dossier_id} (#{d.procedure.libelle}) -%ul - - @dossier_hashes.each do |d| - %li= "n° #{d[:id]} (#{d[:procedure_libelle]})" - -%p= t('.dossier_will_not_be_processed', count: @dossier_hashes.count) +%p= t('.footer', count: @deleted_dossiers.count) = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_brouillon_deletion.html.haml b/app/views/dossier_mailer/notify_brouillon_deletion.html.haml index 7a28ec3f7..a621b7009 100644 --- a/app/views/dossier_mailer/notify_brouillon_deletion.html.haml +++ b/app/views/dossier_mailer/notify_brouillon_deletion.html.haml @@ -3,10 +3,10 @@ %p Bonjour, -%p= t('.automatic_dossier_deletion', count: @dossier_hashes.count) - -%ul - - @dossier_hashes.each do |d| - %li n° #{d[:id]} (#{d[:procedure_libelle]}) +%p + = t('.header', count: @dossier_hashes.count) + %ul + - @dossier_hashes.each do |d| + %li n° #{d[:id]} (#{d[:procedure_libelle]}) = 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 fc972ddd0..bce0ad8dc 100644 --- a/app/views/dossier_mailer/notify_brouillon_near_deletion.html.haml +++ b/app/views/dossier_mailer/notify_brouillon_near_deletion.html.haml @@ -4,13 +4,11 @@ Bonjour, %p - Afin de limiter la conservation de vos données personnelles, - = t('.automatic_dossier_deletion', count: @dossiers.count) + = t('.header', count: @dossiers.count) %ul - @dossiers.each do |d| %li= link_to("n° #{d.id} (#{d.procedure.libelle})", dossier_url(d)) -%p - #{sanitize(t('.send_your_draft', count: @dossiers.count))}. Et sinon, vous n'avez rien à faire. +%p= sanitize(t('.footer', count: @dossiers.count)) = 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 d53e295e5..e64cab4b6 100644 --- a/app/views/dossier_mailer/notify_deletion_to_administration.html.haml +++ b/app/views/dossier_mailer/notify_deletion_to_administration.html.haml @@ -1,11 +1,9 @@ -- content_for(:title, "Suppression du dossier n° #{@deleted_dossier.dossier_id}") +- content_for(:title, "#{@subject}") %p Bonjour, %p - À la demande de l'usager, le dossier n° #{@deleted_dossier.dossier_id} - (sur la démarche « #{@deleted_dossier.procedure.libelle} ») - a été supprimé. + = t('.body', dossier_id: @deleted_dossier.dossier_id, procedure: @deleted_dossier.procedure.libelle) = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_deletion_to_user.html.haml b/app/views/dossier_mailer/notify_deletion_to_user.html.haml index 293994ca1..e64cab4b6 100644 --- a/app/views/dossier_mailer/notify_deletion_to_user.html.haml +++ b/app/views/dossier_mailer/notify_deletion_to_user.html.haml @@ -1,11 +1,9 @@ -- content_for(:title, "Suppression du dossier n° #{@deleted_dossier.dossier_id}") +- content_for(:title, "#{@subject}") %p Bonjour, %p - Votre dossier n° #{@deleted_dossier.dossier_id} - (« #{@deleted_dossier.procedure.libelle} ») a bien été supprimé. - Une trace anonyme de ce traitement sera conservée pour l’administration. + = t('.body', dossier_id: @deleted_dossier.dossier_id, procedure: @deleted_dossier.procedure.libelle) = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_en_construction_near_deletion.html.haml b/app/views/dossier_mailer/notify_en_construction_near_deletion.html.haml deleted file mode 100644 index 896138408..000000000 --- a/app/views/dossier_mailer/notify_en_construction_near_deletion.html.haml +++ /dev/null @@ -1,27 +0,0 @@ -- content_for(:title, "#{@subject}") - -%p - Bonjour, - -%p - - if !@for_user - Afin de limiter la conservation de vos données personnelles, - - = t('.automatic_dossier_deletion', count: @dossiers.count) - - %ul - - @dossiers.each do |d| - - if !@for_user - %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))} - - else - %li - #{link_to("n° #{d.id} (#{d.procedure.libelle})", dossier_url(d))}. Retrouvez le dossier au format #{link_to("PDF", dossier_url(d, format: :pdf))} - -%p - - if @for_user - = sanitize(t('.send_user_draft', count: @dossiers.count)) - - else - = sanitize(t('.send_other_draft', count: @dossiers.count)) - -= render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_en_construction_near_deletion_to_administration.html.haml b/app/views/dossier_mailer/notify_en_construction_near_deletion_to_administration.html.haml new file mode 100644 index 000000000..b89f885f9 --- /dev/null +++ b/app/views/dossier_mailer/notify_en_construction_near_deletion_to_administration.html.haml @@ -0,0 +1,16 @@ +- content_for(:title, "#{@subject}") + +%p + Bonjour, + +%p + = t('.header', count: @dossiers.count) + %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 + = sanitize(t('.footer', count: @dossiers.count)) + += render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_en_construction_near_deletion_to_user.html.haml b/app/views/dossier_mailer/notify_en_construction_near_deletion_to_user.html.haml new file mode 100644 index 000000000..30dd62ad6 --- /dev/null +++ b/app/views/dossier_mailer/notify_en_construction_near_deletion_to_user.html.haml @@ -0,0 +1,16 @@ +- content_for(:title, "#{@subject}") + +%p + Bonjour, + +%p + = t('.header', count: @dossiers.count) + %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", dossier_url(d, format: :pdf))} + +%p + = sanitize(t('.footer', count: @dossiers.count)) + += 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 c0f77813f..1fcfd6198 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 @@ -4,6 +4,6 @@ fr: subject: one: "Un dossier a été supprimé automatiquement" other: "Des dossiers ont été supprimés automatiquement" - automatic_dossier_deletion: + header: one: "Le délai maximum de conservation du dossier suivant a été atteint, il a donc été supprimé :" other: "Le délai maximum de conservation des dossiers suivants a été atteint, ils ont donc été supprimés :" 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 7f5aef939..0f082b5ab 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 @@ -4,9 +4,9 @@ fr: subject: one: "Un dossier a été supprimé automatiquement" other: "Des dossiers ont été supprimés automatiquement" - automatic_dossier_deletion: + header: one: "Le délai maximum de conservation du dossier suivant a été atteint, il a donc été supprimé :" other: "Le délai maximum de conservation des dossiers suivants a été atteint, ils ont donc été supprimés :" - dossier_will_not_be_processed: + footer: 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." 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 291dffc23..bcb8ce439 100644 --- a/config/locales/views/dossier_mailer/notify_brouillon_deletion/fr.yml +++ b/config/locales/views/dossier_mailer/notify_brouillon_deletion/fr.yml @@ -4,6 +4,6 @@ fr: subject: one: "Un dossier en brouillon a été supprimé automatiquement" other: "Des dossiers en brouillon ont été supprimés automatiquement" - automatic_dossier_deletion: + header: one: "Le délai maximum de conservation du dossier en brouillon suivant a été atteint, il a donc été supprimé :" other: "Le délai maximum de conservation des dossiers en brouillon suivants a été atteint, ils 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 a3cbf01dc..f4ccef4e0 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 @@ -4,9 +4,9 @@ fr: subject: one: Un dossier en brouillon va bientôt être supprimé other: Des dossiers en brouillon vont bientôt être supprimés - automatic_dossier_deletion: - one: "le dossier en brouillon suivant sera bientôt automatiquement supprimé :" - other: "les dossiers en brouillon suivant seront bientôt automatiquement supprimés :" - send_your_draft: - one: "Si vous souhaitez toujours déposer ce dossier, vous pouvez retrouver votre brouillon pendant encore un mois" - other: "Si vous souhaitez toujours déposer ces dossiers, vous pouvez retrouver vos brouillons pendant encore un mois" + 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 suivant 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. 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. Et sinon, vous n’avez rien à faire." diff --git a/config/locales/views/dossier_mailer/notify_deletion_to_administration/fr.yml b/config/locales/views/dossier_mailer/notify_deletion_to_administration/fr.yml new file mode 100644 index 000000000..b31847d64 --- /dev/null +++ b/config/locales/views/dossier_mailer/notify_deletion_to_administration/fr.yml @@ -0,0 +1,5 @@ +fr: + dossier_mailer: + notify_deletion_to_administration: + subject: Le dossier nº %{dossier_id} a été supprimé à la demande de l’usager + body: À la demande de l’usager, le dossier n° %{dossier_id} (%{procedure}) a été supprimé. diff --git a/config/locales/views/dossier_mailer/notify_deletion_to_user/fr.yml b/config/locales/views/dossier_mailer/notify_deletion_to_user/fr.yml new file mode 100644 index 000000000..5d8caecf7 --- /dev/null +++ b/config/locales/views/dossier_mailer/notify_deletion_to_user/fr.yml @@ -0,0 +1,5 @@ +fr: + dossier_mailer: + notify_deletion_to_user: + subject: Votre dossier nº %{dossier_id} a bien été supprimé + body: Votre dossier n° %{dossier_id} (%{procedure}) a bien été supprimé. Une trace de ce traitement sera conservée pour l’administration. diff --git a/config/locales/views/dossier_mailer/notify_en_construction_near_deletion/fr.yml b/config/locales/views/dossier_mailer/notify_en_construction_near_deletion/fr.yml deleted file mode 100644 index 6a4955e0b..000000000 --- a/config/locales/views/dossier_mailer/notify_en_construction_near_deletion/fr.yml +++ /dev/null @@ -1,15 +0,0 @@ -fr: - dossier_mailer: - notify_en_construction_near_deletion: - subject: - one: Un dossier en construction va bientôt être supprimé - other: Des dossiers en construction vont bientôt être supprimés - automatic_dossier_deletion: - one: "le dossier en construction suivant sera bientôt automatiquement supprimé :" - other: "les dossiers en construction suivant seront bientôt automatiquement supprimés :" - send_user_draft: - one: "Vous pouvez retrouver votre dossier pendant encore un mois. Vous n'avez rien à faire." - other: "Vous pouvez retrouver vos dossiers pendant encore un mois. Vous n'avez rien à faire." - send_other_draft: - one: "Vous avez un mois pour traiter le dossier." - other: "Vous avez un mois pour traiter les dossiers." diff --git a/config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_administration/fr.yml b/config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_administration/fr.yml new file mode 100644 index 000000000..43bf63ded --- /dev/null +++ b/config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_administration/fr.yml @@ -0,0 +1,12 @@ +fr: + dossier_mailer: + notify_en_construction_near_deletion_to_administration: + subject: + one: Un dossier en construction va bientôt être supprimé + other: Des dossiers en construction vont bientôt être supprimés + header: + one: "Le dossier en construction suivant sera bientôt automatiquement supprimé :" + other: "Les dossiers en construction suivant seront bientôt automatiquement supprimés :" + footer: + one: "Vous avez un mois pour commencer l'instruction du dossier." + other: "Vous avez un mois pour commencer l'instruction des dossiers." diff --git a/config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_user/fr.yml b/config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_user/fr.yml new file mode 100644 index 000000000..d9c58d97b --- /dev/null +++ b/config/locales/views/dossier_mailer/notify_en_construction_near_deletion_to_user/fr.yml @@ -0,0 +1,12 @@ +fr: + dossier_mailer: + notify_en_construction_near_deletion_to_user: + subject: + one: Un dossier en construction va bientôt être supprimé + other: Des dossiers en construction vont bientôt être supprimés + header: + one: "Afin de limiter la conservation de vos données personnelles, le dossier en construction suivant sera bientôt automatiquement supprimé :" + other: "Afin de limiter la conservation de vos données personnelles, les dossiers en construction suivant seront bientôt automatiquement supprimés :" + footer: + one: "Vous pouvez retrouver votre dossier pendant encore un mois. Vous n’avez rien à faire." + other: "Vous pouvez retrouver vos dossiers pendant encore un mois. Vous n’avez rien à faire." diff --git a/spec/mailers/dossier_mailer_spec.rb b/spec/mailers/dossier_mailer_spec.rb index 4dec70856..c277461c8 100644 --- a/spec/mailers/dossier_mailer_spec.rb +++ b/spec/mailers/dossier_mailer_spec.rb @@ -55,8 +55,8 @@ RSpec.describe DossierMailer, type: :mailer do subject { described_class.notify_deletion_to_administration(deleted_dossier, to_email) } - it { expect(subject.subject).to eq("Le dossier nº #{deleted_dossier.dossier_id} a été supprimé à la demande de l'usager") } - it { expect(subject.body).to include("À la demande de l'usager") } + it { expect(subject.subject).to eq("Le dossier nº #{deleted_dossier.dossier_id} a été supprimé à la demande de l’usager") } + it { expect(subject.body).to include("À la demande de l’usager") } it { expect(subject.body).to include(deleted_dossier.dossier_id) } it { expect(subject.body).to include(deleted_dossier.procedure.libelle) } end @@ -81,7 +81,7 @@ RSpec.describe DossierMailer, type: :mailer do @date_suppression = dossier.created_at + duree.months end - subject { described_class.notify_brouillon_near_deletion(dossier.user, [dossier]) } + subject { described_class.notify_brouillon_near_deletion([dossier], dossier.user.email) } it { expect(subject.body).to include("n° #{dossier.id} ") } it { expect(subject.body).to include(dossier.procedure.libelle) } @@ -90,7 +90,7 @@ RSpec.describe DossierMailer, type: :mailer do describe '.notify_brouillon_deletion' do let(:dossier) { create(:dossier) } - subject { described_class.notify_brouillon_deletion(dossier.user, [dossier.hash_for_deletion_mail]) } + subject { described_class.notify_brouillon_deletion([dossier.hash_for_deletion_mail], dossier.user.email) } it { expect(subject.subject).to eq("Un dossier en brouillon a été supprimé automatiquement") } it { expect(subject.body).to include("n° #{dossier.id} (#{dossier.procedure.libelle})") } @@ -98,13 +98,14 @@ RSpec.describe DossierMailer, type: :mailer do describe '.notify_automatic_deletion_to_user' do let(:dossier) { create(:dossier) } + let(:deleted_dossier) { DeletedDossier.create_from_dossier(dossier) } before do duree = dossier.procedure.duree_conservation_dossiers_dans_ds @date_suppression = dossier.created_at + duree.months end - subject { described_class.notify_automatic_deletion_to_user(dossier.user.email, [dossier.hash_for_deletion_mail]) } + subject { described_class.notify_automatic_deletion_to_user([deleted_dossier], dossier.user.email) } it { expect(subject.to).to eq([dossier.user.email]) } it { expect(subject.subject).to eq("Un dossier a été supprimé automatiquement") } @@ -115,8 +116,9 @@ RSpec.describe DossierMailer, type: :mailer do describe '.notify_automatic_deletion_to_administration' do let(:dossier) { create(:dossier) } + let(:deleted_dossier) { DeletedDossier.create_from_dossier(dossier) } - subject { described_class.notify_automatic_deletion_to_administration(dossier.user, [dossier.hash_for_deletion_mail]) } + subject { described_class.notify_automatic_deletion_to_administration([deleted_dossier], dossier.user.email) } it { expect(subject.subject).to eq("Un dossier a été supprimé automatiquement") } it { expect(subject.body).to include("n° #{dossier.id} (#{dossier.procedure.libelle})") } @@ -130,13 +132,13 @@ RSpec.describe DossierMailer, type: :mailer do @date_suppression = dossier.created_at + duree.months end - subject { described_class.notify_en_construction_near_deletion(dossier.user.email, [dossier], true) } + subject { described_class.notify_en_construction_near_deletion_to_administration([dossier], dossier.user.email) } it { expect(subject.subject).to eq("Un dossier en construction va bientôt être supprimé") } it { expect(subject.body).to include("n° #{dossier.id} ") } it { expect(subject.body).to include(dossier.procedure.libelle) } it { expect(subject.body).to include("PDF") } - it { expect(subject.body).to include("Vous pouvez retrouver votre dossier pendant encore un mois. Vous n'avez rien à faire.") } + it { expect(subject.body).to include("Vous avez un mois pour commencer l'instruction du dossier.") } end describe '.notify_en_construction_near_deletion_to_user' do @@ -147,14 +149,14 @@ RSpec.describe DossierMailer, type: :mailer do @date_suppression = dossier.created_at + duree.months end - subject { described_class.notify_en_construction_near_deletion(dossier.user.email, [dossier], false) } + subject { described_class.notify_en_construction_near_deletion_to_user([dossier], dossier.user.email) } it { expect(subject.to).to eq([dossier.user.email]) } it { expect(subject.subject).to eq("Un dossier en construction va bientôt être supprimé") } it { expect(subject.body).to include("n° #{dossier.id} ") } it { expect(subject.body).to include(dossier.procedure.libelle) } it { expect(subject.body).to include("PDF") } - it { expect(subject.body).to include("Vous avez un mois pour traiter le dossier.") } + it { expect(subject.body).to include("Vous pouvez retrouver votre dossier pendant encore un mois. Vous n’avez rien à faire.") } end describe '.notify_groupe_instructeur_changed_to_instructeur' do diff --git a/spec/mailers/previews/dossier_mailer_preview.rb b/spec/mailers/previews/dossier_mailer_preview.rb index 38c22902f..55c1fd562 100644 --- a/spec/mailers/previews/dossier_mailer_preview.rb +++ b/spec/mailers/previews/dossier_mailer_preview.rb @@ -8,47 +8,61 @@ class DossierMailerPreview < ActionMailer::Preview DossierMailer.notify_new_answer(dossier) end - def notify_deletion_to_user - DossierMailer.notify_deletion_to_user(deleted_dossier, "user@ds.fr") - end - - def notify_deletion_to_administration - DossierMailer.notify_deletion_to_administration(deleted_dossier, "admin@ds.fr") - end - def notify_revert_to_instruction DossierMailer.notify_revert_to_instruction(dossier) end def notify_brouillon_near_deletion - DossierMailer.notify_brouillon_near_deletion(User.new(email: "usager@example.com"), [dossier]) + DossierMailer.notify_brouillon_near_deletion([dossier], usager_email) end def notify_brouillons_near_deletion - DossierMailer.notify_brouillon_near_deletion(User.new(email: "usager@example.com"), [dossier, dossier]) + DossierMailer.notify_brouillon_near_deletion([dossier, dossier], usager_email) + end + + def notify_en_construction_near_deletion_to_user + DossierMailer.notify_en_construction_near_deletion_to_user([dossier], usager_email) + end + + def notify_en_construction_near_deletion_to_administration + DossierMailer.notify_en_construction_near_deletion_to_administration([dossier, dossier], administration_email) end def notify_brouillon_deletion - DossierMailer.notify_brouillon_deletion(User.new(email: "usager@example.com"), [dossier.hash_for_deletion_mail]) + DossierMailer.notify_brouillon_deletion([dossier.hash_for_deletion_mail], usager_email) end def notify_brouillons_deletion dossier_hashes = [dossier, dossier].map(&:hash_for_deletion_mail) - DossierMailer.notify_brouillon_deletion(User.new(email: "usager@example.com"), dossier_hashes) + DossierMailer.notify_brouillon_deletion(dossier_hashes, usager_email) + end + + def notify_deletion_to_user + DossierMailer.notify_deletion_to_user(deleted_dossier, usager_email) + end + + def notify_deletion_to_administration + DossierMailer.notify_deletion_to_administration(deleted_dossier, administration_email) end def notify_automatic_deletion_to_user - dossier_hashes = [dossier, dossier].map(&:hash_for_deletion_mail) - DossierMailer.notify_automatic_deletion_to_user("usager@example.com", dossier_hashes) + DossierMailer.notify_automatic_deletion_to_user([deleted_dossier, deleted_dossier], usager_email) end def notify_automatic_deletion_to_administration - dossier_hashes = [dossier, dossier].map(&:hash_for_deletion_mail) - DossierMailer.notify_automatic_deletion_to_administration("admin@example.com", dossier_hashes) + DossierMailer.notify_automatic_deletion_to_administration([deleted_dossier, deleted_dossier], administration_email) end private + def usager_email + "usager@example.com" + end + + def administration_email + "administration@example.com" + end + def deleted_dossier DeletedDossier.new(dossier_id: 1, procedure: procedure) end @@ -62,7 +76,7 @@ class DossierMailerPreview < ActionMailer::Preview end def procedure - Procedure.new(libelle: 'Dotation d’Équipement des Territoires Ruraux - Exercice 2019', service: service, logo: Rack::Test::UploadedFile.new("./spec/fixtures/files/logo_test_procedure.png", 'image/png')) + Procedure.new(id: 1234, libelle: 'Dotation d’Équipement des Territoires Ruraux - Exercice 2019', service: service, logo: Rack::Test::UploadedFile.new("./spec/fixtures/files/logo_test_procedure.png", 'image/png')) end def service diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb index c927755d8..1b7c1088f 100644 --- a/spec/services/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -24,7 +24,7 @@ describe ExpiredDossiersDeletionService do it 'emails should be sent' do expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).once - expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(brouillon_close_to_expiration.user, [brouillon_close_to_expiration]) + expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with([brouillon_close_to_expiration], brouillon_close_to_expiration.user.email) end it 'dossier state should change' do @@ -33,8 +33,7 @@ describe ExpiredDossiersDeletionService do it 'deletes and notify expired brouillon' do expect(DossierMailer).to have_received(:notify_brouillon_deletion).once - expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(expired_brouillon.user, [expired_brouillon.hash_for_deletion_mail]) - + expect(DossierMailer).to have_received(:notify_brouillon_deletion).with([expired_brouillon.hash_for_deletion_mail], expired_brouillon.user.email) expect(DeletedDossier.find_by(dossier_id: expired_brouillon.id)).to be_present expect { expired_brouillon.reload }.to raise_error(ActiveRecord::RecordNotFound) end @@ -68,7 +67,7 @@ describe ExpiredDossiersDeletionService do it { expect(dossier.reload.brouillon_close_to_expiration_notice_sent_at).not_to be_nil } it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).once } - it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(dossier.user, [dossier]) } + it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with([dossier], dossier.user.email) } end end @@ -80,7 +79,7 @@ describe ExpiredDossiersDeletionService do before { ExpiredDossiersDeletionService.send_brouillon_expiration_notices } it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).once } - it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(user, match_array([dossier_1, dossier_2])) } + it { expect(DossierMailer).to have_received(:notify_brouillon_near_deletion).with(match_array([dossier_1, dossier_2]), user.email) } end end @@ -119,7 +118,7 @@ describe ExpiredDossiersDeletionService do it { expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) } it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).once } - it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(dossier.user, [dossier.hash_for_deletion_mail]) } + it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).with([dossier.hash_for_deletion_mail], dossier.user.email) } end end @@ -131,7 +130,7 @@ describe ExpiredDossiersDeletionService do before { ExpiredDossiersDeletionService.delete_expired_brouillons_and_notify } it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).once } - it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(user, match_array([dossier_1, dossier_2].map(&:hash_for_deletion_mail))) } + it { expect(DossierMailer).to have_received(:notify_brouillon_deletion).with(match_array([dossier_1.hash_for_deletion_mail, dossier_2.hash_for_deletion_mail]), user.email) } end end @@ -142,7 +141,8 @@ describe ExpiredDossiersDeletionService do after { Timecop.return } before do - allow(DossierMailer).to receive(:notify_en_construction_near_deletion).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_en_construction_near_deletion_to_user).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_en_construction_near_deletion_to_administration).and_return(double(deliver_later: nil)) end context 'with a single dossier' do @@ -154,7 +154,8 @@ describe ExpiredDossiersDeletionService do let(:en_construction_at) { (conservation_par_defaut - 1.month - 1.day).ago } it { expect(dossier.reload.en_construction_close_to_expiration_notice_sent_at).to be_nil } - it { expect(DossierMailer).not_to have_received(:notify_en_construction_near_deletion) } + it { expect(DossierMailer).not_to have_received(:notify_en_construction_near_deletion_to_user) } + it { expect(DossierMailer).not_to have_received(:notify_en_construction_near_deletion_to_administration) } end context 'when the dossier is near deletion' do @@ -162,10 +163,11 @@ describe ExpiredDossiersDeletionService do it { expect(dossier.reload.en_construction_close_to_expiration_notice_sent_at).not_to be_nil } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).thrice } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.user.email, [dossier], true) } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.procedure.administrateurs.first.email, [dossier], false) } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.followers_instructeurs.first.email, [dossier], false) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).twice } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_user).with([dossier], dossier.user.email) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).with([dossier], dossier.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).with([dossier], dossier.followers_instructeurs.first.email) } end end @@ -181,11 +183,12 @@ describe ExpiredDossiersDeletionService do ExpiredDossiersDeletionService.send_en_construction_expiration_notices end - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).exactly(4).times } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(user.email, match_array([dossier_1, dossier_2]), true) } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(instructeur.email, match_array([dossier_1, dossier_2]), false) } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier_1.procedure.administrateurs.first.email, [dossier_1], false) } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier_2.procedure.administrateurs.first.email, [dossier_2], false) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).exactly(3).times } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_user).with(match_array([dossier_1, dossier_2]), user.email) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).with(match_array([dossier_1, dossier_2]), instructeur.email) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).with([dossier_1], dossier_1.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).with([dossier_2], dossier_2.procedure.administrateurs.first.email) } end context 'when an instructeur is also administrateur' do @@ -198,9 +201,9 @@ describe ExpiredDossiersDeletionService do ExpiredDossiersDeletionService.send_en_construction_expiration_notices end - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).exactly(2).times } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(dossier.user.email, [dossier], true) } - it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion).with(administrateur.email, [dossier], false) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_user).with([dossier], dossier.user.email) } + it { expect(DossierMailer).to have_received(:notify_en_construction_near_deletion_to_administration).with([dossier], administrateur.email) } end end @@ -217,6 +220,7 @@ describe ExpiredDossiersDeletionService do context 'with a single dossier' do let!(:dossier) { create(:dossier, :en_construction, :followed, en_construction_close_to_expiration_notice_sent_at: notice_sent_at) } + let(:deleted_dossier) { DeletedDossier.find_by(dossier_id: dossier.id) } before { ExpiredDossiersDeletionService.delete_expired_en_construction_and_notify } @@ -242,11 +246,11 @@ describe ExpiredDossiersDeletionService do 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(dossier.user.email, [dossier.hash_for_deletion_mail]) } + 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_administration).twice } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier.procedure.administrateurs.first.email, [dossier.hash_for_deletion_mail]) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier.followers_instructeurs.first.email, [dossier.hash_for_deletion_mail]) } + 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) } end end @@ -254,6 +258,8 @@ describe ExpiredDossiersDeletionService do let!(:user) { create(:user) } let!(:dossier_1) { create(:dossier, :en_construction, user: user, en_construction_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } let!(:dossier_2) { create(:dossier, :en_construction, 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) } @@ -263,12 +269,12 @@ describe ExpiredDossiersDeletionService 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(user.email, match_array([dossier_1, dossier_2].map(&:hash_for_deletion_mail))) } + 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_administration).thrice } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(instructeur.email, match_array([dossier_1, dossier_2].map(&:hash_for_deletion_mail))) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier_1.procedure.administrateurs.first.email, [dossier_1.hash_for_deletion_mail]) } - it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(dossier_2.procedure.administrateurs.first.email, [dossier_2.hash_for_deletion_mail]) } + 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) } end end end From 1b4a218b0ef4b2b94831a4b2c8b623160dd61b63 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Thu, 19 Mar 2020 17:13:52 +0100 Subject: [PATCH 18/26] specs: remove useless chrome argument The `options.add_argument('--headless')` above is sufficient. --- spec/spec_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f5e6de454..97fca6426 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -44,7 +44,7 @@ Capybara.register_driver :headless_chrome do |app| options.add_argument('--window-size=1440,900') capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( - chromeOptions: { args: ['headless', 'disable-dev-shm-usage', 'disable-software-rasterizer', 'mute-audio', 'window-size=1440,900'] } + chromeOptions: { args: ['disable-dev-shm-usage', 'disable-software-rasterizer', 'mute-audio', 'window-size=1440,900'] } ) Capybara::Selenium::Driver.new app, From ec2199f7b1b6728e1615005707b30ae0f48c9f9f Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 16 Mar 2020 19:19:50 +0100 Subject: [PATCH 19/26] javascript: make utils.ajax() return a promise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allow to use `await ajax(…)`, and still have Rails manage the request, insert the proper headers and tokens, etc. --- app/javascript/shared/utils.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/javascript/shared/utils.js b/app/javascript/shared/utils.js index 0921b6d68..e74ddd78e 100644 --- a/app/javascript/shared/utils.js +++ b/app/javascript/shared/utils.js @@ -3,7 +3,7 @@ import $ from 'jquery'; import debounce from 'debounce'; export { debounce }; -export const { fire, ajax } = Rails; +export const { fire } = Rails; export function show(el) { el && el.classList.remove('hidden'); @@ -45,6 +45,22 @@ export function delegate(eventNames, selector, callback) { ); } +export function ajax(options) { + return new Promise((resolve, reject) => { + Object.assign(options, { + success: (response, statusText, xhr) => { + resolve({ response, statusText, xhr }); + }, + error: (response, statusText, xhr) => { + let error = new Error(`Erreur ${xhr.status} : ${statusText}`); + Object.assign(error, { response, statusText, xhr }); + reject(error); + } + }); + Rails.ajax(options); + }); +} + export function getJSON(url, data, method = 'get') { incrementActiveRequestsCount(); data = method !== 'get' ? JSON.stringify(data) : data; From 884de51b940d8269e0f2950b64dc3cc7c3f977dd Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 18 Mar 2020 16:29:48 +0100 Subject: [PATCH 20/26] Revert "Revert "go to procedure after cliking link"" This reverts commit 952bae32fe6ba5d2729ebc7205a525d1f56c1d71. --- app/controllers/application_controller.rb | 2 +- spec/controllers/application_controller_spec.rb | 1 + spec/features/users/dossier_creation_spec.rb | 12 ++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b78fe1b90..5ec259b6f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -198,7 +198,7 @@ class ApplicationController < ActionController::Base # return at this location # after the device is trusted - store_location_for(:user, request.fullpath) + store_location_for(:user, request.fullpath) if get_stored_location_for(:user).blank? send_login_token_or_bufferize(current_instructeur) redirect_to link_sent_path(email: current_instructeur.email) diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 990c55961..8289c3482 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -164,6 +164,7 @@ describe ApplicationController, type: :controller do allow(@controller).to receive(:instructeur_signed_in?).and_return(instructeur_signed_in) allow(@controller).to receive(:sensitive_path).and_return(sensitive_path) allow(@controller).to receive(:send_login_token_or_bufferize) + allow(@controller).to receive(:get_stored_location_for).and_return(nil) allow(@controller).to receive(:store_location_for) allow(IPService).to receive(:ip_trusted?).and_return(ip_trusted) end diff --git a/spec/features/users/dossier_creation_spec.rb b/spec/features/users/dossier_creation_spec.rb index 662d02918..e54228974 100644 --- a/spec/features/users/dossier_creation_spec.rb +++ b/spec/features/users/dossier_creation_spec.rb @@ -110,4 +110,16 @@ feature 'Creating a new dossier:' do end end end + + context 'when the user is not signed in' do + let(:instructeur) { create(:instructeur) } + let(:procedure) { create(:procedure, :published) } + scenario 'the user is an instructeur with untrusted device' do + visit commencer_path(path: procedure.path) + click_on "J’ai déjà un compte" + sign_in_with(instructeur.email, instructeur.user.password, true) + + expect(page).to have_current_path(commencer_path(path: procedure.path)) + end + end end From 775cc11d30909ff57e289f33b23d9821c41856c8 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 18 Mar 2020 16:05:04 +0100 Subject: [PATCH 21/26] include store_location_extension for all controllers --- app/controllers/application_controller.rb | 1 + app/controllers/invites_controller.rb | 2 -- app/controllers/users/dossiers_controller.rb | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5ec259b6f..c3260ddc2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,7 @@ class ApplicationController < ActionController::Base include TrustedDeviceConcern include Pundit + include Devise::StoreLocationExtension MAINTENANCE_MESSAGE = 'Le site est actuellement en maintenance. Il sera à nouveau disponible dans un court instant.' diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 646c3505c..29412c102 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -1,6 +1,4 @@ class InvitesController < ApplicationController - include Devise::StoreLocationExtension - before_action :authenticate_user!, only: [:create] before_action :store_user_location!, only: [:show] diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 2e70cd862..8d4ffd26a 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -1,6 +1,5 @@ module Users class DossiersController < UserController - include Devise::StoreLocationExtension include DossierHelper layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret] From d46bcecc517b5a1abb34f269f2cc98b9ed1448e2 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Fri, 20 Mar 2020 10:26:21 +0100 Subject: [PATCH 22/26] improve code readbility --- app/controllers/application_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c3260ddc2..b146affec 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -199,7 +199,9 @@ class ApplicationController < ActionController::Base # return at this location # after the device is trusted - store_location_for(:user, request.fullpath) if get_stored_location_for(:user).blank? + if get_stored_location_for(:user).blank? + store_location_for(:user, request.fullpath) + end send_login_token_or_bufferize(current_instructeur) redirect_to link_sent_path(email: current_instructeur.email) From eb8df80c187d01e0365d808c3847184e25ad5229 Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Fri, 20 Mar 2020 10:53:42 +0100 Subject: [PATCH 23/26] fix the email notifications data bug --- app/models/instructeur.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index d580694ae..bb55fe36a 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -163,11 +163,13 @@ class Instructeur < ApplicationRecord acc << h end - [["en_instruction", h[:nb_en_instruction]], ["accepte", h[:nb_accepted]]].each do |state, count| - if procedure.declarative_with_state == state && count > 0 - h[:procedure_id] = procedure.id - h[:procedure_libelle] = procedure.libelle - acc << h + if h[:nb_en_instruction] > 0 || h[:nb_accepted] > 0 + [["en_instruction", h[:nb_en_instruction]], ["accepte", h[:nb_accepted]]].each do |state, count| + if procedure&.declarative_with_state == state && count > 0 + h[:procedure_id] = procedure.id + h[:procedure_libelle] = procedure.libelle + acc << h + end end end From 969d5625c88bab5c00e9aea42ac3fe4083eb2fe4 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 20 Mar 2020 22:28:52 +0100 Subject: [PATCH 24/26] fix missing rename --- app/jobs/expired_dossiers_deletion_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/expired_dossiers_deletion_job.rb b/app/jobs/expired_dossiers_deletion_job.rb index 65e478192..f269d595a 100644 --- a/app/jobs/expired_dossiers_deletion_job.rb +++ b/app/jobs/expired_dossiers_deletion_job.rb @@ -2,6 +2,6 @@ class ExpiredDossiersDeletionJob < ApplicationJob queue_as :cron def perform(*args) - ExpiredDossiersDeletionService.process_dossiers_brouillon + ExpiredDossiersDeletionService.process_expired_dossiers_brouillon end end From 1f27652cd370a9edd851dd4bec13abaf8b94960c Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Mon, 16 Mar 2020 17:55:16 +0100 Subject: [PATCH 25/26] add files validations to models --- app/models/attestation_template.rb | 5 ++--- app/models/avis.rb | 2 ++ app/models/commentaire.rb | 1 + app/models/procedure.rb | 20 +++++++++++++++++++ .../procedures/_informations.html.haml | 2 ++ spec/models/procedure_spec.rb | 16 +++++++++++---- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/app/models/attestation_template.rb b/app/models/attestation_template.rb index 69056789b..87accde3c 100644 --- a/app/models/attestation_template.rb +++ b/app/models/attestation_template.rb @@ -10,9 +10,8 @@ class AttestationTemplate < ApplicationRecord has_one_attached :signature validates :footer, length: { maximum: 190 } - - validates :logo, content_type: [:png, :jpg, :jpeg] - validates :signature, content_type: [:png, :jpg, :jpeg] + validates :logo, content_type: ['image/png', 'image/jpg', 'image/jpeg'], size: { less_than: 1.megabytes } + validates :signature, content_type: ['image/png', 'image/jpg', 'image/jpeg'], size: { less_than: 1.megabytes } DOSSIER_STATE = Dossier.states.fetch(:accepte) diff --git a/app/models/avis.rb b/app/models/avis.rb index fae8f3a35..bf468b96a 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -10,6 +10,8 @@ class Avis < ApplicationRecord validates :email, format: { with: Devise.email_regexp, message: "n'est pas valide" }, allow_nil: true validates :claimant, presence: true + validates :piece_justificative_file, size: { less_than: 20.megabytes } + validates :introduction_file, size: { less_than: 20.megabytes } before_validation -> { sanitize_email(:email) } before_create :try_to_assign_instructeur diff --git a/app/models/commentaire.rb b/app/models/commentaire.rb index 9a93319d4..7d4a520ae 100644 --- a/app/models/commentaire.rb +++ b/app/models/commentaire.rb @@ -11,6 +11,7 @@ class Commentaire < ApplicationRecord has_one_attached :piece_jointe validates :body, presence: { message: "ne peut être vide" } + validates :piece_jointe, size: { less_than: 20.megabytes } default_scope { order(created_at: :asc) } scope :updated_since?, -> (date) { where('commentaires.updated_at > ?', date) } diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 807899628..3c3a72fca 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -84,6 +84,26 @@ class Procedure < ApplicationRecord validates :duree_conservation_dossiers_dans_ds, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: MAX_DUREE_CONSERVATION }, unless: :durees_conservation_required validates :duree_conservation_dossiers_hors_ds, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, unless: :durees_conservation_required validates_with MonAvisEmbedValidator + validates :notice, content_type: [ + "application/msword", + "application/pdf", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-powerpoint", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.oasis.opendocument.text", + "application/vnd.oasis.opendocument.presentation", + "text/plain" + ], size: { less_than: 20.megabytes } + + validates :deliberation, content_type: [ + "application/msword", + "application/pdf", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "text/plain", + "application/vnd.oasis.opendocument.text" + ], size: { less_than: 20.megabytes } + + validates :logo, content_type: ['image/png', 'image/jpg', 'image/jpeg'], size: { less_than: 5.megabytes } before_save :update_juridique_required before_save :update_durees_conservation_required after_initialize :ensure_path_exists diff --git a/app/views/new_administrateur/procedures/_informations.html.haml b/app/views/new_administrateur/procedures/_informations.html.haml index 9a3385173..db14b75a1 100644 --- a/app/views/new_administrateur/procedures/_informations.html.haml +++ b/app/views/new_administrateur/procedures/_informations.html.haml @@ -70,6 +70,8 @@ Une notice explicative est un document destiné à guider l’usager dans sa démarche. C’est un document que vous avez élaboré et qui peut prendre la forme d’un fichier doc, d’un pdf ou encore de diapositives. Le bouton pour télécharger cette notice apparaît en haut du formulaire pour l’usager. = f.label :notice, 'Notice' +%p.notice + Formats acceptés : .doc, .odt, .pdf, .ppt, .pptx - notice = @procedure.notice = render 'shared/attachment/edit', { form: f, diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index 080d753a5..0d3b220df 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -193,12 +193,19 @@ describe Procedure do context 'when the deliberation is uploaded ' do before do - allow(procedure).to receive(:deliberation) - .and_return(double('attached?': true)) + procedure.deliberation = Rack::Test::UploadedFile.new('spec/fixtures/files/file.pdf', 'application/pdf') end it { expect(procedure.valid?).to eq(true) } end + + context 'when the deliberation is uploaded with an unauthorized format' do + before do + procedure.deliberation = Rack::Test::UploadedFile.new('spec/fixtures/files/french-flag.gif', 'image/gif') + end + + it { expect(procedure.valid?).to eq(false) } + end end end @@ -925,8 +932,9 @@ describe Procedure do p.reload expect(p.juridique_required).to be_falsey - allow(p).to receive(:deliberation).and_return(double('attached?': true)) - p.save + @deliberation = Rack::Test::UploadedFile.new('spec/fixtures/files/file.pdf', 'application/pdf') + p.update(deliberation: @deliberation) + p.reload expect(p.juridique_required).to be_truthy end end From d1cad0388ec90c263cc9ad43f092716e0dde151e Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 20 Mar 2020 22:11:07 +0100 Subject: [PATCH 26/26] minor rails bump --- Gemfile | 2 +- Gemfile.lock | 74 ++++++++++++++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Gemfile b/Gemfile index ada4d9e22..92790bce2 100644 --- a/Gemfile +++ b/Gemfile @@ -54,7 +54,7 @@ gem 'puma' # Use Puma as the app server gem 'pundit' gem 'rack-attack' gem 'rack-mini-profiler' -gem 'rails' +gem 'rails', '= 5.2.4.2' gem 'rails-i18n' # Locales par défaut gem 'rake-progressbar', require: false gem 'react-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 224b5f9a5..425c59161 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,25 +20,25 @@ GEM specs: aasm (5.0.1) concurrent-ruby (~> 1.0) - actioncable (5.2.4.1) - actionpack (= 5.2.4.1) + actioncable (5.2.4.2) + actionpack (= 5.2.4.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.1) - actionpack (= 5.2.4.1) - actionview (= 5.2.4.1) - activejob (= 5.2.4.1) + actionmailer (5.2.4.2) + actionpack (= 5.2.4.2) + actionview (= 5.2.4.2) + activejob (= 5.2.4.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.1) - actionview (= 5.2.4.1) - activesupport (= 5.2.4.1) + actionpack (5.2.4.2) + actionview (= 5.2.4.2) + activesupport (= 5.2.4.2) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.1) - activesupport (= 5.2.4.1) + actionview (5.2.4.2) + activesupport (= 5.2.4.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -53,25 +53,25 @@ GEM jsonapi-renderer (>= 0.1.1.beta1, < 0.3) active_storage_validations (0.8.7) rails (>= 5.2.0) - activejob (5.2.4.1) - activesupport (= 5.2.4.1) + activejob (5.2.4.2) + activesupport (= 5.2.4.2) globalid (>= 0.3.6) - activemodel (5.2.4.1) - activesupport (= 5.2.4.1) - activerecord (5.2.4.1) - activemodel (= 5.2.4.1) - activesupport (= 5.2.4.1) + activemodel (5.2.4.2) + activesupport (= 5.2.4.2) + activerecord (5.2.4.2) + activemodel (= 5.2.4.2) + activesupport (= 5.2.4.2) arel (>= 9.0) - activestorage (5.2.4.1) - actionpack (= 5.2.4.1) - activerecord (= 5.2.4.1) + activestorage (5.2.4.2) + actionpack (= 5.2.4.2) + activerecord (= 5.2.4.2) marcel (~> 0.3.1) activestorage-openstack (1.4.1) fog-openstack (~> 1.0) marcel mime-types rails (>= 5.2.2) - activesupport (5.2.4.1) + activesupport (5.2.4.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -469,18 +469,18 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.1) - actioncable (= 5.2.4.1) - actionmailer (= 5.2.4.1) - actionpack (= 5.2.4.1) - actionview (= 5.2.4.1) - activejob (= 5.2.4.1) - activemodel (= 5.2.4.1) - activerecord (= 5.2.4.1) - activestorage (= 5.2.4.1) - activesupport (= 5.2.4.1) + rails (5.2.4.2) + actioncable (= 5.2.4.2) + actionmailer (= 5.2.4.2) + actionpack (= 5.2.4.2) + actionview (= 5.2.4.2) + activejob (= 5.2.4.2) + activemodel (= 5.2.4.2) + activerecord (= 5.2.4.2) + activestorage (= 5.2.4.2) + activesupport (= 5.2.4.2) bundler (>= 1.3.0) - railties (= 5.2.4.1) + railties (= 5.2.4.2) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.4) actionpack (>= 5.0.1.x) @@ -494,9 +494,9 @@ GEM rails-i18n (5.1.2) i18n (>= 0.7, < 2) railties (>= 5.0, < 6) - railties (5.2.4.1) - actionpack (= 5.2.4.1) - activesupport (= 5.2.4.1) + railties (5.2.4.2) + actionpack (= 5.2.4.2) + activesupport (= 5.2.4.2) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) @@ -782,7 +782,7 @@ DEPENDENCIES pundit rack-attack rack-mini-profiler - rails + rails (= 5.2.4.2) rails-controller-testing rails-i18n rake-progressbar