Skip to content

Commit 99e1a54

Browse files
authored
Merge pull request #11752 from demarches-simplifiees/add-expired-at-to-dossiers
ETQ Tech je veux que la date d'expiration d'un dossier soit persistée en base
2 parents 8f29e2b + c380fec commit 99e1a54

10 files changed

Lines changed: 123 additions & 17 deletions

app/jobs/reset_expiring_dossiers_job.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def perform(procedure)
1111
dossier.update(brouillon_close_to_expiration_notice_sent_at: nil,
1212
en_construction_close_to_expiration_notice_sent_at: nil,
1313
termine_close_to_expiration_notice_sent_at: nil)
14+
dossier.update_expired_at
1415
end
1516
end
1617
end

app/models/concerns/dossier_state_concern.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def after_passer_en_construction
1919
self.depose_at = self.en_construction_at = self.traitements
2020
.passer_en_construction
2121
.processed_at
22+
self.expired_at = expiration_date
2223

2324
save!
2425

@@ -52,6 +53,8 @@ def after_passer_en_instruction(h)
5253
self.en_instruction_at = self.traitements
5354
.passer_en_instruction(instructeur: instructeur)
5455
.processed_at
56+
self.expired_at = nil
57+
5558
save!
5659

5760
reset_user_buffer_stream!
@@ -77,6 +80,7 @@ def after_passer_automatiquement_en_instruction
7780
self.en_construction_close_to_expiration_notice_sent_at = nil
7881
self.conservation_extension = 0.days
7982
self.en_instruction_at = traitements.passer_en_instruction.processed_at
83+
self.expired_at = nil
8084

8185
if procedure.declarative_en_instruction?
8286
self.declarative_triggered_at = en_instruction_at
@@ -109,6 +113,7 @@ def after_repasser_en_construction(h)
109113
self.en_construction_at = self.traitements
110114
.passer_en_construction(instructeur: instructeur)
111115
.processed_at
116+
self.expired_at = expiration_date
112117

113118
save!
114119

@@ -126,6 +131,8 @@ def after_accepter(h)
126131
self.processed_at = self.traitements
127132
.accepter(motivation: motivation, instructeur: instructeur)
128133
.processed_at
134+
self.expired_at = expiration_date
135+
129136
save!
130137

131138
if justificatif
@@ -161,6 +168,7 @@ def after_commit_accepter(h)
161168

162169
def after_accepter_automatiquement
163170
self.processed_at = traitements.accepter_automatiquement.processed_at
171+
self.expired_at = expiration_date
164172

165173
if procedure.declarative_accepte?
166174
self.en_instruction_at = self.processed_at
@@ -202,6 +210,8 @@ def after_refuser(h)
202210
self.processed_at = self.traitements
203211
.refuser(motivation: motivation, instructeur: instructeur)
204212
.processed_at
213+
self.expired_at = expiration_date
214+
205215
save!
206216

207217
if justificatif
@@ -239,6 +249,7 @@ def after_refuser_automatiquement
239249

240250
self.processed_at = traitements.refuser_automatiquement(motivation:).processed_at
241251
self.sva_svr_decision_triggered_at = self.processed_at
252+
self.expired_at = expiration_date
242253

243254
save!
244255

@@ -267,6 +278,8 @@ def after_classer_sans_suite(h)
267278
self.processed_at = self.traitements
268279
.classer_sans_suite(motivation: motivation, instructeur: instructeur)
269280
.processed_at
281+
self.expired_at = expiration_date
282+
270283
save!
271284

272285
if justificatif
@@ -308,6 +321,7 @@ def after_repasser_en_instruction(h)
308321
self.en_instruction_at = self.traitements
309322
.passer_en_instruction(instructeur: instructeur)
310323
.processed_at
324+
self.expired_at = nil
311325
attestation&.destroy
312326

313327
self.sva_svr_decision_on = nil

app/models/dossier.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ def classer_sans_suite(motivation: nil, instructeur: nil, processed_at: Time.zon
429429
delegate :france_connected_with_one_identity?, to: :user, allow_nil: true
430430

431431
after_save :send_web_hook
432+
after_save :update_expired_at, if: :brouillon?
432433

433434
validates :user, presence: true, if: -> { deleted_user_email_never_send.nil? }, unless: -> { prefilled }
434435
validates :individual, presence: true, if: -> { revision.procedure.for_individual? }
@@ -669,6 +670,7 @@ def extend_conservation(conservation_extension)
669670
brouillon_close_to_expiration_notice_sent_at: nil,
670671
en_construction_close_to_expiration_notice_sent_at: nil,
671672
termine_close_to_expiration_notice_sent_at: nil)
673+
update_expired_at
672674
end
673675

674676
def extend_conservation_and_restore(conservation_extension, author)
@@ -1053,6 +1055,8 @@ def update_champs_timestamps(changed_champs)
10531055
update_columns(attributes)
10541056
end
10551057

1058+
def update_expired_at = update_column(:expired_at, expiration_date)
1059+
10561060
private
10571061

10581062
def build_default_champs
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
module Maintenance
4+
class T20250611backfillDossiersExpiredAtTask < MaintenanceTasks::Task
5+
# Documentation: cette tâche modifie les données pour remplir
6+
# le nouvel attribut expired_at de la table dossiers.
7+
8+
include RunnableOnDeployConcern
9+
include StatementsHelpersConcern
10+
11+
def collection
12+
Dossier
13+
.where.not(state: Dossier.states.fetch(:en_instruction))
14+
.where(expired_at: nil)
15+
end
16+
17+
def process(dossier)
18+
dossier.update_column(:expired_at, dossier.expiration_date)
19+
end
20+
end
21+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
class AddExpiredAtToDossiers < ActiveRecord::Migration[7.1]
4+
def change
5+
add_column :dossiers, :expired_at, :datetime
6+
end
7+
end

db/schema.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@
503503
t.datetime "en_construction_at", precision: nil
504504
t.datetime "en_construction_close_to_expiration_notice_sent_at", precision: nil
505505
t.datetime "en_instruction_at", precision: nil
506+
t.datetime "expired_at"
506507
t.boolean "for_procedure_preview", default: false, null: false
507508
t.boolean "for_tiers", default: false, null: false
508509
t.boolean "forced_groupe_instructeur", default: false, null: false

spec/controllers/users/dossiers_controller_spec.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2001,7 +2001,7 @@
20012001

20022002
describe '#extend_conservation' do
20032003
let(:procedure) { create(:procedure, duree_conservation_dossiers_dans_ds: 3) }
2004-
let(:dossier) { create(:dossier, procedure: procedure, user: user) }
2004+
let(:dossier) { create(:dossier, :en_construction, procedure:, user:) }
20052005
subject { post :extend_conservation, params: { dossier_id: dossier.id } }
20062006
context 'when user logged in' do
20072007
before { sign_in(user) }
@@ -2014,6 +2014,12 @@
20142014
expect(dossier.reload.conservation_extension).to eq(procedure.duree_conservation_dossiers_dans_ds.months)
20152015
end
20162016

2017+
it 'updates expired_at' do
2018+
expired_at = dossier.expired_at
2019+
subject
2020+
expect(dossier.reload.expired_at).to be_within(1.hour).of(expired_at + 3.months)
2021+
end
2022+
20172023
it 'flashed notice success' do
20182024
subject
20192025
expect(flash[:notice]).to eq(I18n.t('views.users.dossiers.archived_dossier', duree_conservation_dossiers_dans_ds: procedure.duree_conservation_dossiers_dans_ds))

spec/jobs/reset_expiring_dossiers_job_spec.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
expect(expiring_dossier_brouillon.reload.brouillon_close_to_expiration_notice_sent_at).to eq(nil)
1717
expect(expiring_dossier_en_construction.reload.en_construction_close_to_expiration_notice_sent_at).to eq(nil)
1818
expect(expiring_dossier_en_termine.reload.termine_close_to_expiration_notice_sent_at).to eq(nil)
19+
expect(expiring_dossier_brouillon.expired_at).to be_within(1.hour).of(2.months.from_now)
20+
expect(expiring_dossier_en_construction.expired_at).to be_within(1.hour).of(2.months.from_now)
21+
expect(expiring_dossier_en_termine.expired_at).to be_within(1.hour).of(2.months.from_now)
1922
end
2023
end
2124
end

spec/models/dossier_spec.rb

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@
495495
expect(dossier.depose_at).to eq(beginning_of_day)
496496
expect(dossier.traitement.state).to eq(Dossier.states.fetch(:en_construction))
497497
expect(dossier.traitement.processed_at).to eq(beginning_of_day)
498+
expect(dossier.expired_at).to eq(dossier.expiration_date)
498499
end
499500

500501
it 'should keep first en_construction_at date' do
@@ -592,10 +593,13 @@
592593
dossier.reload
593594
end
594595

595-
it { expect(dossier.state).to eq(Dossier.states.fetch(:en_instruction)) }
596-
it { expect(dossier.en_instruction_at).to eq(beginning_of_day) }
597-
it { expect(dossier.traitement.state).to eq(Dossier.states.fetch(:en_instruction)) }
598-
it { expect(dossier.traitement.processed_at).to eq(beginning_of_day) }
596+
it do
597+
expect(dossier.state).to eq(Dossier.states.fetch(:en_instruction))
598+
expect(dossier.en_instruction_at).to eq(beginning_of_day)
599+
expect(dossier.traitement.state).to eq(Dossier.states.fetch(:en_instruction))
600+
expect(dossier.traitement.processed_at).to eq(beginning_of_day)
601+
expect(dossier.expired_at).to be_nil
602+
end
599603

600604
it 'should keep first en_instruction_at date if dossier is set to en_construction again' do
601605
travel_back
@@ -618,10 +622,13 @@
618622
dossier.reload
619623
end
620624

621-
it { expect(dossier.state).to eq(Dossier.states.fetch(:accepte)) }
622-
it { expect(dossier.processed_at).to eq(beginning_of_day) }
623-
it { expect(dossier.traitement.state).to eq(Dossier.states.fetch(:accepte)) }
624-
it { expect(dossier.traitement.processed_at).to eq(beginning_of_day) }
625+
it do
626+
expect(dossier.state).to eq(Dossier.states.fetch(:accepte))
627+
expect(dossier.processed_at).to eq(beginning_of_day)
628+
expect(dossier.traitement.state).to eq(Dossier.states.fetch(:accepte))
629+
expect(dossier.traitement.processed_at).to eq(beginning_of_day)
630+
expect(dossier.expired_at).to eq(dossier.expiration_date)
631+
end
625632
end
626633

627634
context 'when dossier is refuse' do
@@ -632,10 +639,13 @@
632639
dossier.reload
633640
end
634641

635-
it { expect(dossier.state).to eq(Dossier.states.fetch(:refuse)) }
636-
it { expect(dossier.processed_at).to eq(beginning_of_day) }
637-
it { expect(dossier.traitement.state).to eq(Dossier.states.fetch(:refuse)) }
638-
it { expect(dossier.traitement.processed_at).to eq(beginning_of_day) }
642+
it do
643+
expect(dossier.state).to eq(Dossier.states.fetch(:refuse))
644+
expect(dossier.processed_at).to eq(beginning_of_day)
645+
expect(dossier.traitement.state).to eq(Dossier.states.fetch(:refuse))
646+
expect(dossier.traitement.processed_at).to eq(beginning_of_day)
647+
expect(dossier.expired_at).to eq(dossier.expiration_date)
648+
end
639649
end
640650

641651
context 'when dossier is sans_suite' do
@@ -646,10 +656,13 @@
646656
dossier.reload
647657
end
648658

649-
it { expect(dossier.state).to eq(Dossier.states.fetch(:sans_suite)) }
650-
it { expect(dossier.processed_at).to eq(beginning_of_day) }
651-
it { expect(dossier.traitement.state).to eq(Dossier.states.fetch(:sans_suite)) }
652-
it { expect(dossier.traitement.processed_at).to eq(beginning_of_day) }
659+
it do
660+
expect(dossier.state).to eq(Dossier.states.fetch(:sans_suite))
661+
expect(dossier.processed_at).to eq(beginning_of_day)
662+
expect(dossier.traitement.state).to eq(Dossier.states.fetch(:sans_suite))
663+
expect(dossier.traitement.processed_at).to eq(beginning_of_day)
664+
expect(dossier.expired_at).to eq(dossier.expiration_date)
665+
end
653666
end
654667
end
655668

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
require "rails_helper"
4+
5+
module Maintenance
6+
RSpec.describe T20250611backfillDossiersExpiredAtTask do
7+
describe "#process" do
8+
subject(:process) { described_class.process(dossier) }
9+
10+
context "when dossier is en brouillon" do
11+
let(:dossier) { create(:dossier, :brouillon) }
12+
before { dossier.update_column(:expired_at, nil) }
13+
14+
it "updates dossier expired_at attribute" do
15+
expect { process }.to change { dossier.reload.expired_at }.from(nil).to be_within(1.second).of(dossier.expiration_date)
16+
end
17+
end
18+
19+
context "when dossier is en construction" do
20+
let(:dossier) { create(:dossier, :en_construction) }
21+
before { dossier.update_column(:expired_at, nil) }
22+
23+
it "updates dossier expired_at attribute" do
24+
expect { process }.to change { dossier.reload.expired_at }.from(nil).to be_within(1.second).of(dossier.expiration_date)
25+
end
26+
end
27+
28+
context "when dossier is en instruction" do
29+
let(:dossier) { create(:dossier, :en_instruction) }
30+
it "raises an error" do
31+
expect { process }.to raise_error(RuntimeError, 'expiration_date_reference should not be called in state en_instruction')
32+
end
33+
end
34+
end
35+
end
36+
end

0 commit comments

Comments
 (0)