[#10951] Create a cron job to warn user with a old brouillon
This commit is contained in:
parent
b77a5f4c6e
commit
38e9ca4979
10 changed files with 221 additions and 1 deletions
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Cron::NotifyOldBrouillonDossiersSoonDeletedJob < Cron::CronJob
|
||||||
|
self.schedule_expression = "every day at 9:00"
|
||||||
|
|
||||||
|
def perform
|
||||||
|
Dossier
|
||||||
|
.state_brouillon
|
||||||
|
.where(updated_at: ..3.months.ago)
|
||||||
|
.where("notified_soon_deleted_sent_at IS NULL OR notified_soon_deleted_sent_at < updated_at")
|
||||||
|
.find_each do |dossier|
|
||||||
|
DossierMailer.notify_old_brouillon_soon_deleted(dossier).deliver_later
|
||||||
|
dossier.update_column(:notified_soon_deleted_sent_at, Time.zone.now)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -217,6 +217,26 @@ class DossierMailer < ApplicationMailer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def notify_old_brouillon_after_deletion(dossier)
|
||||||
|
@dossier = dossier
|
||||||
|
configure_defaults_for_user(dossier.user)
|
||||||
|
|
||||||
|
I18n.with_locale(dossier.user_locale) do
|
||||||
|
@subject = default_i18n_subject(dossier_id: dossier.id)
|
||||||
|
mail(to: dossier.user_email_for(:notification), subject: @subject)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def notify_old_brouillon_soon_deleted(dossier)
|
||||||
|
@dossier = dossier
|
||||||
|
configure_defaults_for_user(dossier.user)
|
||||||
|
|
||||||
|
I18n.with_locale(dossier.user_locale) do
|
||||||
|
@subject = default_i18n_subject(dossier_id: dossier.id)
|
||||||
|
mail(to: dossier.user_email_for(:notification), subject: @subject)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.critical_email?(action_name)
|
def self.critical_email?(action_name)
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
- content_for(:title, "#{@subject}")
|
||||||
|
|
||||||
|
%p= t(:hello, scope: [:views, :shared, :greetings])
|
||||||
|
|
||||||
|
%p= t('.body', dossier_id: @dossier.id, libelle_demarche: @dossier.procedure.libelle)
|
||||||
|
|
||||||
|
%p= link_to t('.access_dossier'), dossier_url(@dossier), target: '_blank'
|
||||||
|
|
||||||
|
= render partial: "layouts/mailers/signature"
|
|
@ -0,0 +1,11 @@
|
||||||
|
en:
|
||||||
|
dossier_mailer:
|
||||||
|
notify_old_brouillon_soon_deleted:
|
||||||
|
subject: 'Your draft file n°%{dossier_id} will soon be deleted'
|
||||||
|
body: |
|
||||||
|
Your file n° %{dossier_id} for "%{libelle_demarche}" has not been modified for more than 3 months.
|
||||||
|
|
||||||
|
It will be automatically deleted in 2 weeks.
|
||||||
|
|
||||||
|
If you wish to keep this application, please update it by logging into your personal space.
|
||||||
|
access_dossier: 'Access my dossier'
|
|
@ -0,0 +1,11 @@
|
||||||
|
fr:
|
||||||
|
dossier_mailer:
|
||||||
|
notify_old_brouillon_soon_deleted:
|
||||||
|
subject: 'Votre dossier n°%{dossier_id} en brouillon va bientôt être supprimé'
|
||||||
|
body: |
|
||||||
|
Votre dossier n° %{dossier_id} pour la démarche "%{libelle_demarche}" n'a pas été modifié depuis plus de 3 mois.
|
||||||
|
|
||||||
|
Il sera automatiquement supprimé dans 2 semaines.
|
||||||
|
|
||||||
|
Si vous souhaitez conserver ce dossier, nous vous invitons à le mettre à jour en vous connectant à votre espace personnel.
|
||||||
|
access_dossier: 'Accéder à mon dossier'
|
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddNotifiedSoonDeletedSentAtToDossiers < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
add_column :dossiers, :notified_soon_deleted_sent_at, :datetime
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.0].define(version: 2024_11_12_090128) do
|
ActiveRecord::Schema[7.0].define(version: 2024_11_26_145420) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "pg_buffercache"
|
enable_extension "pg_buffercache"
|
||||||
enable_extension "pg_stat_statements"
|
enable_extension "pg_stat_statements"
|
||||||
|
@ -505,6 +505,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_11_12_090128) do
|
||||||
t.string "mandataire_first_name"
|
t.string "mandataire_first_name"
|
||||||
t.string "mandataire_last_name"
|
t.string "mandataire_last_name"
|
||||||
t.text "motivation"
|
t.text "motivation"
|
||||||
|
t.datetime "notified_soon_deleted_sent_at", precision: nil
|
||||||
t.bigint "parent_dossier_id"
|
t.bigint "parent_dossier_id"
|
||||||
t.string "prefill_token"
|
t.string "prefill_token"
|
||||||
t.boolean "prefilled"
|
t.boolean "prefilled"
|
||||||
|
|
24
spec/jobs/cron/notify_old_brouillon_dossiers_job_spec.rb
Normal file
24
spec/jobs/cron/notify_old_brouillon_dossiers_job_spec.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Cron::NotifyOldBrouillonDossiersSoonDeletedJob, type: :job do
|
||||||
|
let(:procedure) { create(:procedure) }
|
||||||
|
|
||||||
|
let!(:recent_brouillon) { create(:dossier, :brouillon, procedure: procedure, updated_at: 2.months.ago) }
|
||||||
|
let!(:old_brouillon) { create(:dossier, :brouillon, procedure: procedure, updated_at: 4.months.ago) }
|
||||||
|
let!(:old_en_construction) { create(:dossier, :en_construction, procedure: procedure, updated_at: 4.months.ago) }
|
||||||
|
|
||||||
|
subject(:perform_job) { described_class.perform_now }
|
||||||
|
|
||||||
|
describe '#perform' do
|
||||||
|
before do
|
||||||
|
allow(DossierMailer).to receive(:notify_old_brouillon_soon_deleted).and_return(double(deliver_later: true))
|
||||||
|
perform_job
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sends email only for old brouillon dossiers' do
|
||||||
|
expect(DossierMailer).to have_received(:notify_old_brouillon_soon_deleted).with(old_brouillon).once
|
||||||
|
expect(DossierMailer).not_to have_received(:notify_old_brouillon_soon_deleted).with(recent_brouillon)
|
||||||
|
expect(DossierMailer).not_to have_received(:notify_old_brouillon_soon_deleted).with(old_en_construction)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,53 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Cron::NotifyOldBrouillonDossiersSoonDeletedJob, type: :job do
|
||||||
|
describe "#perform" do
|
||||||
|
let(:job) { described_class.new }
|
||||||
|
|
||||||
|
context "when there are old draft dossiers" do
|
||||||
|
let!(:old_draft_never_notified) { travel_to(4.months.ago) { create(:dossier, :brouillon) } }
|
||||||
|
let!(:old_draft_notified_before_update) do
|
||||||
|
travel_to(4.months.ago) do
|
||||||
|
create(:dossier, :brouillon, notified_soon_deleted_sent_at: 1.month.ago)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let!(:old_draft_recently_notified) do
|
||||||
|
travel_to(4.months.ago) do
|
||||||
|
create(:dossier, :brouillon, notified_soon_deleted_sent_at: 3.months.from_now)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let!(:recent_draft) { travel_to(2.months.ago) { create(:dossier, :brouillon) } }
|
||||||
|
let!(:old_non_draft) { travel_to(4.months.ago) { create(:dossier, :en_construction) } }
|
||||||
|
|
||||||
|
it "sends notifications only for eligible draft dossiers" do
|
||||||
|
expect(DossierMailer).to receive(:notify_old_brouillon_soon_deleted)
|
||||||
|
.with(old_draft_never_notified)
|
||||||
|
.and_return(double(deliver_later: true))
|
||||||
|
.once
|
||||||
|
|
||||||
|
expect(DossierMailer).to receive(:notify_old_brouillon_soon_deleted)
|
||||||
|
.with(old_draft_notified_before_update)
|
||||||
|
.and_return(double(deliver_later: true))
|
||||||
|
.once
|
||||||
|
|
||||||
|
expect(DossierMailer).not_to receive(:notify_old_brouillon_soon_deleted)
|
||||||
|
.with(old_draft_recently_notified)
|
||||||
|
|
||||||
|
job.perform
|
||||||
|
|
||||||
|
expect(old_draft_never_notified.reload.notified_soon_deleted_sent_at).to be_present
|
||||||
|
expect(old_draft_notified_before_update.reload.notified_soon_deleted_sent_at).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there are no old draft dossiers" do
|
||||||
|
let!(:recent_draft) { create(:dossier, :brouillon, updated_at: 2.months.ago) }
|
||||||
|
|
||||||
|
it "doesn't send any notifications" do
|
||||||
|
expect(DossierMailer).not_to receive(:notify_old_brouillon_soon_deleted)
|
||||||
|
|
||||||
|
job.perform
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -382,4 +382,72 @@ RSpec.describe DossierMailer, type: :mailer do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.notify_old_brouillon_soon_deleted' do
|
||||||
|
let(:procedure) { create(:procedure, libelle: 'Une superbe démarche') }
|
||||||
|
let(:dossier) { create(:dossier, :brouillon, procedure: procedure) }
|
||||||
|
|
||||||
|
subject { described_class.notify_old_brouillon_soon_deleted(dossier) }
|
||||||
|
|
||||||
|
it 'renders the subject' do
|
||||||
|
expect(subject.subject).to eq("Votre dossier n°#{dossier.id} en brouillon va bientôt être supprimé")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders the receiver email' do
|
||||||
|
expect(subject.to).to eq([dossier.user.email])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes dossier information in body' do
|
||||||
|
expect(subject.body).to include(dossier.id.to_s)
|
||||||
|
expect(subject.body).to include(dossier.procedure.libelle)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes the dossier URL' do
|
||||||
|
expect(subject.body).to include(dossier_url(dossier, host: ENV.fetch("APP_HOST_LEGACY")))
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a different locale' do
|
||||||
|
let(:dossier) { create(:dossier, :brouillon, procedure: procedure) }
|
||||||
|
before { dossier.user.update(locale: :en) }
|
||||||
|
|
||||||
|
it 'renders in the user locale' do
|
||||||
|
expect(subject.body).to include('Access my dossier')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.notify_old_brouillon_after_deletion' do
|
||||||
|
let(:procedure) { create(:procedure, libelle: 'Une superbe démarche') }
|
||||||
|
let(:dossier) { create(:dossier, :brouillon, procedure: procedure) }
|
||||||
|
|
||||||
|
subject { described_class.notify_old_brouillon_after_deletion(dossier) }
|
||||||
|
|
||||||
|
it 'renders the subject' do
|
||||||
|
expect(subject.subject).to eq("Votre dossier n°#{dossier.id} en brouillon a été supprimé pour cause d'inactivité")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders the receiver email' do
|
||||||
|
expect(subject.to).to eq([dossier.user.email])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes dossier information in body' do
|
||||||
|
expect(subject.body).to include(dossier.id.to_s)
|
||||||
|
expect(subject.body).to include(dossier.procedure.libelle)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes link to create new dossier' do
|
||||||
|
expect(subject.body).to include(commencer_url(dossier.procedure, host: ENV.fetch("APP_HOST_LEGACY")))
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a different locale' do
|
||||||
|
let(:dossier) { create(:dossier, :brouillon, procedure: procedure) }
|
||||||
|
before { dossier.user.update(locale: :en) }
|
||||||
|
|
||||||
|
it 'renders in the user locale' do
|
||||||
|
expect(subject.subject).to include("has been deleted due to inactivity")
|
||||||
|
expect(subject.body).to include("has been automatically deleted")
|
||||||
|
expect(subject.body).to include("submit a new application")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue