feat(dossiers): enable dossiers termine expiration behind feature flag
feature flag "procedure_process_expired_dossiers_termine" controls if a procedure has expiration enabled on dossiers termine re #3796
This commit is contained in:
parent
d67778a636
commit
ffa8c0c80a
8 changed files with 64 additions and 12 deletions
|
@ -4,5 +4,6 @@ class Cron::ExpiredDossiersDeletionJob < Cron::CronJob
|
||||||
def perform(*args)
|
def perform(*args)
|
||||||
ExpiredDossiersDeletionService.process_expired_dossiers_brouillon
|
ExpiredDossiersDeletionService.process_expired_dossiers_brouillon
|
||||||
ExpiredDossiersDeletionService.process_expired_dossiers_en_construction
|
ExpiredDossiersDeletionService.process_expired_dossiers_en_construction
|
||||||
|
ExpiredDossiersDeletionService.process_expired_dossiers_termine
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -79,7 +79,37 @@ class Dossier < ApplicationRecord
|
||||||
has_many :previous_followers_instructeurs, -> { distinct }, through: :previous_follows, source: :instructeur
|
has_many :previous_followers_instructeurs, -> { distinct }, through: :previous_follows, source: :instructeur
|
||||||
has_many :avis, inverse_of: :dossier, dependent: :destroy
|
has_many :avis, inverse_of: :dossier, dependent: :destroy
|
||||||
has_many :experts, through: :avis
|
has_many :experts, through: :avis
|
||||||
has_many :traitements, -> { order(:processed_at) }, inverse_of: :dossier, dependent: :destroy
|
has_many :traitements, -> { order(:processed_at) }, inverse_of: :dossier, dependent: :destroy do
|
||||||
|
def accepter_automatiquement(processed_at: Time.zone.now)
|
||||||
|
build(state: Dossier.states.fetch(:accepte),
|
||||||
|
process_expired: proxy_association.owner.procedure.feature_enabled?(:procedure_process_expired_dossiers_termine),
|
||||||
|
processed_at: processed_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
def accepter(motivation: nil, instructeur: nil, processed_at: Time.zone.now)
|
||||||
|
build(state: Dossier.states.fetch(:accepte),
|
||||||
|
instructeur_email: instructeur&.email,
|
||||||
|
motivation: motivation,
|
||||||
|
process_expired: proxy_association.owner.procedure.feature_enabled?(:procedure_process_expired_dossiers_termine),
|
||||||
|
processed_at: processed_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
def refuser(motivation: nil, instructeur: nil, processed_at: Time.zone.now)
|
||||||
|
build(state: Dossier.states.fetch(:refuse),
|
||||||
|
instructeur_email: instructeur&.email,
|
||||||
|
motivation: motivation,
|
||||||
|
process_expired: proxy_association.owner.procedure.feature_enabled?(:procedure_process_expired_dossiers_termine),
|
||||||
|
processed_at: processed_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
def classer_sans_suite(motivation: nil, instructeur: nil, processed_at: Time.zone.now)
|
||||||
|
build(state: Dossier.states.fetch(:sans_suite),
|
||||||
|
instructeur_email: instructeur&.email,
|
||||||
|
motivation: motivation,
|
||||||
|
process_expired: proxy_association.owner.procedure.feature_enabled?(:procedure_process_expired_dossiers_termine),
|
||||||
|
processed_at: processed_at)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
has_many :dossier_operation_logs, -> { order(:created_at) }, inverse_of: :dossier
|
has_many :dossier_operation_logs, -> { order(:created_at) }, inverse_of: :dossier
|
||||||
|
|
||||||
|
@ -271,7 +301,7 @@ class Dossier < ApplicationRecord
|
||||||
scope :termine_close_to_expiration, -> do
|
scope :termine_close_to_expiration, -> do
|
||||||
state_termine
|
state_termine
|
||||||
.joins(:procedure)
|
.joins(:procedure)
|
||||||
.where(id: Traitement.termine_close_to_expiration.pluck(:dossier_id).uniq)
|
.where(id: Traitement.termine_close_to_expiration.select(:dossier_id).distinct)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope :brouillon_expired, -> do
|
scope :brouillon_expired, -> do
|
||||||
|
@ -676,7 +706,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_accepter(instructeur, motivation, justificatif = nil)
|
def after_accepter(instructeur, motivation, justificatif = nil)
|
||||||
self.traitements.build(state: Dossier.states.fetch(:accepte), instructeur_email: instructeur.email, motivation: motivation, processed_at: Time.zone.now)
|
self.traitements.accepter(motivation: motivation, instructeur: instructeur)
|
||||||
|
|
||||||
if justificatif
|
if justificatif
|
||||||
self.justificatif_motivation.attach(justificatif)
|
self.justificatif_motivation.attach(justificatif)
|
||||||
|
@ -694,7 +724,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_accepter_automatiquement
|
def after_accepter_automatiquement
|
||||||
self.traitements.build(state: Dossier.states.fetch(:accepte), instructeur_email: nil, motivation: nil, processed_at: Time.zone.now)
|
self.traitements.accepter_automatiquement
|
||||||
self.en_instruction_at ||= Time.zone.now
|
self.en_instruction_at ||= Time.zone.now
|
||||||
self.declarative_triggered_at = Time.zone.now
|
self.declarative_triggered_at = Time.zone.now
|
||||||
|
|
||||||
|
@ -709,7 +739,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_refuser(instructeur, motivation, justificatif = nil)
|
def after_refuser(instructeur, motivation, justificatif = nil)
|
||||||
self.traitements.build(state: Dossier.states.fetch(:refuse), instructeur_email: instructeur.email, motivation: motivation, processed_at: Time.zone.now)
|
self.traitements.refuser(motivation: motivation, instructeur: instructeur)
|
||||||
|
|
||||||
if justificatif
|
if justificatif
|
||||||
self.justificatif_motivation.attach(justificatif)
|
self.justificatif_motivation.attach(justificatif)
|
||||||
|
@ -723,7 +753,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_classer_sans_suite(instructeur, motivation, justificatif = nil)
|
def after_classer_sans_suite(instructeur, motivation, justificatif = nil)
|
||||||
self.traitements.build(state: Dossier.states.fetch(:sans_suite), instructeur_email: instructeur.email, motivation: motivation, processed_at: Time.zone.now)
|
self.traitements.classer_sans_suite(motivation: motivation, instructeur: instructeur)
|
||||||
|
|
||||||
if justificatif
|
if justificatif
|
||||||
self.justificatif_motivation.attach(justificatif)
|
self.justificatif_motivation.attach(justificatif)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
# id :bigint not null, primary key
|
# id :bigint not null, primary key
|
||||||
# instructeur_email :string
|
# instructeur_email :string
|
||||||
# motivation :string
|
# motivation :string
|
||||||
|
# process_expired :boolean
|
||||||
# processed_at :datetime
|
# processed_at :datetime
|
||||||
# state :string
|
# state :string
|
||||||
# dossier_id :bigint
|
# dossier_id :bigint
|
||||||
|
@ -15,6 +16,7 @@ class Traitement < ApplicationRecord
|
||||||
scope :termine_close_to_expiration, -> do
|
scope :termine_close_to_expiration, -> do
|
||||||
joins(dossier: :procedure)
|
joins(dossier: :procedure)
|
||||||
.where(state: Dossier::TERMINE)
|
.where(state: Dossier::TERMINE)
|
||||||
|
.where(process_expired: true)
|
||||||
.where('dossiers.state' => Dossier::TERMINE)
|
.where('dossiers.state' => Dossier::TERMINE)
|
||||||
.where("traitements.processed_at + (procedures.duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now", { now: Time.zone.now, expires_in: Dossier::INTERVAL_BEFORE_EXPIRATION })
|
.where("traitements.processed_at + (procedures.duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now", { now: Time.zone.now, expires_in: Dossier::INTERVAL_BEFORE_EXPIRATION })
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,7 +33,8 @@ features = [
|
||||||
:instructeur_bypass_email_login_token,
|
:instructeur_bypass_email_login_token,
|
||||||
:make_experts_notifiable,
|
:make_experts_notifiable,
|
||||||
:procedure_revisions,
|
:procedure_revisions,
|
||||||
:procedure_routage_api
|
:procedure_routage_api,
|
||||||
|
:procedure_process_expired_dossiers_termine
|
||||||
]
|
]
|
||||||
|
|
||||||
def database_exists?
|
def database_exists?
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
class AddProcessExpiredToTraitements < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
add_column :traitements, :process_expired, :boolean
|
||||||
|
add_index :traitements, :process_expired
|
||||||
|
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.define(version: 2021_07_27_172504) do
|
ActiveRecord::Schema.define(version: 2021_08_18_083349) 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 "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -695,7 +695,9 @@ ActiveRecord::Schema.define(version: 2021_07_27_172504) do
|
||||||
t.string "state"
|
t.string "state"
|
||||||
t.datetime "processed_at"
|
t.datetime "processed_at"
|
||||||
t.string "instructeur_email"
|
t.string "instructeur_email"
|
||||||
|
t.boolean "process_expired"
|
||||||
t.index ["dossier_id"], name: "index_traitements_on_dossier_id"
|
t.index ["dossier_id"], name: "index_traitements_on_dossier_id"
|
||||||
|
t.index ["process_expired"], name: "index_traitements_on_process_expired"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "trusted_device_tokens", force: :cascade do |t|
|
create_table "trusted_device_tokens", force: :cascade do |t|
|
||||||
|
|
|
@ -146,11 +146,11 @@ FactoryBot.define do
|
||||||
if processed_at.present?
|
if processed_at.present?
|
||||||
dossier.en_construction_at ||= processed_at - 2.minutes
|
dossier.en_construction_at ||= processed_at - 2.minutes
|
||||||
dossier.en_instruction_at ||= processed_at - 1.minute
|
dossier.en_instruction_at ||= processed_at - 1.minute
|
||||||
dossier.traitements.build(state: Dossier.states.fetch(:accepte), processed_at: processed_at, motivation: evaluator.motivation)
|
dossier.traitements.accepter(motivation: evaluator.motivation, processed_at: processed_at)
|
||||||
else
|
else
|
||||||
dossier.en_construction_at ||= dossier.created_at + 1.minute
|
dossier.en_construction_at ||= dossier.created_at + 1.minute
|
||||||
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
|
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
|
||||||
dossier.traitements.build(state: Dossier.states.fetch(:accepte), processed_at: dossier.en_instruction_at + 1.minute, motivation: evaluator.motivation)
|
dossier.traitements.accepter(motivation: evaluator.motivation, processed_at: dossier.en_instruction_at + 1.minute)
|
||||||
end
|
end
|
||||||
dossier.save!
|
dossier.save!
|
||||||
end
|
end
|
||||||
|
@ -162,7 +162,7 @@ FactoryBot.define do
|
||||||
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
|
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
|
||||||
dossier.en_construction_at ||= dossier.created_at + 1.minute
|
dossier.en_construction_at ||= dossier.created_at + 1.minute
|
||||||
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
|
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
|
||||||
dossier.traitements.build(state: Dossier.states.fetch(:refuse), processed_at: dossier.en_instruction_at + 1.minute)
|
dossier.traitements.refuser(processed_at: dossier.en_instruction_at + 1.minute)
|
||||||
dossier.save!
|
dossier.save!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -173,7 +173,7 @@ FactoryBot.define do
|
||||||
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
|
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
|
||||||
dossier.en_construction_at ||= dossier.created_at + 1.minute
|
dossier.en_construction_at ||= dossier.created_at + 1.minute
|
||||||
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
|
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
|
||||||
dossier.traitements.build(state: Dossier.states.fetch(:sans_suite), processed_at: dossier.en_instruction_at + 1.minute)
|
dossier.traitements.classer_sans_suite(processed_at: dossier.en_instruction_at + 1.minute)
|
||||||
dossier.save!
|
dossier.save!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -274,6 +274,11 @@ describe ExpiredDossiersDeletionService do
|
||||||
before { Timecop.freeze(reference_date) }
|
before { Timecop.freeze(reference_date) }
|
||||||
after { Timecop.return }
|
after { Timecop.return }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Flipper.enable(:procedure_process_expired_dossiers_termine, procedure)
|
||||||
|
Flipper.enable(:procedure_process_expired_dossiers_termine, procedure_2)
|
||||||
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(DossierMailer).to receive(:notify_near_deletion_to_user).and_call_original
|
allow(DossierMailer).to receive(:notify_near_deletion_to_user).and_call_original
|
||||||
allow(DossierMailer).to receive(:notify_near_deletion_to_administration).and_call_original
|
allow(DossierMailer).to receive(:notify_near_deletion_to_administration).and_call_original
|
||||||
|
@ -343,6 +348,11 @@ describe ExpiredDossiersDeletionService do
|
||||||
before { Timecop.freeze(reference_date) }
|
before { Timecop.freeze(reference_date) }
|
||||||
after { Timecop.return }
|
after { Timecop.return }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Flipper.enable(:procedure_process_expired_dossiers_termine, procedure)
|
||||||
|
Flipper.enable(:procedure_process_expired_dossiers_termine, procedure_2)
|
||||||
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(DossierMailer).to receive(:notify_automatic_deletion_to_user).and_call_original
|
allow(DossierMailer).to receive(:notify_automatic_deletion_to_user).and_call_original
|
||||||
allow(DossierMailer).to receive(:notify_automatic_deletion_to_administration).and_call_original
|
allow(DossierMailer).to receive(:notify_automatic_deletion_to_administration).and_call_original
|
||||||
|
|
Loading…
Reference in a new issue