refactor(PiecesJustificativesService): stop passing flags, pass user_profile and manage ACL from the service itself
This commit is contained in:
parent
83690529ca
commit
32e8f34511
16 changed files with 355 additions and 277 deletions
|
@ -159,9 +159,7 @@ module Experts
|
|||
end
|
||||
|
||||
def telecharger_pjs
|
||||
@dossier = dossier_with_champs
|
||||
|
||||
files = ActiveStorage::DownloadableFile.create_list_from_dossiers(Dossier.where(id: @dossier.id), include_avis_for_expert: current_expert)
|
||||
files = ActiveStorage::DownloadableFile.create_list_from_dossiers(user_profile: current_expert, dossiers: Dossier.where(id: @dossier.id))
|
||||
cleaned_files = ActiveStorage::DownloadableFile.cleanup_list_from_dossier(files)
|
||||
|
||||
zipline(cleaned_files, "dossier-#{@dossier.id}.zip")
|
||||
|
|
|
@ -49,10 +49,9 @@ module Instructeurs
|
|||
def show
|
||||
@demande_seen_at = current_instructeur.follows.find_by(dossier: dossier_with_champs)&.demande_seen_at
|
||||
@is_dossier_in_batch_operation = dossier.batch_operation.present?
|
||||
|
||||
respond_to do |format|
|
||||
format.pdf do
|
||||
@include_infos_administration = true
|
||||
@acls = PiecesJustificativesService.new(user_profile: current_instructeur).acl_for_dossier_export
|
||||
render(template: 'dossiers/show', formats: [:pdf])
|
||||
end
|
||||
format.all
|
||||
|
@ -322,7 +321,7 @@ module Instructeurs
|
|||
end
|
||||
|
||||
def telecharger_pjs
|
||||
files = ActiveStorage::DownloadableFile.create_list_from_dossiers(Dossier.where(id: dossier.id), with_champs_private: true, include_infos_administration: true)
|
||||
files = ActiveStorage::DownloadableFile.create_list_from_dossiers(dossiers: Dossier.where(id: dossier.id), user_profile: current_instructeur)
|
||||
cleaned_files = ActiveStorage::DownloadableFile.cleanup_list_from_dossier(files)
|
||||
|
||||
zipline(cleaned_files, "dossier-#{dossier.id}.zip")
|
||||
|
|
|
@ -88,10 +88,11 @@ module Users
|
|||
end
|
||||
|
||||
def show
|
||||
pj_service = PiecesJustificativesService.new(user_profile: current_user)
|
||||
respond_to do |format|
|
||||
format.pdf do
|
||||
@dossier = dossier_with_champs(pj_template: false)
|
||||
@include_infos_administration = false
|
||||
@acls = pj_service.acl_for_dossier_export
|
||||
render(template: 'dossiers/show', formats: [:pdf])
|
||||
end
|
||||
format.all do
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
require 'fog/openstack'
|
||||
|
||||
class ActiveStorage::DownloadableFile
|
||||
def self.create_list_from_dossiers(
|
||||
dossiers,
|
||||
with_bills: false,
|
||||
with_champs_private: false,
|
||||
include_infos_administration: false,
|
||||
include_avis_for_expert: false
|
||||
)
|
||||
PiecesJustificativesService.generate_dossier_export(dossiers, include_infos_administration:, include_avis_for_expert:) +
|
||||
PiecesJustificativesService.liste_documents(dossiers, with_bills:, with_champs_private:, with_avis_piece_justificative: include_infos_administration)
|
||||
def self.create_list_from_dossiers(dossiers:, user_profile:)
|
||||
pj_service = PiecesJustificativesService.new(user_profile:)
|
||||
|
||||
pj_service.generate_dossiers_export(dossiers) + pj_service.liste_documents(dossiers)
|
||||
end
|
||||
|
||||
def self.cleanup_list_from_dossier(files)
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
class PiecesJustificativesService
|
||||
def self.liste_documents(dossiers,
|
||||
with_bills:,
|
||||
with_champs_private:,
|
||||
with_avis_piece_justificative:)
|
||||
def initialize(user_profile:)
|
||||
@user_profile = user_profile
|
||||
end
|
||||
|
||||
def liste_documents(dossiers)
|
||||
bill_ids = []
|
||||
|
||||
docs = dossiers.in_batches.flat_map do |batch|
|
||||
pjs = pjs_for_champs(batch, with_champs_private:) +
|
||||
pjs = pjs_for_champs(batch) +
|
||||
pjs_for_commentaires(batch) +
|
||||
pjs_for_dossier(batch) +
|
||||
pjs_for_avis(batch, with_avis_piece_justificative:)
|
||||
pjs_for_avis(batch)
|
||||
|
||||
if with_bills
|
||||
if liste_documents_allows?(:with_bills)
|
||||
# some bills are shared among operations
|
||||
# so first, all the bill_ids are fetched
|
||||
operation_logs, some_bill_ids = operation_logs_and_signature_ids(batch)
|
||||
|
@ -23,7 +24,7 @@ class PiecesJustificativesService
|
|||
pjs
|
||||
end
|
||||
|
||||
if with_bills
|
||||
if liste_documents_allows?(:with_bills)
|
||||
# then the bills are retrieved without duplication
|
||||
docs += signatures(bill_ids.uniq)
|
||||
end
|
||||
|
@ -31,6 +32,38 @@ class PiecesJustificativesService
|
|||
docs
|
||||
end
|
||||
|
||||
def generate_dossiers_export(dossiers)
|
||||
return [] if dossiers.empty?
|
||||
|
||||
pdfs = []
|
||||
|
||||
procedure = dossiers.first.procedure
|
||||
dossiers = dossiers.includes(:individual, :traitement, :etablissement, user: :france_connect_information, avis: :expert, commentaires: [:instructeur, :expert])
|
||||
dossiers = DossierPreloader.new(dossiers).in_batches
|
||||
dossiers.each do |dossier|
|
||||
dossier.association(:procedure).target = procedure
|
||||
|
||||
pdf = ApplicationController
|
||||
.render(template: 'dossiers/show', formats: [:pdf],
|
||||
assigns: {
|
||||
acls: acl_for_dossier_export,
|
||||
dossier: dossier
|
||||
})
|
||||
|
||||
a = ActiveStorage::FakeAttachment.new(
|
||||
file: StringIO.new(pdf),
|
||||
filename: "export-#{dossier.id}.pdf",
|
||||
name: 'pdf_export_for_instructeur',
|
||||
id: dossier.id,
|
||||
created_at: dossier.updated_at
|
||||
)
|
||||
|
||||
pdfs << ActiveStorage::DownloadableFile.pj_and_path(dossier.id, a)
|
||||
end
|
||||
|
||||
pdfs
|
||||
end
|
||||
|
||||
def self.serialize_types_de_champ_as_type_pj(revision)
|
||||
tdcs = revision.types_de_champ_public.filter { |type_champ| type_champ.old_pj.present? }
|
||||
tdcs.map.with_index do |type_champ, order_place|
|
||||
|
@ -48,47 +81,52 @@ class PiecesJustificativesService
|
|||
end
|
||||
end
|
||||
|
||||
def self.generate_dossier_export(dossiers, include_infos_administration: false, include_avis_for_expert: false)
|
||||
return [] if dossiers.empty?
|
||||
|
||||
pdfs = []
|
||||
|
||||
procedure = dossiers.first.procedure
|
||||
dossiers = dossiers.includes(:individual, :traitement, :etablissement, user: :france_connect_information, avis: :expert, commentaires: [:instructeur, :expert])
|
||||
dossiers = DossierPreloader.new(dossiers).in_batches
|
||||
dossiers.each do |dossier|
|
||||
dossier.association(:procedure).target = procedure
|
||||
|
||||
pdf = ApplicationController
|
||||
.render(template: 'dossiers/show', formats: [:pdf],
|
||||
assigns: {
|
||||
include_infos_administration:,
|
||||
include_avis_for_expert:,
|
||||
dossier: dossier
|
||||
})
|
||||
|
||||
a = ActiveStorage::FakeAttachment.new(
|
||||
file: StringIO.new(pdf),
|
||||
filename: "export-#{dossier.id}.pdf",
|
||||
name: 'pdf_export_for_instructeur',
|
||||
id: dossier.id,
|
||||
created_at: dossier.updated_at
|
||||
)
|
||||
|
||||
pdfs << ActiveStorage::DownloadableFile.pj_and_path(dossier.id, a)
|
||||
def acl_for_dossier_export
|
||||
case @user_profile
|
||||
when Expert
|
||||
{ include_infos_administration: true, include_avis_for_expert: true, only_for_expert: @user_profile }
|
||||
when Instructeur, Administrateur
|
||||
{ include_infos_administration: true, include_avis_for_expert: true, only_for_export: false }
|
||||
when User
|
||||
{ include_infos_administration: false, include_avis_for_expert: false, only_for_expert: false }
|
||||
else
|
||||
raise 'not supported'
|
||||
end
|
||||
|
||||
pdfs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.pjs_for_champs(dossiers, with_champs_private:)
|
||||
def liste_documents_allows?(scope)
|
||||
case @user_profile
|
||||
when Expert
|
||||
{
|
||||
with_bills: false,
|
||||
with_champs_private: false,
|
||||
with_avis_piece_justificative: false
|
||||
}
|
||||
when Instructeur
|
||||
{
|
||||
with_bills: false,
|
||||
with_champs_private: true,
|
||||
with_avis_piece_justificative: true
|
||||
}
|
||||
when Administrateur
|
||||
{
|
||||
with_bills: true,
|
||||
with_champs_private: true,
|
||||
with_avis_piece_justificative: true
|
||||
}
|
||||
else
|
||||
raise 'not supported'
|
||||
end.fetch(scope)
|
||||
end
|
||||
|
||||
def pjs_for_champs(dossiers)
|
||||
champs = Champ
|
||||
.joins(:piece_justificative_file_attachments)
|
||||
.where(type: "Champs::PieceJustificativeChamp", dossier: dossiers)
|
||||
|
||||
if !with_champs_private
|
||||
if !liste_documents_allows?(:with_champs_private)
|
||||
champs = champs.where(private: false)
|
||||
end
|
||||
|
||||
|
@ -106,7 +144,7 @@ class PiecesJustificativesService
|
|||
end
|
||||
end
|
||||
|
||||
def self.pjs_for_commentaires(dossiers)
|
||||
def pjs_for_commentaires(dossiers)
|
||||
commentaire_id_dossier_id = Commentaire
|
||||
.joins(:piece_jointe_attachment)
|
||||
.where(dossier: dossiers)
|
||||
|
@ -123,13 +161,13 @@ class PiecesJustificativesService
|
|||
end
|
||||
end
|
||||
|
||||
def self.pjs_for_dossier(dossiers)
|
||||
def pjs_for_dossier(dossiers)
|
||||
motivations(dossiers) +
|
||||
attestations(dossiers) +
|
||||
etablissements(dossiers)
|
||||
end
|
||||
|
||||
def self.etablissements(dossiers)
|
||||
def etablissements(dossiers)
|
||||
etablissement_id_dossier_id = Etablissement
|
||||
.where(dossier: dossiers)
|
||||
.pluck(:id, :dossier_id)
|
||||
|
@ -144,7 +182,7 @@ class PiecesJustificativesService
|
|||
end
|
||||
end
|
||||
|
||||
def self.motivations(dossiers)
|
||||
def motivations(dossiers)
|
||||
ActiveStorage::Attachment
|
||||
.includes(:blob)
|
||||
.where(record_type: "Dossier", name: "justificatif_motivation", record_id: dossiers)
|
||||
|
@ -155,7 +193,7 @@ class PiecesJustificativesService
|
|||
end
|
||||
end
|
||||
|
||||
def self.attestations(dossiers)
|
||||
def attestations(dossiers)
|
||||
attestation_id_dossier_id = Attestation
|
||||
.joins(:pdf_attachment)
|
||||
.where(dossier: dossiers)
|
||||
|
@ -171,10 +209,9 @@ class PiecesJustificativesService
|
|||
end
|
||||
end
|
||||
|
||||
def self.pjs_for_avis(dossiers, with_avis_piece_justificative:)
|
||||
avis_ids_dossier_id_query = Avis.joins(:dossier)
|
||||
.where(dossier: dossiers)
|
||||
avis_ids_dossier_id_query = avis_ids_dossier_id_query.where(confidentiel: false) if !with_avis_piece_justificative
|
||||
def pjs_for_avis(dossiers)
|
||||
avis_ids_dossier_id_query = Avis.joins(:dossier).where(dossier: dossiers)
|
||||
avis_ids_dossier_id_query = avis_ids_dossier_id_query.where(confidentiel: false) if !liste_documents_allows?(:with_avis_piece_justificative)
|
||||
avis_ids_dossier_id = avis_ids_dossier_id_query.pluck(:id, :dossier_id).to_h
|
||||
|
||||
ActiveStorage::Attachment
|
||||
|
@ -187,7 +224,7 @@ class PiecesJustificativesService
|
|||
end
|
||||
end
|
||||
|
||||
def self.operation_logs_and_signature_ids(dossiers)
|
||||
def operation_logs_and_signature_ids(dossiers)
|
||||
dol_id_dossier_id_bill_id = DossierOperationLog
|
||||
.where(dossier: dossiers, data: nil)
|
||||
.pluck(:bill_signature_id, :id, :dossier_id)
|
||||
|
@ -227,14 +264,14 @@ class PiecesJustificativesService
|
|||
[serialized_dols, bill_ids]
|
||||
end
|
||||
|
||||
def self.signatures(bill_ids)
|
||||
def signatures(bill_ids)
|
||||
ActiveStorage::Attachment
|
||||
.includes(:blob)
|
||||
.where(record_type: "BillSignature", record_id: bill_ids)
|
||||
.map { |bill| ActiveStorage::DownloadableFile.bill_and_path(bill) }
|
||||
end
|
||||
|
||||
def self.safe_attachment(attachment)
|
||||
def safe_attachment(attachment)
|
||||
attachment
|
||||
.blob
|
||||
.virus_scan_result == ActiveStorage::VirusScanner::SAFE
|
||||
|
|
|
@ -36,7 +36,7 @@ class ProcedureExportService
|
|||
end
|
||||
|
||||
def to_zip
|
||||
attachments = ActiveStorage::DownloadableFile.create_list_from_dossiers(dossiers, with_champs_private: true, include_infos_administration: true)
|
||||
attachments = ActiveStorage::DownloadableFile.create_list_from_dossiers(dossiers:, user_profile: @user_profile)
|
||||
|
||||
DownloadableFileService.download_and_zip(procedure, attachments, base_filename) do |zip_filepath|
|
||||
ArchiveUploader.new(procedure: procedure, filename: filename(:zip), filepath: zip_filepath).blob
|
||||
|
|
|
@ -110,7 +110,7 @@ def add_identite_etablissement(pdf, etablissement)
|
|||
format_in_2_columns(pdf, "État administratif", humanized_entreprise_etat_administratif(etablissement))
|
||||
end
|
||||
|
||||
if @include_infos_administration
|
||||
if @acls[:include_infos_administration]
|
||||
if etablissement.entreprise_effectif_mensuel.present?
|
||||
format_in_2_columns(pdf, "Effectif mensuel #{try_format_mois_effectif(etablissement)} de l'établissement (URSSAF ou MSA) ", number_with_delimiter(etablissement.entreprise_effectif_mensuel.to_s))
|
||||
end
|
||||
|
@ -349,22 +349,28 @@ prawn_document(page_size: "A4") do |pdf|
|
|||
add_title(pdf, 'Formulaire')
|
||||
add_champs(pdf, @dossier.champs_public)
|
||||
|
||||
if @include_infos_administration && @dossier.champs_private.present?
|
||||
if @acls[:include_infos_administration] && @dossier.champs_private.present?
|
||||
add_title(pdf, "Annotations privées")
|
||||
add_champs(pdf, @dossier.champs_private)
|
||||
end
|
||||
|
||||
if @include_infos_administration && @dossier.avis.present?
|
||||
if @acls[:include_infos_administration] && @dossier.avis.present?
|
||||
add_title(pdf, "Avis")
|
||||
@dossier.avis.each do |avis|
|
||||
add_avis(pdf, avis)
|
||||
end
|
||||
end
|
||||
|
||||
if @include_avis_for_expert && @dossier.avis.present?
|
||||
if @acls[:include_avis_for_expert] && @dossier.avis.present?
|
||||
add_title(pdf, "Avis")
|
||||
@dossier.avis_for_expert(@include_avis_for_expert).each do |avis|
|
||||
add_avis(pdf, avis)
|
||||
if @acls[:only_for_expert]
|
||||
@dossier.avis_for_expert(@acls[:only_for_expert]).each do |avis|
|
||||
add_avis(pdf, avis)
|
||||
end
|
||||
else
|
||||
@dossier.avis.each do |avis|
|
||||
add_avis(pdf, avis)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ namespace :benchmarks do
|
|||
p_45964 = Procedure.find(45964)
|
||||
p_55824 = Procedure.find(55824)
|
||||
Benchmark.bm do |x|
|
||||
x.report("Démarche 45964") { ProcedureExportService.new(p_45964, p_45964.dossiers).to_xlsx }
|
||||
x.report("Démarche 55824") { ProcedureExportService.new(p_55824, p_55824.dossiers).to_xlsx }
|
||||
x.report("Démarche 45964") { ProcedureExportService.new(p_45964, p_45964.dossiers, p_45964.administrateurs.first).to_xlsx }
|
||||
x.report("Démarche 55824") { ProcedureExportService.new(p_55824, p_55824.dossiers, p_55824.administrateurs.first).to_xlsx }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -25,8 +25,8 @@ namespace :benchmarks do
|
|||
p_45964 = Procedure.find(45964)
|
||||
p_55824 = Procedure.find(55824)
|
||||
Benchmark.bm do |x|
|
||||
x.report("Démarche 45964") { PiecesJustificativesService.generate_dossier_export(p_45964.dossiers) }
|
||||
x.report("Démarche 55824") { PiecesJustificativesService.generate_dossier_export(p_55824.dossiers.limit(10_000)) }
|
||||
x.report("Démarche 45964") { PiecesJustificativesService.new(user_profile: p_45964.administrateurs.first).generate_dossiers_export(p_45964.dossiers) }
|
||||
x.report("Démarche 55824") { PiecesJustificativesService.new(user_profile: p_55824.administrateurs.first).generate_dossiers_export(p_55824.dossiers.limit(10_000)) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -116,17 +116,15 @@ describe Experts::AvisController, type: :controller do
|
|||
|
||||
describe '#telecharger_pjs' do
|
||||
let(:avis) { avis_with_answer }
|
||||
|
||||
subject { get :telecharger_pjs, params: { id: avis.id, procedure_id: } }
|
||||
|
||||
before do
|
||||
allow(PiecesJustificativesService).to receive(:generate_dossier_export).and_return([]).with([dossier], include_infos_administration: false, include_avis_for_expert: expert)
|
||||
end
|
||||
|
||||
context 'with a valid avis' do
|
||||
it do
|
||||
service = instance_double(PiecesJustificativesService)
|
||||
expect(PiecesJustificativesService).to receive(:new).with(user_profile: expert).and_return(service)
|
||||
expect(service).to receive(:generate_dossiers_export).with(Dossier.where(id: dossier)).and_return([])
|
||||
expect(service).to receive(:liste_documents).with(Dossier.where(id: dossier)).and_return([])
|
||||
is_expected.to have_http_status(:success)
|
||||
expect(PiecesJustificativesService).to have_received(:generate_dossier_export)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -910,7 +910,7 @@ describe Instructeurs::DossiersController, type: :controller do
|
|||
subject
|
||||
end
|
||||
|
||||
it { expect(assigns(:include_infos_administration)).to eq(true) }
|
||||
it { expect(assigns(:acls)).to eq(PiecesJustificativesService.new(user_profile: instructeur).acl_for_dossier_export) }
|
||||
it { expect(assigns(:is_dossier_in_batch_operation)).to eq(false) }
|
||||
it { expect(response).to render_template 'dossiers/show' }
|
||||
|
||||
|
@ -1053,7 +1053,7 @@ describe Instructeurs::DossiersController, type: :controller do
|
|||
end
|
||||
|
||||
before do
|
||||
allow(PiecesJustificativesService).to receive(:generate_dossier_export).with([dossier], include_infos_administration: true, include_avis_for_expert: false).and_call_original
|
||||
allow_any_instance_of(PiecesJustificativesService).to receive(:generate_dossiers_export).with([dossier]).and_call_original
|
||||
end
|
||||
|
||||
it 'includes an attachment' do
|
||||
|
|
|
@ -1114,8 +1114,8 @@ describe Users::DossiersController, type: :controller do
|
|||
end
|
||||
|
||||
context 'when the dossier has been submitted' do
|
||||
it { expect(assigns(:include_infos_administration)).to eq(false) }
|
||||
it { expect(response).to render_template 'dossiers/show' }
|
||||
it { expect(assigns(:acls)).to eq(PiecesJustificativesService.new(user_profile: user).acl_for_dossier_export) }
|
||||
it { expect(response).to render_template('dossiers/show') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
describe ExportJob do
|
||||
let(:procedure) { create(:procedure, instructeurs: [instructeur]) }
|
||||
let(:instructeur) { create(:instructeur) }
|
||||
let(:procedure) { create(:procedure, instructeurs: [user_profile]) }
|
||||
let(:user_profile) { create(:instructeur) }
|
||||
let(:time_span_type) { :everything }
|
||||
let(:status) { :tous }
|
||||
let(:key) { '123' }
|
||||
|
@ -8,7 +8,7 @@ describe ExportJob do
|
|||
create(:export, format:,
|
||||
time_span_type:,
|
||||
key:,
|
||||
instructeur:,
|
||||
user_profile:,
|
||||
groupe_instructeurs: procedure.groupe_instructeurs)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
describe ActiveStorage::DownloadableFile do
|
||||
let(:dossier) { create(:dossier, :en_construction) }
|
||||
|
||||
subject(:list) { ActiveStorage::DownloadableFile.create_list_from_dossiers(Dossier.where(id: dossier.id), with_bills: true, with_champs_private: true) }
|
||||
let(:user_profile) { create(:administrateur) }
|
||||
let(:dossiers) { Dossier.where(id: dossier.id) }
|
||||
subject(:list) { ActiveStorage::DownloadableFile.create_list_from_dossiers(user_profile:, dossiers:) }
|
||||
|
||||
describe 'create_list_from_dossiers' do
|
||||
context 'when no piece_justificative is present' do
|
||||
|
|
|
@ -1,54 +1,129 @@
|
|||
describe PiecesJustificativesService do
|
||||
describe '.liste_documents' do
|
||||
let(:with_champs_private) { true }
|
||||
let(:with_bills) { true }
|
||||
let(:with_avis_piece_justificative) { true }
|
||||
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:dossiers) { Dossier.where(id: dossier.id) }
|
||||
subject do
|
||||
PiecesJustificativesService
|
||||
.liste_documents(Dossier.where(id: dossier.id), with_bills:, with_champs_private:, with_avis_piece_justificative:)
|
||||
.map(&:first)
|
||||
PiecesJustificativesService.new(user_profile:).liste_documents(dossiers).map(&:first)
|
||||
end
|
||||
|
||||
context 'with a pj champ' do
|
||||
context 'no acl' do
|
||||
let(:user_profile) { build(:administrateur) }
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :piece_justificative }]) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:witness) { create(:dossier, procedure: procedure) }
|
||||
|
||||
let(:pj_champ) { -> (d) { d.champs_public.find { |c| c.type == 'Champs::PieceJustificativeChamp' } } }
|
||||
|
||||
before do
|
||||
attach_file_to_champ(pj_champ.call(dossier))
|
||||
attach_file_to_champ(pj_champ.call(witness))
|
||||
end
|
||||
|
||||
context 'with a single attachment' do
|
||||
before do
|
||||
attach_file_to_champ(pj_champ.call(dossier))
|
||||
attach_file_to_champ(pj_champ.call(witness))
|
||||
end
|
||||
|
||||
it { expect(subject).to match_array(pj_champ.call(dossier).piece_justificative_file.attachments) }
|
||||
end
|
||||
|
||||
context 'with a multiple attachments' do
|
||||
before do
|
||||
attach_file_to_champ(pj_champ.call(dossier))
|
||||
attach_file_to_champ(pj_champ.call(witness))
|
||||
attach_file_to_champ(pj_champ.call(dossier))
|
||||
end
|
||||
|
||||
it { expect(subject.count).to eq(2) }
|
||||
it { expect(subject).to match_array(pj_champ.call(dossier).piece_justificative_file.attachments) }
|
||||
end
|
||||
|
||||
context 'with a pj not safe on a champ' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :piece_justificative }]) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:pj_champ) { -> (d) { d.champs_public.find { |c| c.type == 'Champs::PieceJustificativeChamp' } } }
|
||||
|
||||
before { attach_file_to_champ(pj_champ.call(dossier), safe = false) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
|
||||
context 'with a identite champ pj' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :titre_identite }]) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:witness) { create(:dossier, procedure: procedure) }
|
||||
|
||||
let(:champ_identite) { dossier.champs_public.find { |c| c.type == 'Champs::TitreIdentiteChamp' } }
|
||||
|
||||
before { attach_file_to_champ(champ_identite) }
|
||||
|
||||
it "doesn't return sensitive documents like titre_identite" do
|
||||
expect(champ_identite.piece_justificative_file).to be_attached
|
||||
expect(subject).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a pj on an commentaire' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let(:witness) { create(:dossier) }
|
||||
|
||||
let!(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||
let!(:witness_commentaire) { create(:commentaire, dossier: witness) }
|
||||
|
||||
before do
|
||||
attach_file(commentaire.piece_jointe)
|
||||
attach_file(witness_commentaire.piece_jointe)
|
||||
end
|
||||
|
||||
it { expect(subject).to match_array(dossier.commentaires.first.piece_jointe.attachment) }
|
||||
end
|
||||
|
||||
context 'with a pj not safe on a commentaire' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let!(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||
|
||||
before { attach_file(commentaire.piece_jointe, safe = false) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
|
||||
context 'with a motivation' do
|
||||
let(:dossier) { create(:dossier, :with_justificatif) }
|
||||
let!(:witness) { create(:dossier, :with_justificatif) }
|
||||
|
||||
it { expect(subject).to match_array(dossier.justificatif_motivation.attachment) }
|
||||
end
|
||||
|
||||
context 'with a motivation not safe' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
|
||||
before { attach_file(dossier.justificatif_motivation, safe = false) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
|
||||
context 'with an attestation' do
|
||||
let(:dossier) { create(:dossier, :with_attestation) }
|
||||
let!(:witness) { create(:dossier, :with_attestation) }
|
||||
|
||||
it { expect(subject).to match_array(dossier.attestation.pdf.attachment) }
|
||||
end
|
||||
|
||||
context 'with an etablissement' do
|
||||
let(:dossier) { create(:dossier, :with_entreprise) }
|
||||
let(:attestation_sociale) { dossier.etablissement.entreprise_attestation_sociale }
|
||||
let(:attestation_fiscale) { dossier.etablissement.entreprise_attestation_fiscale }
|
||||
|
||||
let!(:witness) { create(:dossier, :with_entreprise) }
|
||||
let!(:witness_attestation_sociale) { witness.etablissement.entreprise_attestation_sociale }
|
||||
let!(:witness_attestation_fiscale) { witness.etablissement.entreprise_attestation_fiscale }
|
||||
|
||||
before do
|
||||
attach_file(attestation_sociale)
|
||||
attach_file(attestation_fiscale)
|
||||
end
|
||||
|
||||
it { expect(subject).to match_array([attestation_sociale.attachment, attestation_fiscale.attachment]) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a pj not safe on a champ' do
|
||||
context 'acl on private pj champ' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :piece_justificative }]) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:pj_champ) { -> (d) { d.champs_public.find { |c| c.type == 'Champs::PieceJustificativeChamp' } } }
|
||||
|
||||
before { attach_file_to_champ(pj_champ.call(dossier), safe = false) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
|
||||
context 'with a private pj champ' do
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:witness) { create(:dossier, procedure: procedure) }
|
||||
|
||||
let!(:private_pj) { create(:type_de_champ_piece_justificative, procedure: procedure, private: true) }
|
||||
|
@ -59,138 +134,23 @@ describe PiecesJustificativesService do
|
|||
attach_file_to_champ(private_pj_champ.call(witness))
|
||||
end
|
||||
|
||||
it { expect(subject).to match_array(private_pj_champ.call(dossier).piece_justificative_file.attachments) }
|
||||
context 'given an administrateur' do
|
||||
let(:user_profile) { build(:administrateur) }
|
||||
it { expect(subject).to match_array(private_pj_champ.call(dossier).piece_justificative_file.attachments) }
|
||||
end
|
||||
|
||||
context 'without private champ' do
|
||||
let(:with_champs_private) { false }
|
||||
context 'given an instructeur' do
|
||||
let(:user_profile) { create(:instructeur) }
|
||||
it { expect(subject).to match_array(private_pj_champ.call(dossier).piece_justificative_file.attachments) }
|
||||
end
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
context 'given an expert' do
|
||||
let(:user_profile) { create(:expert) }
|
||||
it { expect(subject).not_to match_array(private_pj_champ.call(dossier).piece_justificative_file.attachments) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with avis.piece_justificative being confidentiel' do
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:avis) { create(:avis, dossier: dossier, confidentiel: true) }
|
||||
let(:with_avis_piece_justificative) { false }
|
||||
|
||||
before do
|
||||
to_be_attached = {
|
||||
io: StringIO.new("toto"),
|
||||
filename: "toto.png",
|
||||
content_type: "image/png",
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
}
|
||||
|
||||
avis.piece_justificative_file.attach(to_be_attached)
|
||||
end
|
||||
|
||||
it "doesn't return confidentiel avis.piece_justificative_file" do
|
||||
expect(subject).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with avis.piece_justificative being public' do
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:avis) { create(:avis, dossier: dossier) }
|
||||
let(:with_avis_piece_justificative) { false }
|
||||
|
||||
before do
|
||||
to_be_attached = {
|
||||
io: StringIO.new("toto"),
|
||||
filename: "toto.png",
|
||||
content_type: "image/png",
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
}
|
||||
|
||||
avis.piece_justificative_file.attach(to_be_attached)
|
||||
end
|
||||
|
||||
it "return avis.piece_justificative_file not confidentiel" do
|
||||
expect(subject).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a identite champ pj' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :titre_identite }]) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:witness) { create(:dossier, procedure: procedure) }
|
||||
|
||||
let(:champ_identite) { dossier.champs_public.find { |c| c.type == 'Champs::TitreIdentiteChamp' } }
|
||||
|
||||
before { attach_file_to_champ(champ_identite) }
|
||||
|
||||
it "doesn't return sensitive documents like titre_identite" do
|
||||
expect(champ_identite.piece_justificative_file).to be_attached
|
||||
expect(subject).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a pj on an commentaire' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let(:witness) { create(:dossier) }
|
||||
|
||||
let!(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||
let!(:witness_commentaire) { create(:commentaire, dossier: witness) }
|
||||
|
||||
before do
|
||||
attach_file(commentaire.piece_jointe)
|
||||
attach_file(witness_commentaire.piece_jointe)
|
||||
end
|
||||
|
||||
it { expect(subject).to match_array(dossier.commentaires.first.piece_jointe.attachment) }
|
||||
end
|
||||
|
||||
context 'with a pj not safe on a commentaire' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let!(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||
|
||||
before { attach_file(commentaire.piece_jointe, safe = false) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
|
||||
context 'with a motivation' do
|
||||
let(:dossier) { create(:dossier, :with_justificatif) }
|
||||
let!(:witness) { create(:dossier, :with_justificatif) }
|
||||
|
||||
it { expect(subject).to match_array(dossier.justificatif_motivation.attachment) }
|
||||
end
|
||||
|
||||
context 'with a motivation not safe' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
|
||||
before { attach_file(dossier.justificatif_motivation, safe = false) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
|
||||
context 'with an attestation' do
|
||||
let(:dossier) { create(:dossier, :with_attestation) }
|
||||
let!(:witness) { create(:dossier, :with_attestation) }
|
||||
|
||||
it { expect(subject).to match_array(dossier.attestation.pdf.attachment) }
|
||||
end
|
||||
|
||||
context 'with an etablissement' do
|
||||
let(:dossier) { create(:dossier, :with_entreprise) }
|
||||
let(:attestation_sociale) { dossier.etablissement.entreprise_attestation_sociale }
|
||||
let(:attestation_fiscale) { dossier.etablissement.entreprise_attestation_fiscale }
|
||||
|
||||
let!(:witness) { create(:dossier, :with_entreprise) }
|
||||
let!(:witness_attestation_sociale) { witness.etablissement.entreprise_attestation_sociale }
|
||||
let!(:witness_attestation_fiscale) { witness.etablissement.entreprise_attestation_fiscale }
|
||||
|
||||
before do
|
||||
attach_file(attestation_sociale)
|
||||
attach_file(attestation_fiscale)
|
||||
end
|
||||
|
||||
it { expect(subject).to match_array([attestation_sociale.attachment, attestation_fiscale.attachment]) }
|
||||
end
|
||||
|
||||
context 'with a bill' do
|
||||
context 'acl on bill' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let(:witness) { create(:dossier) }
|
||||
|
||||
|
@ -213,58 +173,140 @@ describe PiecesJustificativesService do
|
|||
|
||||
let(:dossier_bs) { dossier.dossier_operation_logs.first.bill_signature }
|
||||
|
||||
it "returns serialized bill and signature" do
|
||||
expect(subject).to match_array([dossier_bs.serialized.attachment, dossier_bs.signature.attachment])
|
||||
context 'given an Administrateur, includes bills' do
|
||||
let(:user_profile) { build(:administrateur) }
|
||||
|
||||
it "returns serialized bill and signature" do
|
||||
expect(subject).to match_array([dossier_bs.serialized.attachment, dossier_bs.signature.attachment])
|
||||
end
|
||||
|
||||
context 'with a dol' do
|
||||
let(:dol) { create(:dossier_operation_log, dossier: dossier) }
|
||||
let(:witness_dol) { create(:dossier_operation_log, dossier: witness) }
|
||||
|
||||
before do
|
||||
attach_file(dol.serialized)
|
||||
attach_file(witness_dol.serialized)
|
||||
end
|
||||
|
||||
it { expect(subject).to include(dol.serialized.attachment) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'without bills' do
|
||||
let(:with_bills) { false }
|
||||
context 'given an expert, does not includes bills' do
|
||||
let(:user_profile) { create(:expert) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
|
||||
context 'given an instructeur, does not includes bills' do
|
||||
let(:user_profile) { create(:instructeur) }
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a dol' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let(:witness) { create(:dossier) }
|
||||
context 'acl on with_avis_piece_justificative' do
|
||||
let(:user_profile) { create(:expert) }
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
|
||||
let(:dol) { create(:dossier_operation_log, dossier: dossier) }
|
||||
let(:witness_dol) { create(:dossier_operation_log, dossier: witness) }
|
||||
context 'with avis.piece_justificative being confidentiel' do
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:avis) { create(:avis, dossier: dossier, confidentiel: true) }
|
||||
|
||||
before do
|
||||
attach_file(dol.serialized)
|
||||
attach_file(witness_dol.serialized)
|
||||
before do
|
||||
to_be_attached = {
|
||||
io: StringIO.new("toto"),
|
||||
filename: "toto.png",
|
||||
content_type: "image/png",
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
}
|
||||
|
||||
avis.piece_justificative_file.attach(to_be_attached)
|
||||
end
|
||||
|
||||
context 'given an administrateur' do
|
||||
let(:user_profile) { build(:administrateur) }
|
||||
it "doesn't return confidentiel avis.piece_justificative_file" do
|
||||
expect(subject).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'given an instructeur' do
|
||||
let(:user_profile) { create(:instructeur) }
|
||||
it "doesn't return confidentiel avis.piece_justificative_file" do
|
||||
expect(subject).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'given an expert' do
|
||||
let(:user_profile) { create(:expert) }
|
||||
it "doesn't return confidentiel avis.piece_justificative_file" do
|
||||
expect(subject).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it { expect(subject).to match_array(dol.serialized.attachment) }
|
||||
context 'with avis.piece_justificative being public' do
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let(:avis) { create(:avis, dossier: dossier) }
|
||||
before do
|
||||
to_be_attached = {
|
||||
io: StringIO.new("toto"),
|
||||
filename: "toto.png",
|
||||
content_type: "image/png",
|
||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
}
|
||||
|
||||
context 'without bills' do
|
||||
let(:with_bills) { false }
|
||||
avis.piece_justificative_file.attach(to_be_attached)
|
||||
end
|
||||
|
||||
it { expect(subject).to be_empty }
|
||||
context 'given an administrateur' do
|
||||
let(:user_profile) { build(:administrateur) }
|
||||
it "doesn't return confidentiel avis.piece_justificative_file" do
|
||||
expect(subject).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'given an instructeur' do
|
||||
let(:user_profile) { create(:instructeur) }
|
||||
it "doesn't return confidentiel avis.piece_justificative_file" do
|
||||
expect(subject).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'given an expert' do
|
||||
let(:user_profile) { create(:expert) }
|
||||
it "doesn't return confidentiel avis.piece_justificative_file" do
|
||||
expect(subject).not_to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.generate_dossier_export' do
|
||||
describe '.generate_dossiers_export' do
|
||||
let(:user_profile) { build(:administrateur) }
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :repetition, children: [{ type: :piece_justificative }] }]) }
|
||||
let(:dossier) { create(:dossier, :with_populated_champs, procedure: procedure) }
|
||||
|
||||
subject { PiecesJustificativesService.generate_dossier_export(Dossier.where(id: dossier.id)) }
|
||||
let(:dossiers) { Dossier.where(id: dossier.id) }
|
||||
subject { PiecesJustificativesService.new(user_profile:).generate_dossiers_export(dossiers) }
|
||||
|
||||
it "doesn't update dossier" do
|
||||
expect { subject }.not_to change { dossier.updated_at }
|
||||
end
|
||||
|
||||
context 'when given an expert' do
|
||||
let!(:expert) { create(:expert) }
|
||||
let!(:user_profile) { create(:expert) }
|
||||
let!(:confidentiel_avis) { create(:avis, :confidentiel, dossier: dossier) }
|
||||
let!(:not_confidentiel_avis) { create(:avis, :not_confidentiel, dossier: dossier) }
|
||||
let!(:expert_avis) { create(:avis, :confidentiel, dossier: dossier, expert: expert) }
|
||||
let!(:expert_avis) { create(:avis, :confidentiel, dossier: dossier, expert: user_profile) }
|
||||
|
||||
subject { PiecesJustificativesService.generate_dossier_export(Dossier.where(id: dossier.id), include_avis_for_expert: expert) }
|
||||
subject { PiecesJustificativesService.new(user_profile:).generate_dossiers_export(dossiers) }
|
||||
it "includes avis not confidentiel as well as expert's avis" do
|
||||
expect_any_instance_of(Dossier).to receive(:avis_for_expert).with(expert).and_return([])
|
||||
expect_any_instance_of(Dossier).to receive(:avis_for_expert).with(user_profile).and_return([])
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
describe ProcedureArchiveService do
|
||||
let(:procedure) { create(:procedure, :published) }
|
||||
let(:procedure) { create(:procedure, :published, administrateurs: [administrateur]) }
|
||||
let(:instructeur) { create(:instructeur) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:service) { ProcedureArchiveService.new(procedure) }
|
||||
let(:year) { 2020 }
|
||||
let(:month) { 3 }
|
||||
|
@ -18,7 +19,7 @@ describe ProcedureArchiveService do
|
|||
after { Timecop.return }
|
||||
|
||||
context 'for a specific month' do
|
||||
let(:archive) { create(:archive, time_span_type: 'monthly', job_status: 'pending', month: date_month, groupe_instructeurs: groupe_instructeurs) }
|
||||
let(:archive) { create(:archive, user_profile: administrateur, time_span_type: 'monthly', job_status: 'pending', month: date_month, groupe_instructeurs: groupe_instructeurs) }
|
||||
let(:year) { 2021 }
|
||||
|
||||
it 'collects files with success' do
|
||||
|
@ -86,7 +87,7 @@ describe ProcedureArchiveService do
|
|||
|
||||
let(:documents) { [pj, bad_pj].map { |p| ActiveStorage::DownloadableFile.pj_and_path(dossier.id, p) } }
|
||||
before do
|
||||
allow(PiecesJustificativesService).to receive(:liste_documents).and_return(documents)
|
||||
allow_any_instance_of(PiecesJustificativesService).to receive(:liste_documents).and_return(documents)
|
||||
end
|
||||
|
||||
it 'collect files without raising exception' do
|
||||
|
@ -120,7 +121,7 @@ describe ProcedureArchiveService do
|
|||
end
|
||||
|
||||
context 'for all months' do
|
||||
let(:archive) { create(:archive, time_span_type: 'everything', job_status: 'pending', groupe_instructeurs: groupe_instructeurs) }
|
||||
let(:archive) { create(:archive, user_profile: administrateur, time_span_type: 'everything', job_status: 'pending', groupe_instructeurs: groupe_instructeurs) }
|
||||
|
||||
it 'collect files' do
|
||||
allow_any_instance_of(ActiveStorage::Attachment).to receive(:url).and_return("https://opengraph.githubassets.com/5e61989aecb78e369c93674f877d7bf4ecde378850114a9563cdf8b6a2472536/typhoeus/typhoeus/issues/110")
|
||||
|
|
|
@ -510,16 +510,16 @@ describe ProcedureExportService do
|
|||
end
|
||||
end
|
||||
|
||||
context 'generate_dossier_export' do
|
||||
context 'generate_dossiers_export' do
|
||||
it 'include_infos_administration (so it includes avis, champs privés)' do
|
||||
expect(ActiveStorage::DownloadableFile).to receive(:create_list_from_dossiers).with(anything, with_champs_private: true, include_infos_administration: true).and_return([])
|
||||
expect(ActiveStorage::DownloadableFile).to receive(:create_list_from_dossiers).with(dossiers: anything, user_profile: instructeur).and_return([])
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'with files (and http calls)' do
|
||||
let!(:dossier) { create(:dossier, :accepte, :with_populated_champs, :with_individual, procedure: procedure) }
|
||||
let(:dossier_exports) { PiecesJustificativesService.generate_dossier_export(Dossier.where(id: dossier)) }
|
||||
let(:dossier_exports) { PiecesJustificativesService.new(user_profile: instructeur).generate_dossiers_export(Dossier.where(id: dossier)) }
|
||||
before do
|
||||
allow_any_instance_of(ActiveStorage::Attachment).to receive(:url).and_return("https://opengraph.githubassets.com/d0e7862b24d8026a3c03516d865b28151eb3859029c6c6c2e86605891fbdcd7a/socketry/async-io")
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue