diff --git a/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml index cc7359f33a5..b5c6c728cba 100644 --- a/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml +++ b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml @@ -48,7 +48,7 @@ - menu.with_item(class: "inactive form-inside fr-pt-1v") do = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier:, visible: false, - form_path: pending_correction_instructeur_dossier_path(dossier.procedure, dossier, kind: :incomplete), + form_path: pending_correction_instructeur_dossier_path(dossier.procedure, dossier, reason: :incomplete), placeholder: 'Expliquez au demandeur comment compléter son dossier', popup_class: 'pending_completion', button_justificatif_label: "Ajouter une pièce jointe (facultatif)", diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index c101b27725a..53368c216ff 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -234,7 +234,7 @@ def pending_correction commentaire = CommentaireService.build(current_instructeur, dossier, { body: message, piece_jointe: }) if commentaire.valid? - dossier.flag_as_pending_correction!(commentaire, params[:kind].presence) + dossier.flag_as_pending_correction!(commentaire, params[:reason].presence) dossier.update!(last_commentaire_updated_at: Time.zone.now) current_instructeur.follow(dossier) diff --git a/app/models/concerns/dossier_correctable_concern.rb b/app/models/concerns/dossier_correctable_concern.rb index 7e43a6e7dea..e80e6897f7a 100644 --- a/app/models/concerns/dossier_correctable_concern.rb +++ b/app/models/concerns/dossier_correctable_concern.rb @@ -8,14 +8,14 @@ module DossierCorrectableConcern scope :with_pending_corrections, -> { joins(:corrections).where(corrections: { resolved_at: nil }) } - def flag_as_pending_correction!(commentaire, kind = nil) + def flag_as_pending_correction!(commentaire, reason = nil) return unless may_flag_as_pending_correction? - kind ||= :correction + reason ||= :incorrect - corrections.create!(commentaire:, kind:) + corrections.create!(commentaire:, reason:) - log_pending_correction_operation(commentaire, kind) if procedure.sva_svr_enabled? + log_pending_correction_operation(commentaire, reason) if procedure.sva_svr_enabled? return if en_construction? @@ -48,9 +48,9 @@ def resolve_pending_correction! private - def log_pending_correction_operation(commentaire, kind) - operation = case kind.to_sym - when :correction + def log_pending_correction_operation(commentaire, reason) + operation = case reason.to_sym + when :incorrect "demander_une_correction" when :incomplete "demander_a_completer" diff --git a/app/models/dossier_correction.rb b/app/models/dossier_correction.rb index a2752454002..c2ff19b1322 100644 --- a/app/models/dossier_correction.rb +++ b/app/models/dossier_correction.rb @@ -3,7 +3,7 @@ # Table name: dossier_corrections # # id :bigint not null, primary key -# kind :string default("correction"), not null +# reason :string default("incorrect"), not null # resolved_at :datetime # created_at :datetime not null # updated_at :datetime not null @@ -14,11 +14,13 @@ class DossierCorrection < ApplicationRecord belongs_to :dossier belongs_to :commentaire + self.ignored_columns += ['kind'] + validates_associated :commentaire scope :pending, -> { where(resolved_at: nil) } - enum kind: { correction: 'correction', incomplete: 'incomplete' } + enum reason: { incorrect: 'incorrect', incomplete: 'incomplete' }, _prefix: :dossier def resolved? resolved_at.present? diff --git a/app/services/sva_svr_decision_date_calculator_service.rb b/app/services/sva_svr_decision_date_calculator_service.rb index 93b06258e83..66614e5244f 100644 --- a/app/services/sva_svr_decision_date_calculator_service.rb +++ b/app/services/sva_svr_decision_date_calculator_service.rb @@ -47,13 +47,13 @@ def calculate_duration def determine_start_date return dossier.depose_at.to_date if dossier.corrections.empty? return latest_correction_date if resume_method == :reset - return latest_incomplete_correction_date if dossier.corrections.any?(&:incomplete?) + return latest_incomplete_correction_date if dossier.corrections.any?(&:dossier_incomplete?) dossier.depose_at.to_date end def latest_incomplete_correction_date - correction_date dossier.corrections.filter(&:incomplete?).max_by(&:resolved_at) + correction_date dossier.corrections.filter(&:dossier_incomplete?).max_by(&:resolved_at) end def latest_correction_date diff --git a/app/views/dossier_mailer/notify_pending_correction.html.haml b/app/views/dossier_mailer/notify_pending_correction.html.haml index a0163ab8e15..bd5d24603a3 100644 --- a/app/views/dossier_mailer/notify_pending_correction.html.haml +++ b/app/views/dossier_mailer/notify_pending_correction.html.haml @@ -3,12 +3,12 @@ %p= t(:hello, scope: [:views, :shared, :greetings]) -%p= t(".#{@correction.kind}.explanation_html", dossier_id: @dossier.id, libelle_demarche: @dossier.procedure.libelle) +%p= t(".#{@correction.reason}.explanation_html", dossier_id: @dossier.id, libelle_demarche: @dossier.procedure.libelle) %p= t('.link') = round_button(t('.access_message'), messagerie_dossier_url(@dossier), :primary) - if @dossier.sva_svr_decision_on.present? - %p= t(".#{@correction.kind}.sva_svr", rule_name: t(@dossier.procedure.sva? ? :sva : :svr, scope: 'shared.procedures.sva_svr_rule_name')) + %p= t(".#{@correction.reason}.sva_svr", rule_name: t(@dossier.procedure.sva? ? :sva : :svr, scope: 'shared.procedures.sva_svr_rule_name')) = render 'layouts/mailers/signature', service: @service diff --git a/config/locales/views/dossier_mailer/notify_pending_correction/en.yml b/config/locales/views/dossier_mailer/notify_pending_correction/en.yml index cd749d2df82..084b66f08f2 100644 --- a/config/locales/views/dossier_mailer/notify_pending_correction/en.yml +++ b/config/locales/views/dossier_mailer/notify_pending_correction/en.yml @@ -3,7 +3,7 @@ en: dossier_mailer: notify_pending_correction: subject: You need to modify your file no. %{dossier_id} « %{libelle_demarche} » - correction: + incorrect: explanation_html: In order to continue its instruction, an instructor requested you to edit information to your file no. %{dossier_id} of the « %{libelle_demarche} » procedure. sva_svr: diff --git a/config/locales/views/dossier_mailer/notify_pending_correction/fr.yml b/config/locales/views/dossier_mailer/notify_pending_correction/fr.yml index 8d8dcd161a8..3de37804ee2 100644 --- a/config/locales/views/dossier_mailer/notify_pending_correction/fr.yml +++ b/config/locales/views/dossier_mailer/notify_pending_correction/fr.yml @@ -3,7 +3,7 @@ fr: dossier_mailer: notify_pending_correction: subject: Vous devez corriger votre dossier nº %{dossier_id} « %{libelle_demarche} » - correction: + incorrect: explanation_html: Afin de poursuivre son instruction, un instructeur vous demande d’apporter des corrections à votre dossier nº %{dossier_id} de la démarche « %{libelle_demarche} ». sva_svr: diff --git a/db/migrate/20230712095037_add_reason_to_dossier_corrections.rb b/db/migrate/20230712095037_add_reason_to_dossier_corrections.rb new file mode 100644 index 00000000000..dcdab1f9d6d --- /dev/null +++ b/db/migrate/20230712095037_add_reason_to_dossier_corrections.rb @@ -0,0 +1,5 @@ +class AddReasonToDossierCorrections < ActiveRecord::Migration[7.0] + def change + add_column :dossier_corrections, :reason, :string, default: 'incorrect', null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 1ff80dc40e0..0f784ac3b2f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_06_29_102031) do +ActiveRecord::Schema[7.0].define(version: 2023_07_12_095037) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -324,6 +324,7 @@ t.datetime "resolved_at", precision: 6 t.datetime "updated_at", precision: 6, null: false t.string "kind", default: "correction", null: false + t.string "reason", default: "incorrect", null: false t.index ["commentaire_id"], name: "index_dossier_corrections_on_commentaire_id" t.index ["dossier_id"], name: "index_dossier_corrections_on_dossier_id" t.index ["resolved_at"], name: "index_dossier_corrections_on_resolved_at", where: "((resolved_at IS NULL) OR (resolved_at IS NOT NULL))" diff --git a/lib/tasks/deployment/20230712095348_backfill_dossier_correction_reason.rake b/lib/tasks/deployment/20230712095348_backfill_dossier_correction_reason.rake new file mode 100644 index 00000000000..9b74c041d7b --- /dev/null +++ b/lib/tasks/deployment/20230712095348_backfill_dossier_correction_reason.rake @@ -0,0 +1,14 @@ +namespace :after_party do + desc 'Deployment task: backfill_default_dossier_correction_reason' + task backfill_dossier_correction_reason: :environment do + puts "Running deploy task 'backfill_default_dossier_correction_reason'" + + DossierCorrection.where(kind: 'correction').update_all(reason: 'incorrect') + DossierCorrection.where(kind: 'incomplete').update_all(reason: 'incomplete') + + # Update task as completed. If you remove the line below, the task will + # run with every deploy (or every time you call after_party:run). + AfterParty::TaskRecord + .create version: AfterParty::TaskRecorder.new(__FILE__).timestamp + end +end diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index a180180318c..9ec643c11bb 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -503,13 +503,13 @@ describe '#pending_correction' do let(:message) { 'do that' } let(:justificatif) { nil } - let(:kind) { nil } + let(:reason) { nil } subject do post :pending_correction, params: { procedure_id: procedure.id, dossier_id: dossier.id, dossier: { motivation: message, justificatif_motivation: justificatif }, - kind: + reason: }, format: :turbo_stream end @@ -535,7 +535,7 @@ expect(dossier.reload).to be_en_construction expect(dossier).to be_pending_correction - expect(dossier.corrections.last).to be_correction + expect(dossier.corrections.last).to be_dossier_incorrect end it 'create a comment with text body' do @@ -544,10 +544,10 @@ end context 'flagged as incomplete' do - let(:kind) { 'incomplete' } + let(:reason) { 'incomplete' } - it 'create a correction of incomplete kind' do - expect(dossier.corrections.last).to be_incomplete + it 'create a correction of incomplete reason' do + expect(dossier.corrections.last).to be_dossier_incomplete end end diff --git a/spec/factories/dossier_corrections.rb b/spec/factories/dossier_corrections.rb index acad746967e..147f02a1fa2 100644 --- a/spec/factories/dossier_corrections.rb +++ b/spec/factories/dossier_corrections.rb @@ -1,8 +1,8 @@ FactoryBot.define do factory :dossier_correction do dossier - commentaire - kind { :correction } + commentaire { association :commentaire, dossier: dossier } + reason { :incorrect } resolved_at { nil } trait :resolved do diff --git a/spec/mailers/dossier_mailer_spec.rb b/spec/mailers/dossier_mailer_spec.rb index b69326f82df..c800b2083f1 100644 --- a/spec/mailers/dossier_mailer_spec.rb +++ b/spec/mailers/dossier_mailer_spec.rb @@ -233,21 +233,21 @@ def notify_deletion_to_administration(deleted_dossier, to_email) let(:procedure) { create(:procedure) } let(:dossier) { create(:dossier, :en_construction, procedure:, sva_svr_decision_on:) } let(:sva_svr_decision_on) { nil } - let(:kind) { :correction } + let(:reason) { :incorrect } let(:commentaire) { create(:commentaire, dossier:) } subject { - dossier.flag_as_pending_correction!(commentaire, kind) + dossier.flag_as_pending_correction!(commentaire, reason) described_class.with(commentaire:).notify_pending_correction } - context 'kind is correction' do + context 'reason is incorrect' do it { expect(subject.subject).to eq("Vous devez corriger votre dossier nº #{dossier.id} « #{dossier.procedure.libelle} »") } it { expect(subject.body).to include("apporter des corrections") } it { expect(subject.body).not_to include("Silence") } end - context 'sva with kind is correction' do + context 'sva with reason is incorrect' do let(:sva_svr_decision_on) { Date.tomorrow } let(:procedure) { create(:procedure, :sva) } @@ -257,9 +257,9 @@ def notify_deletion_to_administration(deleted_dossier, to_email) it { expect(subject.body).to include("suspendu") } end - context 'sva with kind is incomplete' do + context 'sva with reason is incomplete' do let(:sva_svr_decision_on) { Date.tomorrow } - let(:kind) { :incomplete } + let(:reason) { :incomplete } let(:procedure) { create(:procedure, :sva) } it { expect(subject.body).to include("compléter") } @@ -267,9 +267,9 @@ def notify_deletion_to_administration(deleted_dossier, to_email) it { expect(subject.body).to include("réinitialisé") } end - context 'svr with kind is incomplete' do + context 'svr with reason is incomplete' do let(:sva_svr_decision_on) { Date.tomorrow } - let(:kind) { :incomplete } + let(:reason) { :incomplete } let(:procedure) { create(:procedure, :svr) } it { expect(subject.body).to include("compléter") } diff --git a/spec/models/concern/dossier_correctable_concern_spec.rb b/spec/models/concern/dossier_correctable_concern_spec.rb index a18d58fc3ba..9cdee295bbc 100644 --- a/spec/models/concern/dossier_correctable_concern_spec.rb +++ b/spec/models/concern/dossier_correctable_concern_spec.rb @@ -36,12 +36,12 @@ context 'when dossier is en_construction' do it 'creates a correction' do expect { flag }.to change { dossier.corrections.pending.count }.by(1) - expect(dossier.corrections.last).to be_correction + expect(dossier.corrections.last).to be_dossier_incorrect end it 'created a correction of incomplete kind' do expect { dossier.flag_as_pending_correction!(commentaire, "incomplete") }.to change { dossier.corrections.pending.count }.by(1) - expect(dossier.corrections.last).to be_incomplete + expect(dossier.corrections.last).to be_dossier_incomplete end it 'does not change dossier state' do diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 8f26415078f..b0b734f0caa 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -1072,30 +1072,38 @@ let(:last_operation) { dossier.dossier_operation_logs.last } let(:operation_serialized) { last_operation.data } let(:instructeur) { create(:instructeur) } - let!(:correction) { create(:dossier_correction, dossier:) } + let!(:correction) { create(:dossier_correction, dossier:) } # correction has a commentaire - before { dossier.passer_en_instruction!(instructeur: instructeur) } + subject(:passer_en_instruction) { dossier.passer_en_instruction!(instructeur: instructeur) } - it { expect(dossier.state).to eq('en_instruction') } - it { expect(dossier.followers_instructeurs).to include(instructeur) } - it { expect(dossier.en_construction_close_to_expiration_notice_sent_at).to be_nil } - it { expect(last_operation.operation).to eq('passer_en_instruction') } - it { expect(last_operation.automatic_operation?).to be_falsey } - it { expect(operation_serialized['operation']).to eq('passer_en_instruction') } - it { expect(operation_serialized['dossier_id']).to eq(dossier.id) } - it { expect(operation_serialized['executed_at']).to eq(last_operation.executed_at.iso8601) } - it { expect(dossier.commentaires.count).to eq(1) } + it do + passer_en_instruction + + expect(dossier.state).to eq('en_instruction') + expect(dossier.followers_instructeurs).to include(instructeur) + expect(dossier.en_construction_close_to_expiration_notice_sent_at).to be_nil + expect(last_operation.operation).to eq('passer_en_instruction') + expect(last_operation.automatic_operation?).to be_falsey + expect(operation_serialized['operation']).to eq('passer_en_instruction') + expect(operation_serialized['dossier_id']).to eq(dossier.id) + expect(operation_serialized['executed_at']).to eq(last_operation.executed_at.iso8601) + end + + it { expect { passer_en_instruction }.to change { dossier.commentaires.count }.by(1) } it "resolve pending correction" do + passer_en_instruction + expect(dossier.pending_correction?).to be_falsey expect(correction.reload.resolved_at).to be_present end it 'creates a commentaire in the messagerie with expected wording' do + passer_en_instruction + email_template = dossier.procedure.mail_template_for(Dossier.states.fetch(:en_instruction)) - commentaire = dossier.commentaires.first + commentaire = dossier.commentaires.last - expect(dossier.commentaires.count).to eq(1) expect(commentaire.body).to include(email_template.subject_for_dossier(dossier), email_template.body_for_dossier(dossier)) expect(commentaire.dossier).to eq(dossier) end diff --git a/spec/services/sva_svr_decision_date_calculator_service_spec.rb b/spec/services/sva_svr_decision_date_calculator_service_spec.rb index 23bae7ab70b..e6ff877834f 100644 --- a/spec/services/sva_svr_decision_date_calculator_service_spec.rb +++ b/spec/services/sva_svr_decision_date_calculator_service_spec.rb @@ -59,7 +59,7 @@ end end - context 'there is a pending correction kind = correct' do + context 'there is a pending correction reason = incorrect' do before do travel_to DateTime.new(2023, 5, 30, 18) do dossier.flag_as_pending_correction!(build(:commentaire, dossier:)) @@ -73,7 +73,7 @@ end end - context 'there is a pending correction kind = incomplete' do + context 'there is a pending correction reason = incomplete' do before do travel_to DateTime.new(2023, 5, 30, 18) do dossier.flag_as_pending_correction!(build(:commentaire, dossier:), :incomplete)