dossier: remove UI for uploading old pieces justificatives
This commit is contained in:
parent
0c4cb3b498
commit
5502f2e42e
5 changed files with 5 additions and 268 deletions
|
@ -132,7 +132,6 @@ module Users
|
||||||
end
|
end
|
||||||
|
|
||||||
# FIXME:
|
# FIXME:
|
||||||
# - remove PiecesJustificativesService
|
|
||||||
# - delegate draft save logic to champ ?
|
# - delegate draft save logic to champ ?
|
||||||
def update_brouillon
|
def update_brouillon
|
||||||
@dossier = dossier_with_champs
|
@dossier = dossier_with_champs
|
||||||
|
@ -158,8 +157,6 @@ module Users
|
||||||
@dossier = dossier_with_champs
|
@dossier = dossier_with_champs
|
||||||
end
|
end
|
||||||
|
|
||||||
# FIXME:
|
|
||||||
# - remove PiecesJustificativesService
|
|
||||||
def update
|
def update
|
||||||
@dossier = dossier_with_champs
|
@dossier = dossier_with_champs
|
||||||
|
|
||||||
|
@ -297,7 +294,7 @@ module Users
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_dossier_and_compute_errors
|
def update_dossier_and_compute_errors
|
||||||
errors = PiecesJustificativesService.upload!(@dossier, current_user, params)
|
errors = []
|
||||||
|
|
||||||
if champs_params[:dossier] && !@dossier.update(champs_params[:dossier])
|
if champs_params[:dossier] && !@dossier.update(champs_params[:dossier])
|
||||||
errors += @dossier.errors.full_messages
|
errors += @dossier.errors.full_messages
|
||||||
|
@ -305,7 +302,6 @@ module Users
|
||||||
|
|
||||||
if !save_draft?
|
if !save_draft?
|
||||||
errors += @dossier.check_mandatory_champs
|
errors += @dossier.check_mandatory_champs
|
||||||
errors += PiecesJustificativesService.missing_pj_error_messages(@dossier)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
errors
|
errors
|
||||||
|
|
|
@ -1,37 +1,4 @@
|
||||||
class PiecesJustificativesService
|
class PiecesJustificativesService
|
||||||
def self.upload!(dossier, user, params)
|
|
||||||
tpj_contents = dossier.types_de_piece_justificative
|
|
||||||
.map { |tpj| [tpj, params["piece_justificative_#{tpj.id}"]] }
|
|
||||||
.select { |_, content| content.present? }
|
|
||||||
|
|
||||||
without_virus, with_virus = tpj_contents
|
|
||||||
.partition { |_, content| ClamavService.safe_file?(content.path) }
|
|
||||||
|
|
||||||
errors = with_virus
|
|
||||||
.map { |_, content| "#{content.original_filename} : virus détecté" }
|
|
||||||
|
|
||||||
errors + without_virus
|
|
||||||
.map { |tpj, content| save_pj(content, dossier, tpj, user) }
|
|
||||||
.compact()
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.save_pj(content, dossier, tpj, user)
|
|
||||||
pj = PieceJustificative.new(content: content,
|
|
||||||
dossier: dossier,
|
|
||||||
type_de_piece_justificative: tpj,
|
|
||||||
user: user)
|
|
||||||
|
|
||||||
pj.save ? nil : "le fichier #{content.original_filename} (#{pj.libelle.truncate(200)}) n'a pas pu être sauvegardé"
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.missing_pj_error_messages(dossier)
|
|
||||||
mandatory_pjs = dossier.types_de_piece_justificative.select(&:mandatory)
|
|
||||||
present_pjs = dossier.pieces_justificatives.map(&:type_de_piece_justificative)
|
|
||||||
missing_pjs = mandatory_pjs - present_pjs
|
|
||||||
|
|
||||||
missing_pjs.map { |pj| "La pièce jointe #{pj.libelle.truncate(200)} doit être fournie." }
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.types_pj_as_types_de_champ(procedure)
|
def self.types_pj_as_types_de_champ(procedure)
|
||||||
max_order_place = procedure.types_de_champ.pluck(:order_place).compact.max || -1
|
max_order_place = procedure.types_de_champ.pluck(:order_place).compact.max || -1
|
||||||
order_place = max_order_place + 1
|
order_place = max_order_place + 1
|
||||||
|
|
|
@ -31,45 +31,6 @@
|
||||||
= render partial: "shared/dossiers/editable_champs/editable_champ",
|
= render partial: "shared/dossiers/editable_champs/editable_champ",
|
||||||
locals: { champ: champ, form: champ_form }
|
locals: { champ: champ, form: champ_form }
|
||||||
|
|
||||||
- tpjs = dossier.types_de_piece_justificative.order('order_place ASC')
|
|
||||||
- if tpjs.present?
|
|
||||||
.card.featured
|
|
||||||
.card-title
|
|
||||||
Pièces jointes
|
|
||||||
|
|
||||||
.warning
|
|
||||||
- if tpjs.many?
|
|
||||||
Pour éviter toute erreur, nous vous conseillons de limiter la taille de chaque pièce jointe à 20 Mo, et de les ajouter une par une, en enregistrant votre
|
|
||||||
= dossier.brouillon? ? "brouillon" : "dossier"
|
|
||||||
après chaque ajout.
|
|
||||||
- else
|
|
||||||
Pour éviter toute erreur, nous vous conseillons de limiter la taille de votre pièce jointe à 20 Mo.
|
|
||||||
|
|
||||||
- tpjs.each do |tpj|
|
|
||||||
.pj-input
|
|
||||||
%label{ for: "piece_justificative_#{tpj.id}" }
|
|
||||||
= tpj.libelle
|
|
||||||
- if tpj.mandatory?
|
|
||||||
%span.mandatory *
|
|
||||||
|
|
||||||
%p.piece-description= tpj.description
|
|
||||||
|
|
||||||
- if tpj.lien_demarche.present?
|
|
||||||
%p.piece-description
|
|
||||||
Récupérer le formulaire vierge pour mon dossier :
|
|
||||||
= link_to "Télécharger", tpj.lien_demarche, target: :blank, rel: :noopener
|
|
||||||
|
|
||||||
- if dossier.was_piece_justificative_uploaded_for_type_id?(tpj.id)
|
|
||||||
- pj = dossier.retrieve_last_piece_justificative_by_type(tpj.id)
|
|
||||||
%p
|
|
||||||
Pièce jointe déjà importée :
|
|
||||||
= link_to pj.original_filename, pj.content_url, target: :blank, rel: :noopener
|
|
||||||
|
|
||||||
= file_field_tag "piece_justificative_#{tpj.id}",
|
|
||||||
accept: PieceJustificative.accept_format,
|
|
||||||
max_file_size: 6.megabytes,
|
|
||||||
required: (tpj.mandatory? && !dossier.was_piece_justificative_uploaded_for_type_id?(tpj.id))
|
|
||||||
|
|
||||||
- if !apercu
|
- if !apercu
|
||||||
.send-wrapper
|
.send-wrapper
|
||||||
- if dossier.brouillon?
|
- if dossier.brouillon?
|
||||||
|
|
|
@ -476,29 +476,16 @@ describe Users::DossiersController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the pj service returns an error' do
|
|
||||||
before do
|
|
||||||
expect(PiecesJustificativesService).to receive(:upload!).and_return(['nop'])
|
|
||||||
|
|
||||||
subject
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect(response).to render_template(:brouillon) }
|
|
||||||
it { expect(flash.alert).to eq(['nop']) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when a mandatory champ is missing' do
|
context 'when a mandatory champ is missing' do
|
||||||
let(:value) { nil }
|
let(:value) { nil }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
||||||
allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj'])
|
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(response).to render_template(:brouillon) }
|
it { expect(response).to render_template(:brouillon) }
|
||||||
it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) }
|
it { expect(flash.alert).to eq(['Le champ l doit être rempli.']) }
|
||||||
|
|
||||||
context 'and the user saves a draft' do
|
context 'and the user saves a draft' do
|
||||||
let(:payload) { submit_payload.merge(save_draft: true) }
|
let(:payload) { submit_payload.merge(save_draft: true) }
|
||||||
|
@ -511,7 +498,7 @@ describe Users::DossiersController, type: :controller do
|
||||||
let!(:dossier) { create(:dossier, :en_construction, user: user) }
|
let!(:dossier) { create(:dossier, :en_construction, user: user) }
|
||||||
|
|
||||||
it { expect(response).to render_template(:brouillon) }
|
it { expect(response).to render_template(:brouillon) }
|
||||||
it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) }
|
it { expect(flash.alert).to eq(['Le champ l doit être rempli.']) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -535,8 +522,6 @@ describe Users::DossiersController, type: :controller do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
||||||
allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj'])
|
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -644,29 +629,16 @@ describe Users::DossiersController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the pj service returns an error' do
|
|
||||||
before do
|
|
||||||
expect(PiecesJustificativesService).to receive(:upload!).and_return(['nop'])
|
|
||||||
|
|
||||||
subject
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect(response).to render_template(:modifier) }
|
|
||||||
it { expect(flash.alert).to eq(['nop']) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when a mandatory champ is missing' do
|
context 'when a mandatory champ is missing' do
|
||||||
let(:value) { nil }
|
let(:value) { nil }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
||||||
allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj'])
|
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(response).to render_template(:modifier) }
|
it { expect(response).to render_template(:modifier) }
|
||||||
it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) }
|
it { expect(flash.alert).to eq(['Le champ l doit être rempli.']) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when dossier has no champ' do
|
context 'when dossier has no champ' do
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe PiecesJustificativesService do
|
|
||||||
let(:user) { create(:user) }
|
|
||||||
let(:safe_file) { true }
|
|
||||||
|
|
||||||
before :each do
|
|
||||||
allow(ClamavService).to receive(:safe_file?).and_return(safe_file)
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:hash) { {} }
|
|
||||||
let!(:tpj_not_mandatory) do
|
|
||||||
TypeDePieceJustificative.create(libelle: 'not mandatory', mandatory: false)
|
|
||||||
end
|
|
||||||
let!(:tpj_mandatory) do
|
|
||||||
TypeDePieceJustificative.create(libelle: 'justificatif', mandatory: true)
|
|
||||||
end
|
|
||||||
let(:procedure) { Procedure.create(types_de_piece_justificative: tpjs) }
|
|
||||||
let(:dossier) { Dossier.create(procedure: procedure) }
|
|
||||||
let(:errors) { PiecesJustificativesService.upload!(dossier, user, hash) }
|
|
||||||
let(:tpjs) { [tpj_not_mandatory] }
|
|
||||||
|
|
||||||
let(:attachment_list) { PiecesJustificativesService.liste_pieces_justificatives(dossier) }
|
|
||||||
let(:poids_total) { PiecesJustificativesService.pieces_justificatives_total_size(dossier) }
|
|
||||||
|
|
||||||
describe 'self.upload!' do
|
|
||||||
context 'when no params are given' do
|
|
||||||
it { expect(errors).to eq([]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when there is something wrong with file save' do
|
|
||||||
let(:hash) do
|
|
||||||
{
|
|
||||||
"piece_justificative_#{tpj_not_mandatory.id}" =>
|
|
||||||
double(path: '', original_filename: 'filename')
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect(errors).to match(["le fichier filename (not mandatory) n'a pas pu être sauvegardé"]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when a virus is provided' do
|
|
||||||
let(:safe_file) { false }
|
|
||||||
let(:hash) do
|
|
||||||
{
|
|
||||||
"piece_justificative_#{tpj_not_mandatory.id}" =>
|
|
||||||
double(path: '', original_filename: 'bad_file')
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect(errors).to match(['bad_file : virus détecté']) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when a regular file is provided' do
|
|
||||||
let(:content) { double(path: '', original_filename: 'filename') }
|
|
||||||
let(:hash) do
|
|
||||||
{
|
|
||||||
"piece_justificative_#{tpj_not_mandatory.id}" =>
|
|
||||||
content
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
before :each do
|
|
||||||
expect(PiecesJustificativesService).to receive(:save_pj)
|
|
||||||
.with(content, dossier, tpj_not_mandatory, user)
|
|
||||||
.and_return(nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'is saved' do
|
|
||||||
expect(errors).to match([])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'missing_pj_error_messages' do
|
|
||||||
let(:errors) { PiecesJustificativesService.missing_pj_error_messages(dossier) }
|
|
||||||
let(:tpjs) { [tpj_mandatory] }
|
|
||||||
|
|
||||||
context 'when no params are given' do
|
|
||||||
it { expect(errors).to match(['La pièce jointe justificatif doit être fournie.']) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when the piece justificative is provided' do
|
|
||||||
before :each do
|
|
||||||
# we are messing around piece_justificative
|
|
||||||
# because directly doubling carrierwave params seems complicated
|
|
||||||
piece_justificative_double = double(type_de_piece_justificative: tpj_mandatory)
|
|
||||||
expect(dossier).to receive(:pieces_justificatives).and_return([piece_justificative_double])
|
|
||||||
end
|
|
||||||
|
|
||||||
it {
|
|
||||||
expect(errors).to match([])
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#attachment_list' do
|
|
||||||
context 'when no piece_justificative is present' do
|
|
||||||
it { expect(attachment_list).to match([]) }
|
|
||||||
it { expect(poids_total).to be 0 }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when there is a piece_justificative' do
|
|
||||||
let (:pj) { create(:champ, :piece_justificative, :with_piece_justificative_file) }
|
|
||||||
before do
|
|
||||||
dossier.champs = [pj]
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect(attachment_list).not_to be_empty }
|
|
||||||
it { expect(poids_total).to be pj.piece_justificative_file.byte_size }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'types_pj_as_types_de_champ' do
|
|
||||||
subject { PiecesJustificativesService.types_pj_as_types_de_champ(procedure) }
|
|
||||||
|
|
||||||
it 'generates one header champ, plus one champ per PJ' do
|
|
||||||
expect(subject.pluck(:libelle)).to contain_exactly("Pièces jointes", "not mandatory")
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'remembers the id of the PJ that got converted into a champ' do
|
|
||||||
expect(subject.map(&:old_pj)).to include({ 'stable_id' => tpj_not_mandatory.id })
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'without pre-existing champs' do
|
|
||||||
it 'generates a sequence of order_places incrementing from zero' do
|
|
||||||
expect(subject.pluck(:order_place)).to contain_exactly(0, 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with pre-existing champs' do
|
|
||||||
let(:procedure) do
|
|
||||||
create(
|
|
||||||
:procedure,
|
|
||||||
types_de_piece_justificative: tpjs,
|
|
||||||
types_de_champ: [build(:type_de_champ, order_place: 0), build(:type_de_champ, order_place: 1)]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'generates a sequence of incrementing order_places that continues where the last type de champ left off' do
|
|
||||||
expect(subject.pluck(:order_place)).to contain_exactly(2, 3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with pre-existing champs without an order place' do
|
|
||||||
let(:procedure) do
|
|
||||||
create(
|
|
||||||
:procedure,
|
|
||||||
types_de_piece_justificative: tpjs,
|
|
||||||
types_de_champ: [build(:type_de_champ, order_place: 0), build(:type_de_champ, order_place: nil)]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'ignores champs without an order place' do
|
|
||||||
expect(subject.pluck(:order_place)).to contain_exactly(1, 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in a new issue