diff --git a/app/jobs/auto_archive_procedure_dossiers_job.rb b/app/jobs/auto_archive_procedure_dossiers_job.rb index 44b3387ab5f..ea66992c325 100644 --- a/app/jobs/auto_archive_procedure_dossiers_job.rb +++ b/app/jobs/auto_archive_procedure_dossiers_job.rb @@ -6,6 +6,8 @@ def perform(procedure) .dossiers .state_en_construction .find_each do |d| + next unless d.may_passer_automatiquement_en_instruction? + begin d.passer_automatiquement_en_instruction! rescue StandardError => e diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 5646e528a65..d24ac859433 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -548,9 +548,7 @@ def can_passer_en_instruction? end def can_passer_automatiquement_en_instruction? - # Auto archive always passe en instruction, even if there is a pending correction - return true if procedure.auto_archive_on? && !procedure.auto_archive_on.future? - + return true if procedure.auto_archive_on? && !procedure.auto_archive_on.future? && !pending_correction? return false if !can_passer_en_instruction? return true if declarative_triggered_at.nil? && procedure.declarative_en_instruction? return true if procedure.sva_svr_enabled? && sva_svr_decision_triggered_at.nil? && !pending_correction? diff --git a/app/tasks/maintenance/t20250226_fix_dossiers_en_instruction_with_pending_correction_task.rb b/app/tasks/maintenance/t20250226_fix_dossiers_en_instruction_with_pending_correction_task.rb new file mode 100644 index 00000000000..2d512fbe523 --- /dev/null +++ b/app/tasks/maintenance/t20250226_fix_dossiers_en_instruction_with_pending_correction_task.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Maintenance + class T20250226FixDossiersEnInstructionWithPendingCorrectionTask < MaintenanceTasks::Task + # Cette tâche traite les dossiers en instruction avec une correction en attente pour les repasser en construction. + + include RunnableOnDeployConcern + include StatementsHelpersConcern + + attribute :procedure_id, :string + validates :procedure_id, presence: true + + def collection + Procedure.find(procedure_id) + .dossiers + .state_en_instruction + .with_pending_corrections + end + + def process(dossier) + Dossier.transaction do + correction = dossier.pending_correction + dossier.resolve_pending_correction + + dossier.repasser_en_construction!(instructeur: correction.commentaire.instructeur) + + correction.update!(resolved_at: nil) + end + rescue => e + Rails.logger.error("Failed to process dossier #{dossier.id}: #{e.message}") + Sentry.capture_exception(e, dossier: dossier.id) + end + end +end diff --git a/spec/jobs/auto_archive_procedure_dossiers_job_spec.rb b/spec/jobs/auto_archive_procedure_dossiers_job_spec.rb index 45423ea1e87..46de5db8459 100644 --- a/spec/jobs/auto_archive_procedure_dossiers_job_spec.rb +++ b/spec/jobs/auto_archive_procedure_dossiers_job_spec.rb @@ -18,12 +18,15 @@ let!(:dossier6) { create(:dossier, :accepte, procedure: procedure) } let!(:dossier7) { create(:dossier, :refuse, procedure: procedure) } let!(:dossier8) { create(:dossier, :sans_suite, procedure: procedure) } + let!(:dossier9) { create(:dossier, :en_construction, procedure: procedure) } let(:last_operation) { dossier2.dossier_operation_logs.last } before do + dossier9.flag_as_pending_correction!(build(:commentaire)) + subject - [dossier1, dossier2, dossier3, dossier4, dossier5, dossier6, dossier7, dossier8].each(&:reload) + [dossier1, dossier2, dossier3, dossier4, dossier5, dossier6, dossier7, dossier8, dossier9].each(&:reload) procedure.reload end @@ -39,6 +42,7 @@ expect(dossier6.state).to eq Dossier.states.fetch(:accepte) expect(dossier7.state).to eq Dossier.states.fetch(:refuse) expect(dossier8.state).to eq Dossier.states.fetch(:sans_suite) + expect(dossier9.state).to eq Dossier.states.fetch(:en_construction) } end end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index ff6bf7b55bb..37fcb6bd552 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -1451,8 +1451,8 @@ context 'when there are pending correction' do before { create(:dossier_correction, dossier:) } - it "passes en instruction and keep the correction request" do - expect(dossier.can_passer_automatiquement_en_instruction?).to be_truthy + it "can't passe en instruction" do + expect(dossier.can_passer_automatiquement_en_instruction?).to be_falsey expect(dossier.pending_correction?).to be_truthy end end diff --git a/spec/tasks/maintenance/t20250226_fix_dossiers_en_instruction_with_pending_correction_task_spec.rb b/spec/tasks/maintenance/t20250226_fix_dossiers_en_instruction_with_pending_correction_task_spec.rb new file mode 100644 index 00000000000..df81f1ae5df --- /dev/null +++ b/spec/tasks/maintenance/t20250226_fix_dossiers_en_instruction_with_pending_correction_task_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require "rails_helper" + +module Maintenance + RSpec.describe T20250226FixDossiersEnInstructionWithPendingCorrectionTask do + let(:instructeur) { create(:instructeur) } + let(:dossier) { create(:dossier, :en_instruction) } + let(:commentaire) { create(:commentaire, dossier:, instructeur:) } + + before do + dossier.flag_as_pending_correction!(commentaire) + dossier.update(state: "en_instruction") + end + + describe "#process" do + subject(:process) { described_class.process(dossier) } + + it "repasse le dossier en construction avec la correction toujours en attente" do + expect(dossier).to be_en_instruction + expect(dossier.corrections.one?(&:pending?)).to be_truthy + process + dossier.reload + expect(dossier).to be_en_construction + expect(dossier.corrections.one?(&:pending?)).to be_truthy + end + + it "does not send any email" do + expect { perform_enqueued_jobs { process } }.not_to change { ActionMailer::Base.deliveries.count } + end + + it "creates operation log" do + expect { process }.to change { DossierOperationLog.count }.by(1) + log = DossierOperationLog.last + expect(log.data["author"]).to eq(DossierOperationLog.serialize_author(instructeur)) + expect(log).to be_repasser_en_construction + end + + context "when something fails during transaction" do + before do + allow(dossier).to receive(:repasser_en_construction!).and_raise("boom") + end + + it "rolls back all changes" do + expect(dossier).to be_en_instruction + process + dossier.reload + expect(dossier).to be_en_instruction + expect(dossier.corrections.one?(&:pending?)).to be_truthy + end + end + end + end +end