demarches-normaliennes/app/services/pieces_justificatives_service.rb
mfo 086cc1537b
Merge pull request #10068 from mfo/US/user-has-many-fcis
tech(User.FranceConnect): un usager peut avoir plusieurs profils FranceConnect, pas uniquement un
2024-03-20 16:30:39 +00:00

303 lines
9 KiB
Ruby
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class PiecesJustificativesService
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) +
pjs_for_commentaires(batch) +
pjs_for_dossier(batch) +
pjs_for_avis(batch)
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)
pjs += operation_logs
bill_ids += some_bill_ids
end
pjs
end
if liste_documents_allows?(:with_bills)
# then the bills are retrieved without duplication
docs += signatures(bill_ids.uniq)
end
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_informations, 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(procedure),
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|
description = type_champ.description
if /^(?<original_description>.*?)(?:[\r\n]+)Récupérer le formulaire vierge pour mon dossier : (?<lien_demarche>http.*)$/m =~ description
description = original_description
end
{
id: type_champ.old_pj[:stable_id],
libelle: type_champ.libelle,
description: description,
order_place: order_place,
lien_demarche: lien_demarche
}
end
end
def acl_for_dossier_export(procedure)
case @user_profile
when Expert
{
include_messagerie: procedure.allow_expert_messaging,
include_infos_administration: false,
include_avis_for_expert: true,
only_for_expert: @user_profile
}
when Instructeur, Administrateur
{
include_messagerie: true,
include_infos_administration: true,
include_avis_for_expert: true,
only_for_export: false
}
when User
{
include_messagerie: true,
include_infos_administration: false,
include_avis_for_expert: false, # should be true, expert can use the messagerie, why not provide avis ?
only_for_expert: false
}
else
raise 'not supported'
end
end
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 !liste_documents_allows?(:with_champs_private)
champs = champs.where(private: false)
end
champ_id_dossier_id = champs
.pluck(:id, :dossier_id)
.to_h
ActiveStorage::Attachment
.includes(:blob)
.where(record_type: "Champ", record_id: champ_id_dossier_id.keys)
.filter { |a| safe_attachment(a) }
.map do |a|
dossier_id = champ_id_dossier_id[a.record_id]
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
end
def pjs_for_commentaires(dossiers)
commentaire_id_dossier_id = Commentaire
.joins(:piece_jointe_attachment)
.where(dossier: dossiers)
.pluck(:id, :dossier_id)
.to_h
ActiveStorage::Attachment
.includes(:blob)
.where(record_type: "Commentaire", record_id: commentaire_id_dossier_id.keys)
.filter { |a| safe_attachment(a) }
.map do |a|
dossier_id = commentaire_id_dossier_id[a.record_id]
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
end
def pjs_for_dossier(dossiers)
motivations(dossiers) +
attestations(dossiers) +
etablissements(dossiers)
end
def etablissements(dossiers)
etablissement_id_dossier_id = Etablissement
.where(dossier: dossiers)
.pluck(:id, :dossier_id)
.to_h
ActiveStorage::Attachment
.includes(:blob)
.where(record_type: "Etablissement", record_id: etablissement_id_dossier_id.keys)
.map do |a|
dossier_id = etablissement_id_dossier_id[a.record_id]
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
end
def motivations(dossiers)
ActiveStorage::Attachment
.includes(:blob)
.where(record_type: "Dossier", name: "justificatif_motivation", record_id: dossiers)
.filter { |a| safe_attachment(a) }
.map do |a|
dossier_id = a.record_id
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
end
def attestations(dossiers)
attestation_id_dossier_id = Attestation
.joins(:pdf_attachment)
.where(dossier: dossiers)
.pluck(:id, :dossier_id)
.to_h
ActiveStorage::Attachment
.includes(:blob)
.where(record_type: "Attestation", record_id: attestation_id_dossier_id.keys)
.map do |a|
dossier_id = attestation_id_dossier_id[a.record_id]
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
end
def pjs_for_avis(dossiers)
avis_ids_dossier_id_query = Avis.joins(:dossier).where(dossier: dossiers)
if !liste_documents_allows?(:with_avis_piece_justificative)
avis_ids_dossier_id_query = avis_ids_dossier_id_query.where(confidentiel: false)
end
if @user_profile.is_a?(Expert)
avis_ids = Avis.joins(:dossier, experts_procedure: :expert)
.where(experts_procedure: { expert: @user_profile })
.where(dossier: dossiers)
.pluck(:id)
avis_ids_dossier_id_query = avis_ids_dossier_id_query.or(Avis.where(id: avis_ids))
end
avis_ids_dossier_id = avis_ids_dossier_id_query.pluck(:id, :dossier_id).to_h
ActiveStorage::Attachment
.includes(:blob)
.where(record_type: "Avis", record_id: avis_ids_dossier_id.keys)
.filter { |a| safe_attachment(a) }
.map do |a|
dossier_id = avis_ids_dossier_id[a.record_id]
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
end
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)
dol_id_data_bill_id = DossierOperationLog
.where(dossier: dossiers)
.with_data
.pluck(:bill_signature_id, :id, :dossier_id, :data, :digest, :created_at)
dol_id_dossier_id = dol_id_dossier_id_bill_id
.map { |_, dol_id, dossier_id| [dol_id, dossier_id] }
.to_h
bill_ids = (dol_id_dossier_id_bill_id + dol_id_data_bill_id)
.map(&:first)
.uniq
.compact
serialized_dols = ActiveStorage::Attachment
.includes(:blob)
.where(record_type: "DossierOperationLog", record_id: dol_id_dossier_id.keys)
.map do |a|
dossier_id = dol_id_dossier_id[a.record_id]
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
serialized_dols += dol_id_data_bill_id.map do |_, id, dossier_id, data, digest, created_at|
a = ActiveStorage::FakeAttachment.new(
file: StringIO.new(data.to_json),
filename: "operation-#{digest}.json",
name: 'serialized',
id: id,
created_at: created_at,
record_type: 'DossierOperationLog'
)
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
end
[serialized_dols, bill_ids]
end
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 safe_attachment(attachment)
attachment
.blob
.virus_scan_result == ActiveStorage::VirusScanner::SAFE
end
end