commit
14095864f4
46 changed files with 766 additions and 307 deletions
2
Gemfile
2
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'
|
||||
|
|
74
Gemfile.lock
74
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
|
||||
|
|
|
@ -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.'
|
||||
|
||||
|
@ -198,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?
|
||||
store_location_for(:user, request.fullpath)
|
||||
end
|
||||
|
||||
send_login_token_or_bufferize(current_instructeur)
|
||||
redirect_to link_sent_path(email: current_instructeur.email)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class InvitesController < ApplicationController
|
||||
include Devise::StoreLocationExtension
|
||||
|
||||
before_action :authenticate_user!, only: [:create]
|
||||
before_action :store_user_location!, only: [:show]
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
module Users
|
||||
class DossiersController < UserController
|
||||
include Devise::StoreLocationExtension
|
||||
include DossierHelper
|
||||
|
||||
layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret]
|
||||
|
|
|
@ -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;
|
||||
|
|
7
app/jobs/expired_dossiers_deletion_job.rb
Normal file
7
app/jobs/expired_dossiers_deletion_job.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class ExpiredDossiersDeletionJob < ApplicationJob
|
||||
queue_as :cron
|
||||
|
||||
def perform(*args)
|
||||
ExpiredDossiersDeletionService.process_expired_dossiers_brouillon
|
||||
end
|
||||
end
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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(user, 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: user.email, subject: @subject)
|
||||
mail(to: to_email, subject: @subject)
|
||||
end
|
||||
|
||||
def notify_automatic_deletion_to_administration(user, 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: user.email, subject: @subject)
|
||||
mail(to: to_email, subject: @subject)
|
||||
end
|
||||
|
||||
def notify_en_construction_near_deletion(user, 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: user.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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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: []) }
|
||||
|
@ -669,36 +680,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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
110
app/services/expired_dossiers_deletion_service.rb
Normal file
110
app/services/expired_dossiers_deletion_service.rb
Normal file
|
@ -0,0 +1,110 @@
|
|||
class ExpiredDossiersDeletionService
|
||||
def self.process_expired_dossiers_brouillon
|
||||
send_brouillon_expiration_notices
|
||||
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
|
||||
|
||||
def self.send_brouillon_expiration_notices
|
||||
dossiers_close_to_expiration = Dossier
|
||||
.brouillon_close_to_expiration
|
||||
.without_brouillon_expiration_notice_sent
|
||||
|
||||
dossiers_close_to_expiration
|
||||
.includes(:user, :procedure)
|
||||
.group_by(&:user)
|
||||
.each do |(user, dossiers)|
|
||||
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)
|
||||
end
|
||||
|
||||
def self.send_en_construction_expiration_notices
|
||||
dossiers_close_to_expiration = Dossier
|
||||
.en_construction_close_to_expiration
|
||||
.without_en_construction_expiration_notice_sent
|
||||
|
||||
dossiers_close_to_expiration
|
||||
.includes(:user)
|
||||
.group_by(&:user)
|
||||
.each do |(user, dossiers)|
|
||||
DossierMailer.notify_en_construction_near_deletion_to_user(
|
||||
dossiers,
|
||||
user.email
|
||||
).deliver_later
|
||||
end
|
||||
|
||||
group_by_fonctionnaire_email(dossiers_close_to_expiration).each do |(email, dossiers)|
|
||||
DossierMailer.notify_en_construction_near_deletion_to_administration(
|
||||
dossiers,
|
||||
email
|
||||
).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
|
||||
dossiers_to_remove = Dossier.brouillon_expired
|
||||
|
||||
dossiers_to_remove
|
||||
.includes(:user, :procedure)
|
||||
.group_by(&:user)
|
||||
.each do |(user, dossiers)|
|
||||
DossierMailer.notify_brouillon_deletion(
|
||||
dossiers.map(&:hash_for_deletion_mail),
|
||||
user.email
|
||||
).deliver_later
|
||||
end
|
||||
|
||||
dossiers_to_remove.each do |dossier|
|
||||
DeletedDossier.create_from_dossier(dossier)
|
||||
dossier.destroy
|
||||
end
|
||||
end
|
||||
|
||||
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(
|
||||
DeletedDossier.where(dossier_id: dossiers.map(&:id)),
|
||||
user.email
|
||||
).deliver_later
|
||||
end
|
||||
|
||||
self.group_by_fonctionnaire_email(dossiers_to_remove).each do |(email, dossiers)|
|
||||
DossierMailer.notify_automatic_deletion_to_administration(
|
||||
DeletedDossier.where(dossier_id: dossiers.map(&:id)),
|
||||
email
|
||||
).deliver_later
|
||||
end
|
||||
|
||||
dossiers_to_remove.destroy_all
|
||||
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
|
|
@ -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"
|
||||
|
|
|
@ -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= link_to("n° #{d[:id]} (#{d[:procedure_libelle]})", dossier_url(d))
|
||||
|
||||
%p= t('.dossier_will_not_be_processed', count: @dossier_hashes.count)
|
||||
%p= t('.footer', count: @deleted_dossiers.count)
|
||||
|
||||
= render partial: "layouts/mailers/signature"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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,
|
||||
|
|
|
@ -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 :"
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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 :"
|
||||
|
|
|
@ -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 <b>un mois</b>"
|
||||
other: "Si vous souhaitez toujours déposer ces dossiers, vous pouvez retrouver vos brouillons pendant encore <b>un mois</b>"
|
||||
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 <b>un mois</b>. Et sinon, vous n’avez rien à faire."
|
||||
other: "Si vous souhaitez toujours déposer ces dossiers, vous pouvez retrouver vos brouillons pendant encore <b>un mois</b>. Et sinon, vous n’avez rien à faire."
|
||||
|
|
|
@ -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é.
|
|
@ -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.
|
|
@ -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 <b>un mois</b>. Vous n'avez rien à faire."
|
||||
other: "Vous pouvez retrouver vos dossiers pendant encore <b>un mois</b>. Vous n'avez rien à faire."
|
||||
send_other_draft:
|
||||
one: "Vous avez <b>un mois</b> pour traiter le dossier."
|
||||
other: "Vous avez <b>un mois</b> pour traiter les dossiers."
|
|
@ -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 <b>un mois</b> pour commencer l'instruction du dossier."
|
||||
other: "Vous avez <b>un mois</b> pour commencer l'instruction des dossiers."
|
|
@ -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 <b>un mois</b>. Vous n’avez rien à faire."
|
||||
other: "Vous pouvez retrouver vos dossiers pendant encore <b>un mois</b>. Vous n’avez rien à faire."
|
|
@ -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
|
|
@ -250,9 +250,10 @@ ActiveRecord::Schema.define(version: 2020_03_04_155418) do
|
|||
t.text "private_search_terms"
|
||||
t.bigint "groupe_instructeur_id"
|
||||
t.datetime "brouillon_close_to_expiration_notice_sent_at"
|
||||
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.datetime "groupe_instructeur_updated_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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,14 +98,16 @@ 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, [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") }
|
||||
it { expect(subject.body).to include("n° #{dossier.id} ") }
|
||||
it { expect(subject.body).to include(dossier.procedure.libelle) }
|
||||
|
@ -114,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})") }
|
||||
|
@ -129,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, [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 <b>un mois</b>. Vous n'avez rien à faire.") }
|
||||
it { expect(subject.body).to include("Vous avez <b>un mois</b> pour commencer l'instruction du dossier.") }
|
||||
end
|
||||
|
||||
describe '.notify_en_construction_near_deletion_to_user' do
|
||||
|
@ -146,13 +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, [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 <b>un mois</b> pour traiter le dossier.") }
|
||||
it { expect(subject.body).to include("Vous pouvez retrouver votre dossier pendant encore <b>un mois</b>. Vous n’avez rien à faire.") }
|
||||
end
|
||||
|
||||
describe '.notify_groupe_instructeur_changed_to_instructeur' do
|
||||
|
|
|
@ -8,37 +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
|
||||
DossierMailer.notify_automatic_deletion_to_user([deleted_dossier, deleted_dossier], usager_email)
|
||||
end
|
||||
|
||||
def notify_automatic_deletion_to_administration
|
||||
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
|
||||
|
@ -52,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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -1072,60 +1097,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" }
|
||||
|
|
|
@ -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
|
||||
|
|
280
spec/services/expired_dossiers_deletion_service_spec.rb
Normal file
280
spec/services/expired_dossiers_deletion_service_spec.rb
Normal file
|
@ -0,0 +1,280 @@
|
|||
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], brouillon_close_to_expiration.user.email)
|
||||
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.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
|
||||
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], dossier.user.email) }
|
||||
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(match_array([dossier_1, dossier_2]), user.email) }
|
||||
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.hash_for_deletion_mail], dossier.user.email) }
|
||||
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(match_array([dossier_1.hash_for_deletion_mail, dossier_2.hash_for_deletion_mail]), user.email) }
|
||||
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_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
|
||||
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_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
|
||||
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_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
|
||||
|
||||
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_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
|
||||
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_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
|
||||
|
||||
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) }
|
||||
let(:deleted_dossier) { DeletedDossier.find_by(dossier_id: dossier.id) }
|
||||
|
||||
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([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([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
|
||||
|
||||
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(: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) }
|
||||
|
||||
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(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(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
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue