Fix dossier AASM exceptions (#4657)

Instructeur : meilleur messages lorsque le changement d’état d’un dossier échoue
This commit is contained in:
Pierre de La Morinerie 2019-12-19 15:34:28 +01:00 committed by GitHub
commit fccbbdf53a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 44 deletions

View file

@ -88,33 +88,33 @@ module Instructeurs
end end
def passer_en_instruction def passer_en_instruction
if dossier.en_instruction? begin
flash.notice = 'Le dossier est déjà en instruction.'
else
dossier.passer_en_instruction!(current_instructeur) dossier.passer_en_instruction!(current_instructeur)
flash.notice = 'Dossier passé en instruction.' flash.notice = 'Dossier passé en instruction.'
rescue AASM::InvalidTransition => e
flash.alert = aasm_error_message(e, target_state: :en_instruction)
end end
render partial: 'state_button_refresh', locals: { dossier: dossier } render partial: 'state_button_refresh', locals: { dossier: dossier }
end end
def repasser_en_construction def repasser_en_construction
if dossier.en_construction? begin
flash.notice = 'Le dossier est déjà en construction.'
else
dossier.repasser_en_construction!(current_instructeur) dossier.repasser_en_construction!(current_instructeur)
flash.notice = 'Dossier repassé en construction.' flash.notice = 'Dossier repassé en construction.'
rescue AASM::InvalidTransition => e
flash.alert = aasm_error_message(e, target_state: :en_construction)
end end
render partial: 'state_button_refresh', locals: { dossier: dossier } render partial: 'state_button_refresh', locals: { dossier: dossier }
end end
def repasser_en_instruction def repasser_en_instruction
if dossier.en_instruction? begin
flash.notice = 'Le dossier est déjà en instruction.'
else
flash.notice = "Le dossier #{dossier.id} a été repassé en instruction." flash.notice = "Le dossier #{dossier.id} a été repassé en instruction."
dossier.repasser_en_instruction!(current_instructeur) dossier.repasser_en_instruction!(current_instructeur)
rescue AASM::InvalidTransition => e
flash.alert = aasm_error_message(e, target_state: :en_instruction)
end end
render partial: 'state_button_refresh', locals: { dossier: dossier } render partial: 'state_button_refresh', locals: { dossier: dossier }
@ -124,20 +124,23 @@ module Instructeurs
motivation = params[:dossier] && params[:dossier][:motivation] motivation = params[:dossier] && params[:dossier][:motivation]
justificatif = params[:dossier] && params[:dossier][:justificatif_motivation] justificatif = params[:dossier] && params[:dossier][:justificatif_motivation]
if dossier.termine? begin
flash.notice = "Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"
else
case params[:process_action] case params[:process_action]
when "refuser" when "refuser"
target_state = :refuse
dossier.refuser!(current_instructeur, motivation, justificatif) dossier.refuser!(current_instructeur, motivation, justificatif)
flash.notice = "Dossier considéré comme refusé." flash.notice = "Dossier considéré comme refusé."
when "classer_sans_suite" when "classer_sans_suite"
target_state = :sans_suite
dossier.classer_sans_suite!(current_instructeur, motivation, justificatif) dossier.classer_sans_suite!(current_instructeur, motivation, justificatif)
flash.notice = "Dossier considéré comme sans suite." flash.notice = "Dossier considéré comme sans suite."
when "accepter" when "accepter"
target_state = :accepte
dossier.accepter!(current_instructeur, motivation, justificatif) dossier.accepter!(current_instructeur, motivation, justificatif)
flash.notice = "Dossier traité avec succès." flash.notice = "Dossier traité avec succès."
end end
rescue AASM::InvalidTransition => e
flash.alert = aasm_error_message(e, target_state: target_state)
end end
render partial: 'state_button_refresh', locals: { dossier: dossier } render partial: 'state_button_refresh', locals: { dossier: dossier }
@ -219,5 +222,13 @@ module Instructeurs
def mark_annotations_privees_as_read def mark_annotations_privees_as_read
current_instructeur.mark_tab_as_seen(dossier, :annotations_privees) current_instructeur.mark_tab_as_seen(dossier, :annotations_privees)
end end
def aasm_error_message(exception, target_state:)
if exception.originating_state == target_state
"Le dossier est déjà #{dossier_display_state(target_state, lower: true)}."
else
"Le dossier est en ce moment #{dossier_display_state(exception.originating_state, lower: true)} : il nest pas possible de le passer #{dossier_display_state(target_state, lower: true)}."
end
end
end end
end end

View file

@ -47,9 +47,10 @@ module DossierHelper
dossier.brouillon? && dossier.procedure.close? dossier.brouillon? && dossier.procedure.close?
end end
def dossier_display_state(dossier, lower: false) def dossier_display_state(dossier_or_state, lower: false)
state = I18n.t(dossier.state, scope: [:activerecord, :attributes, :dossier, :state]) state = dossier_or_state.is_a?(Dossier) ? dossier_or_state.state : dossier_or_state
lower ? state.downcase : state display_state = I18n.t(state, scope: [:activerecord, :attributes, :dossier, :state])
lower ? display_state.downcase : display_state
end end
def dossier_legacy_state(dossier) def dossier_legacy_state(dossier)

View file

@ -112,9 +112,23 @@ describe Instructeurs::DossiersController, type: :controller do
context 'when the dossier has already been put en_instruction' do context 'when the dossier has already been put en_instruction' do
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) } let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
it 'warns about the error, but doesnt raise' do it 'warns about the error' do
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction))
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(response.body).to have_text('Le dossier est déjà en instruction.')
end
end
context 'when the dossier has already been closed' do
let(:dossier) { create(:dossier, :accepte, procedure: procedure) }
it 'doesnt change the dossier state' do
expect(dossier.reload.state).to eq(Dossier.states.fetch(:accepte))
end
it 'warns about the error' do
expect(response).to have_http_status(:ok)
expect(response.body).to have_text('Le dossier est en ce moment accepté : il nest pas possible de le passer en instruction.')
end end
end end
end end
@ -136,9 +150,10 @@ describe Instructeurs::DossiersController, type: :controller do
context 'when the dossier has already been put en_construction' do context 'when the dossier has already been put en_construction' do
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
it 'warns about the error, but doesnt raise' do it 'warns about the error' do
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction))
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(response.body).to have_text('Le dossier est déjà en construction.')
end end
end end
end end
@ -161,9 +176,10 @@ describe Instructeurs::DossiersController, type: :controller do
context 'when the dossier has already been put en_instruction' do context 'when the dossier has already been put en_instruction' do
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) } let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
it 'warns about the error, but doesnt raise' do it 'warns about the error' do
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction))
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(response.body).to have_text('Le dossier est déjà en instruction.')
end end
end end
@ -355,15 +371,18 @@ describe Instructeurs::DossiersController, type: :controller do
context 'when a dossier is already closed' do context 'when a dossier is already closed' do
let(:dossier) { create(:dossier, :accepte, procedure: procedure) } let(:dossier) { create(:dossier, :accepte, procedure: procedure) }
before { allow(dossier).to receive(:accepter!) } before { allow(dossier).to receive(:after_accepter) }
subject { post :terminer, params: { process_action: "accepter", procedure_id: procedure.id, dossier_id: dossier.id, dossier: { justificatif_motivation: fake_justificatif } }, format: 'js' } subject { post :terminer, params: { process_action: "accepter", procedure_id: procedure.id, dossier_id: dossier.id, dossier: { justificatif_motivation: fake_justificatif } }, format: 'js' }
it 'does not close it again' do it 'does not close it again' do
subject subject
expect(dossier).not_to have_received(:accepter!) expect(dossier).not_to have_received(:after_accepter)
expect(dossier.state).to eq(Dossier.states.fetch(:accepte))
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(response.body).to have_text('Le dossier est déjà accepté.')
end end
end end
end end

View file

@ -132,37 +132,20 @@ RSpec.describe DossierHelper, type: :helper do
expect(subject).to eq('Refusé') expect(subject).to eq('Refusé')
end end
context "lower: true" do context 'when requesting lowercase' do
subject { dossier_display_state(dossier, lower: true) } subject { dossier_display_state(dossier, lower: true) }
it 'brouillon is brouillon' do it 'lowercases the display name' do
dossier.brouillon! dossier.brouillon!
expect(subject).to eq('brouillon') expect(subject).to eq('brouillon')
end end
it 'en_construction is En construction' do
dossier.en_construction!
expect(subject).to eq('en construction')
end end
it 'accepte is traité' do context 'when providing directly a state name' do
dossier.accepte! subject { dossier_display_state(:brouillon) }
expect(subject).to eq('accepté')
end
it 'en_instruction is reçu' do it 'generates a display name for the given state' do
dossier.en_instruction! expect(subject).to eq('Brouillon')
expect(subject).to eq('en instruction')
end
it 'sans_suite is traité' do
dossier.sans_suite!
expect(subject).to eq('sans suite')
end
it 'refuse is traité' do
dossier.refuse!
expect(subject).to eq('refusé')
end end
end end
end end