From a194616772e0b2b9a70b82f28db9ad21dd847d1c Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 8 Apr 2022 17:05:02 +0200 Subject: [PATCH 1/9] refactor(export): remove unnecessary to_sym --- app/models/export.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/export.rb b/app/models/export.rb index a62872c5b..476372bce 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -49,11 +49,11 @@ class Export < ApplicationRecord FORMATS_WITH_TIME_SPAN = [:xlsx, :ods, :csv].flat_map do |format| time_span_types.keys.map do |time_span_type| - { format: format.to_sym, time_span_type: time_span_type } + { format: format, time_span_type: time_span_type } end end FORMATS = [:xlsx, :ods, :csv].map do |format| - { format: format.to_sym } + { format: format } end def compute_async From cf8c084a59f2836d66a81cb34e5de61cef35a5b6 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 8 Apr 2022 17:07:54 +0200 Subject: [PATCH 2/9] refactor: extract download_and_zip in to a shared service --- app/services/downloadable_file_service.rb | 27 ++++++++++++++ app/services/procedure_archive_service.rb | 28 +------------- spec/jobs/archive_creation_job_spec.rb | 4 +- .../downloadable_file_service_spec.rb | 37 +++++++++++++++++++ .../procedure_archive_service_spec.rb | 31 ---------------- 5 files changed, 67 insertions(+), 60 deletions(-) create mode 100644 app/services/downloadable_file_service.rb create mode 100644 spec/services/downloadable_file_service_spec.rb diff --git a/app/services/downloadable_file_service.rb b/app/services/downloadable_file_service.rb new file mode 100644 index 000000000..97909578b --- /dev/null +++ b/app/services/downloadable_file_service.rb @@ -0,0 +1,27 @@ +class DownloadableFileService + ARCHIVE_CREATION_DIR = ENV.fetch('ARCHIVE_CREATION_DIR') { '/tmp' } + + def self.download_and_zip(procedure, attachments, filename, &block) + Dir.mktmpdir(nil, ARCHIVE_CREATION_DIR) do |tmp_dir| + export_dir = File.join(tmp_dir, filename) + zip_path = File.join(ARCHIVE_CREATION_DIR, "#{filename}.zip") + + begin + FileUtils.remove_entry_secure(export_dir) if Dir.exist?(export_dir) + Dir.mkdir(export_dir) + + download_manager = DownloadManager::ProcedureAttachmentsExport.new(procedure, attachments, export_dir) + download_manager.download_all + + Dir.chdir(tmp_dir) do + File.delete(zip_path) if File.exist?(zip_path) + system 'zip', '-0', '-r', zip_path, filename + end + yield(zip_path) + ensure + FileUtils.remove_entry_secure(export_dir) if Dir.exist?(export_dir) + File.delete(zip_path) if File.exist?(zip_path) + end + end + end +end diff --git a/app/services/procedure_archive_service.rb b/app/services/procedure_archive_service.rb index 31f0786f6..6da543ac5 100644 --- a/app/services/procedure_archive_service.rb +++ b/app/services/procedure_archive_service.rb @@ -1,8 +1,6 @@ require 'tempfile' class ProcedureArchiveService - ARCHIVE_CREATION_DIR = ENV.fetch('ARCHIVE_CREATION_DIR') { '/tmp' } - def initialize(procedure) @procedure = procedure end @@ -27,9 +25,9 @@ class ProcedureArchiveService attachments = ActiveStorage::DownloadableFile.create_list_from_dossiers(dossiers) - download_and_zip(archive, attachments) do |zip_filepath| ArchiveUploader.new(procedure: @procedure, archive: archive, filepath: zip_filepath) .upload + DownloadableFileService.download_and_zip(@procedure, attachments, zip_root_folder(archive)) do |zip_filepath| end end @@ -45,30 +43,6 @@ class ProcedureArchiveService private - def download_and_zip(archive, attachments, &block) - Dir.mktmpdir(nil, ARCHIVE_CREATION_DIR) do |tmp_dir| - archive_dir = File.join(tmp_dir, zip_root_folder(archive)) - zip_path = File.join(ARCHIVE_CREATION_DIR, "#{zip_root_folder(archive)}.zip") - - begin - FileUtils.remove_entry_secure(archive_dir) if Dir.exist?(archive_dir) - Dir.mkdir(archive_dir) - - download_manager = DownloadManager::ProcedureAttachmentsExport.new(@procedure, attachments, archive_dir) - download_manager.download_all - - Dir.chdir(tmp_dir) do - File.delete(zip_path) if File.exist?(zip_path) - system 'zip', '-0', '-r', zip_path, zip_root_folder(archive) - end - yield(zip_path) - ensure - FileUtils.remove_entry_secure(archive_dir) if Dir.exist?(archive_dir) - File.delete(zip_path) if File.exist?(zip_path) - end - end - end - def zip_root_folder(archive) "procedure-#{@procedure.id}-#{archive.id}" end diff --git a/spec/jobs/archive_creation_job_spec.rb b/spec/jobs/archive_creation_job_spec.rb index 2f4f38425..985a0d1d8 100644 --- a/spec/jobs/archive_creation_job_spec.rb +++ b/spec/jobs/archive_creation_job_spec.rb @@ -11,7 +11,7 @@ describe ArchiveCreationJob, type: :job do before { expect(InstructeurMailer).not_to receive(:send_archive) } it 'does not send email and forward error for retry' do - allow_any_instance_of(ProcedureArchiveService).to receive(:download_and_zip).and_raise(StandardError, "kaboom") + allow(DownloadableFileService).to receive(:download_and_zip).and_raise(StandardError, "kaboom") expect { job.perform_now }.to raise_error(StandardError, "kaboom") expect(archive.reload.failed?).to eq(true) end @@ -20,7 +20,7 @@ describe ArchiveCreationJob, type: :job do context 'when it works' do let(:mailer) { double('mailer', deliver_later: true) } before do - allow_any_instance_of(ProcedureArchiveService).to receive(:download_and_zip).and_return(true) + allow(DownloadableFileService).to receive(:download_and_zip).and_return(true) expect(InstructeurMailer).to receive(:send_archive).and_return(mailer) end diff --git a/spec/services/downloadable_file_service_spec.rb b/spec/services/downloadable_file_service_spec.rb new file mode 100644 index 000000000..5e8c3c497 --- /dev/null +++ b/spec/services/downloadable_file_service_spec.rb @@ -0,0 +1,37 @@ +describe DownloadableFileService do + let(:procedure) { create(:procedure, :published) } + let(:service) { ProcedureArchiveService.new(procedure) } + + describe '#download_and_zip' do + let(:archive) { build(:archive, id: '3') } + let(:filename) { service.send(:zip_root_folder, archive) } + + it 'create a tmpdir while block is running' do + previous_dir_list = Dir.entries(DownloadableFileService::ARCHIVE_CREATION_DIR) + + DownloadableFileService.download_and_zip(procedure, [], filename) do |_zip_file| + new_dir_list = Dir.entries(DownloadableFileService::ARCHIVE_CREATION_DIR) + expect(previous_dir_list).not_to eq(new_dir_list) + end + end + + it 'cleans up its tmpdir after block execution' do + expect { DownloadableFileService.download_and_zip(procedure, [], filename) { |zip_file| } } + .not_to change { Dir.entries(DownloadableFileService::ARCHIVE_CREATION_DIR) } + end + + it 'creates a zip with zip utility' do + expected_zip_path = File.join(DownloadableFileService::ARCHIVE_CREATION_DIR, "#{service.send(:zip_root_folder, archive)}.zip") + expect(DownloadableFileService).to receive(:system).with('zip', '-0', '-r', expected_zip_path, an_instance_of(String)) + DownloadableFileService.download_and_zip(procedure, [], filename) { |zip_path| } + end + + it 'cleans up its generated zip' do + expected_zip_path = File.join(DownloadableFileService::ARCHIVE_CREATION_DIR, "#{service.send(:zip_root_folder, archive)}.zip") + DownloadableFileService.download_and_zip(procedure, [], filename) do |_zip_path| + expect(File.exist?(expected_zip_path)).to be_truthy + end + expect(File.exist?(expected_zip_path)).to be_falsey + end + end +end diff --git a/spec/services/procedure_archive_service_spec.rb b/spec/services/procedure_archive_service_spec.rb index 72c99a62a..73b7c7917 100644 --- a/spec/services/procedure_archive_service_spec.rb +++ b/spec/services/procedure_archive_service_spec.rb @@ -172,37 +172,6 @@ describe ProcedureArchiveService do end end - describe '#download_and_zip' do - let(:archive) { build(:archive, id: '3') } - it 'create a tmpdir while block is running' do - previous_dir_list = Dir.entries(ProcedureArchiveService::ARCHIVE_CREATION_DIR) - - service.send(:download_and_zip, archive, []) do |_zip_file| - new_dir_list = Dir.entries(ProcedureArchiveService::ARCHIVE_CREATION_DIR) - expect(previous_dir_list).not_to eq(new_dir_list) - end - end - - it 'cleans up its tmpdir after block execution' do - expect { service.send(:download_and_zip, archive, []) { |zip_file| } } - .not_to change { Dir.entries(ProcedureArchiveService::ARCHIVE_CREATION_DIR) } - end - - it 'creates a zip with zip utility' do - expected_zip_path = File.join(ProcedureArchiveService::ARCHIVE_CREATION_DIR, "#{service.send(:zip_root_folder, archive)}.zip") - expect(service).to receive(:system).with('zip', '-0', '-r', expected_zip_path, an_instance_of(String)) - service.send(:download_and_zip, archive, []) { |zip_path| } - end - - it 'cleans up its generated zip' do - expected_zip_path = File.join(ProcedureArchiveService::ARCHIVE_CREATION_DIR, "#{service.send(:zip_root_folder, archive)}.zip") - service.send(:download_and_zip, archive, []) do |_zip_path| - expect(File.exist?(expected_zip_path)).to be_truthy - end - expect(File.exist?(expected_zip_path)).to be_falsey - end - end - private def create_dossier_for_month(year, month) From 561b83781e2bcb27cd1d72eab50aaa394d863341 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 8 Apr 2022 17:09:22 +0200 Subject: [PATCH 3/9] refactor(archive): remove dependencie on archive from ArchiveUploader --- app/services/archive_uploader.rb | 14 +++++++++----- app/services/procedure_archive_service.rb | 4 ++-- spec/services/archive_uploader_spec.rb | 12 ++++++------ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/services/archive_uploader.rb b/app/services/archive_uploader.rb index c3dd7581f..fc644a65e 100644 --- a/app/services/archive_uploader.rb +++ b/app/services/archive_uploader.rb @@ -4,7 +4,7 @@ class ArchiveUploader # when file size is bigger, active storage expects the chunks + a manifest. MAX_FILE_SIZE_FOR_BACKEND_BEFORE_CHUNKING = ENV.fetch('ACTIVE_STORAGE_FILE_SIZE_THRESHOLD_BEFORE_CUSTOM_UPLOAD') { 4.gigabytes }.to_i - def upload + def upload(archive) uploaded_blob = create_and_upload_blob begin archive.file.purge if archive.file.attached? @@ -21,9 +21,13 @@ class ArchiveUploader ) end + def blob + create_and_upload_blob + end + private - attr_reader :procedure, :archive, :filepath + attr_reader :procedure, :filename, :filepath def create_and_upload_blob if active_storage_service_local? || File.size(filepath) < MAX_FILE_SIZE_FOR_BACKEND_BEFORE_CHUNKING @@ -62,7 +66,7 @@ class ArchiveUploader def blob_default_params(filepath) { key: namespaced_object_key, - filename: archive.filename(procedure), + filename: filename, content_type: 'application/zip', metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } } @@ -89,9 +93,9 @@ class ArchiveUploader system(ENV.fetch('ACTIVE_STORAGE_BIG_FILE_UPLOADER_WITH_ENCRYPTION_PATH').to_s, filepath, blob.key, exception: true) end - def initialize(procedure:, archive:, filepath:) + def initialize(procedure:, filename:, filepath:) @procedure = procedure - @archive = archive + @filename = filename @filepath = filepath end end diff --git a/app/services/procedure_archive_service.rb b/app/services/procedure_archive_service.rb index 6da543ac5..d0aa7efea 100644 --- a/app/services/procedure_archive_service.rb +++ b/app/services/procedure_archive_service.rb @@ -25,9 +25,9 @@ class ProcedureArchiveService attachments = ActiveStorage::DownloadableFile.create_list_from_dossiers(dossiers) - ArchiveUploader.new(procedure: @procedure, archive: archive, filepath: zip_filepath) - .upload DownloadableFileService.download_and_zip(@procedure, attachments, zip_root_folder(archive)) do |zip_filepath| + ArchiveUploader.new(procedure: @procedure, filename: archive.filename(@procedure), filepath: zip_filepath) + .upload(archive) end end diff --git a/spec/services/archive_uploader_spec.rb b/spec/services/archive_uploader_spec.rb index eb6a41f0b..c916d7e2b 100644 --- a/spec/services/archive_uploader_spec.rb +++ b/spec/services/archive_uploader_spec.rb @@ -4,18 +4,18 @@ describe ProcedureArchiveService do let(:file) { Tempfile.new } let(:fixture_blob) { ActiveStorage::Blob.create_before_direct_upload!(filename: File.basename(file.path), byte_size: file.size, checksum: 'osf') } - let(:uploader) { ArchiveUploader.new(procedure: procedure, archive: archive, filepath: file.path) } + let(:uploader) { ArchiveUploader.new(procedure: procedure, filename: archive.filename(procedure), filepath: file.path) } describe '.upload' do context 'when active storage service is local' do it 'uploads with upload_with_active_storage' do expect(uploader).to receive(:active_storage_service_local?).and_return(true) expect(uploader).to receive(:upload_with_active_storage).and_return(fixture_blob) - uploader.upload + uploader.upload(archive) end it 'link the created blob as an attachment to the current archive instance' do - expect { uploader.upload } + expect { uploader.upload(archive) } .to change { ActiveStorage::Attachment.where(name: 'file', record_type: 'Archive', record_id: archive.id).count }.by(1) end end @@ -31,7 +31,7 @@ describe ProcedureArchiveService do it 'uploads with upload_with_active_storage' do expect(uploader).to receive(:upload_with_active_storage).and_return(fixture_blob) - uploader.upload + uploader.upload(archive) end end @@ -40,12 +40,12 @@ describe ProcedureArchiveService do it 'uploads with upload_with_chunking_wrapper' do expect(uploader).to receive(:upload_with_chunking_wrapper).and_return(fixture_blob) - uploader.upload + uploader.upload(archive) end it 'link the created blob as an attachment to the current archive instance' do expect(uploader).to receive(:upload_with_chunking_wrapper).and_return(fixture_blob) - expect { uploader.upload } + expect { uploader.upload(archive) } .to change { ActiveStorage::Attachment.where(name: 'file', record_type: 'Archive', record_id: archive.id).count }.by(1) end end From 87e5e6faeb3fe8847123fd76170533a6049dfea9 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 8 Apr 2022 17:10:46 +0200 Subject: [PATCH 4/9] refactor(export): add procedure attr to export service --- app/services/procedure_export_service.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/services/procedure_export_service.rb b/app/services/procedure_export_service.rb index 7381b32ea..7366f3f53 100644 --- a/app/services/procedure_export_service.rb +++ b/app/services/procedure_export_service.rb @@ -1,5 +1,5 @@ class ProcedureExportService - attr_reader :dossiers + attr_reader :procedure, :dossiers def initialize(procedure, dossiers) @procedure = procedure @@ -40,12 +40,12 @@ class ProcedureExportService end def champs_repetables_options - revision = @procedure.active_revision + revision = procedure.active_revision champs_by_stable_id = dossiers .flat_map { |dossier| (dossier.champs + dossier.champs_private).filter(&:repetition?) } .group_by(&:stable_id) - @procedure.types_de_champ_for_procedure_presentation.repetition + procedure.types_de_champ_for_procedure_presentation.repetition .map { |type_de_champ_repetition| [type_de_champ_repetition, type_de_champ_repetition.types_de_champ_for_revision(revision).to_a] } .filter { |(_, types_de_champ)| types_de_champ.present? } .map do |(type_de_champ_repetition, types_de_champ)| @@ -85,7 +85,7 @@ class ProcedureExportService end def spreadsheet_columns(format) - types_de_champ = @procedure.types_de_champ_for_procedure_presentation.not_repetition.to_a + types_de_champ = procedure.types_de_champ_for_procedure_presentation.not_repetition.to_a Proc.new do |instance| instance.send(:"spreadsheet_columns_#{format}", types_de_champ: types_de_champ) From 2832ea0286546706a245ad0c168bafcc4d222f8e Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 8 Apr 2022 17:12:34 +0200 Subject: [PATCH 5/9] refactor(export): return blob from to_* methods --- app/models/export.rb | 32 ++----------- app/services/procedure_export_service.rb | 48 +++++++++++++++++-- .../services/procedure_export_service_spec.rb | 16 +++---- 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/app/models/export.rb b/app/models/export.rb index 476372bce..988e78c1a 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -63,13 +63,7 @@ class Export < ApplicationRecord def compute load_snapshot! - file.attach( - io: io, - filename: filename, - content_type: content_type, - # We generate the exports ourselves, so they are safe - metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } - ) + file.attach(blob) end def since @@ -177,32 +171,16 @@ class Export < ApplicationRecord end end - def filename - procedure_identifier = procedure.path || "procedure-#{procedure.id}" - "dossiers_#{procedure_identifier}_#{statut}_#{Time.zone.now.strftime('%Y-%m-%d_%H-%M')}.#{format}" - end - - def io + def blob service = ProcedureExportService.new(procedure, dossiers_for_export) case format.to_sym when :csv - StringIO.new(service.to_csv) + service.to_csv when :xlsx - StringIO.new(service.to_xlsx) + service.to_xlsx when :ods - StringIO.new(service.to_ods) - end - end - - def content_type - case format.to_sym - when :csv - 'text/csv' - when :xlsx - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - when :ods - 'application/vnd.oasis.opendocument.spreadsheet' + service.to_ods end end diff --git a/app/services/procedure_export_service.rb b/app/services/procedure_export_service.rb index 7366f3f53..a9b3fc280 100644 --- a/app/services/procedure_export_service.rb +++ b/app/services/procedure_export_service.rb @@ -8,25 +8,63 @@ class ProcedureExportService end def to_csv - SpreadsheetArchitect.to_csv(options_for(:dossiers, :csv)) + io = StringIO.new(SpreadsheetArchitect.to_csv(options_for(:dossiers, :csv))) + create_blob(io, :csv) end def to_xlsx # We recursively build multi page spreadsheet - @tables.reduce(nil) do |package, table| + io = @tables.reduce(nil) do |package, table| SpreadsheetArchitect.to_axlsx_package(options_for(table, :xlsx), package) - end.to_stream.read + end.to_stream + create_blob(io, :xlsx) end def to_ods # We recursively build multi page spreadsheet - @tables.reduce(nil) do |spreadsheet, table| + io = StringIO.new(@tables.reduce(nil) do |spreadsheet, table| SpreadsheetArchitect.to_rodf_spreadsheet(options_for(table, :ods), spreadsheet) - end.bytes + end.bytes) + create_blob(io, :ods) + end end private + def create_blob(io, format) + ActiveStorage::Blob.create_and_upload!( + io: io, + filename: filename(format), + content_type: content_type(format), + identify: false, + # We generate the exports ourselves, so they are safe + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + ) + end + + def base_filename + @base_filename ||= "dossiers_#{procedure_identifier}_#{Time.zone.now.strftime('%Y-%m-%d_%H-%M')}" + end + + def filename(format) + "#{base_filename}.#{format}" + end + + def procedure_identifier + procedure.path || "procedure-#{procedure.id}" + end + + def content_type(format) + case format + when :csv + 'text/csv' + when :xlsx + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + when :ods + 'application/vnd.oasis.opendocument.spreadsheet' + end + end + def etablissements @etablissements ||= dossiers.flat_map do |dossier| [dossier.champs, dossier.champs_private] diff --git a/spec/services/procedure_export_service_spec.rb b/spec/services/procedure_export_service_spec.rb index c91dace09..1021691b6 100644 --- a/spec/services/procedure_export_service_spec.rb +++ b/spec/services/procedure_export_service_spec.rb @@ -4,11 +4,9 @@ describe ProcedureExportService do describe 'to_data' do let(:procedure) { create(:procedure, :published, :for_individual, :with_all_champs) } subject do - Tempfile.create do |f| - f << ProcedureExportService.new(procedure, procedure.dossiers).to_xlsx - f.rewind - SimpleXlsxReader.open(f.path) - end + ProcedureExportService.new(procedure, procedure.dossiers) + .to_xlsx + .open { |f| SimpleXlsxReader.open(f.path) } end let(:dossiers_sheet) { subject.sheets.first } @@ -178,11 +176,9 @@ describe ProcedureExportService do context 'as csv' do subject do - Tempfile.create do |f| - f << ProcedureExportService.new(procedure, procedure.dossiers).to_csv - f.rewind - CSV.read(f.path) - end + ProcedureExportService.new(procedure, procedure.dossiers) + .to_csv + .open { |f| CSV.read(f.path) } end let(:nominal_headers) do From d14e13230534d91aa5afdf2b92f9cbbf9cc3a9a1 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 8 Apr 2022 17:12:53 +0200 Subject: [PATCH 6/9] feat(export): add zip format support --- app/models/export.rb | 17 ++++++++++++++--- app/services/procedure_export_service.rb | 9 +++++++++ .../views/instructeurs/procedures/fr.yml | 1 + spec/models/export_spec.rb | 6 +++--- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/app/models/export.rb b/app/models/export.rb index 988e78c1a..e6ceb89d7 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -18,8 +18,9 @@ class Export < ApplicationRecord enum format: { csv: 'csv', ods: 'ods', - xlsx: 'xlsx' - } + xlsx: 'xlsx', + zip: 'zip' + }, _prefix: true enum time_span_type: { everything: 'everything', @@ -52,7 +53,7 @@ class Export < ApplicationRecord { format: format, time_span_type: time_span_type } end end - FORMATS = [:xlsx, :ods, :csv].map do |format| + FORMATS = [:xlsx, :ods, :csv, :zip].map do |format| { format: format } end @@ -98,6 +99,10 @@ class Export < ApplicationRecord format == self.class.formats.fetch(:csv) end + def zip? + format == self.class.formats.fetch(:zip) + end + def self.find_or_create_export(format, groupe_instructeurs, time_span_type: time_span_types.fetch(:everything), statut: statuts.fetch(:tous), procedure_presentation: nil) create_with(groupe_instructeurs: groupe_instructeurs, procedure_presentation: procedure_presentation, procedure_presentation_snapshot: procedure_presentation&.snapshot) .includes(:procedure_presentation) @@ -128,6 +133,10 @@ class Export < ApplicationRecord csv: { time_span_type: not_filtered.filter(&:csv?).index_by(&:time_span_type), statut: filtered.filter(&:csv?).index_by(&:statut) + }, + zip: { + time_span_type: {}, + statut: filtered.filter(&:zip?).index_by(&:statut) } } end @@ -181,6 +190,8 @@ class Export < ApplicationRecord service.to_xlsx when :ods service.to_ods + when :zip + service.to_zip end end diff --git a/app/services/procedure_export_service.rb b/app/services/procedure_export_service.rb index a9b3fc280..907426fd6 100644 --- a/app/services/procedure_export_service.rb +++ b/app/services/procedure_export_service.rb @@ -27,6 +27,13 @@ class ProcedureExportService end.bytes) create_blob(io, :ods) end + + def to_zip + attachments = ActiveStorage::DownloadableFile.create_list_from_dossiers(dossiers, true) + + DownloadableFileService.download_and_zip(procedure, attachments, base_filename) do |zip_filepath| + ArchiveUploader.new(procedure: procedure, filename: filename(:zip), filepath: zip_filepath).blob + end end private @@ -62,6 +69,8 @@ class ProcedureExportService 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' when :ods 'application/vnd.oasis.opendocument.spreadsheet' + when :zip + 'application/zip' end end diff --git a/config/locales/views/instructeurs/procedures/fr.yml b/config/locales/views/instructeurs/procedures/fr.yml index 9cf758507..b4139e687 100644 --- a/config/locales/views/instructeurs/procedures/fr.yml +++ b/config/locales/views/instructeurs/procedures/fr.yml @@ -5,6 +5,7 @@ fr: everything_csv_html: Demander un export au format .csv
(uniquement les dossiers, sans les champs répétables) everything_xlsx_html: Demander un export au format .xlsx everything_ods_html: Demander un export au format .ods + everything_zip_html: Demander un export au format .zip everything_short: Demander un export au format %{export_format} everything_pending_html: Un export au format %{export_format} est en train d’être généré
(demandé il y a %{export_time}) everything_ready_html: Télécharger l’export au format %{export_format}
(généré il y a %{export_time}) diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb index 2bfdec18a..3511895e5 100644 --- a/spec/models/export_spec.rb +++ b/spec/models/export_spec.rb @@ -48,9 +48,9 @@ RSpec.describe Export, type: :model do context 'when an export is made for one groupe instructeur' do let!(:export) { create(:export, groupe_instructeurs: [gi_1, gi_2]) } - it { expect(Export.find_for_groupe_instructeurs([gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} } }) } - it { expect(Export.find_for_groupe_instructeurs([gi_2.id, gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: { 'everything' => export } }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} } }) } - it { expect(Export.find_for_groupe_instructeurs([gi_1.id, gi_2.id, gi_3.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} } }) } + it { expect(Export.find_for_groupe_instructeurs([gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} } }) } + it { expect(Export.find_for_groupe_instructeurs([gi_2.id, gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: { 'everything' => export } }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} } }) } + it { expect(Export.find_for_groupe_instructeurs([gi_1.id, gi_2.id, gi_3.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} } }) } end end end From caace89d98e83d461347f76a4d210407f071a7f2 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 12 Apr 2022 11:59:24 +0200 Subject: [PATCH 7/9] refactor(export): use predefined helpers --- app/models/export.rb | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/app/models/export.rb b/app/models/export.rb index e6ceb89d7..545935673 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -87,22 +87,6 @@ class Export < ApplicationRecord procedure_presentation_id.present? end - def xlsx? - format == self.class.formats.fetch(:xlsx) - end - - def ods? - format == self.class.formats.fetch(:ods) - end - - def csv? - format == self.class.formats.fetch(:csv) - end - - def zip? - format == self.class.formats.fetch(:zip) - end - def self.find_or_create_export(format, groupe_instructeurs, time_span_type: time_span_types.fetch(:everything), statut: statuts.fetch(:tous), procedure_presentation: nil) create_with(groupe_instructeurs: groupe_instructeurs, procedure_presentation: procedure_presentation, procedure_presentation_snapshot: procedure_presentation&.snapshot) .includes(:procedure_presentation) @@ -123,20 +107,20 @@ class Export < ApplicationRecord { xlsx: { - time_span_type: not_filtered.filter(&:xlsx?).index_by(&:time_span_type), - statut: filtered.filter(&:xlsx?).index_by(&:statut) + time_span_type: not_filtered.filter(&:format_xlsx?).index_by(&:time_span_type), + statut: filtered.filter(&:format_xlsx?).index_by(&:statut) }, ods: { - time_span_type: not_filtered.filter(&:ods?).index_by(&:time_span_type), - statut: filtered.filter(&:ods?).index_by(&:statut) + time_span_type: not_filtered.filter(&:format_ods?).index_by(&:time_span_type), + statut: filtered.filter(&:format_ods?).index_by(&:statut) }, csv: { - time_span_type: not_filtered.filter(&:csv?).index_by(&:time_span_type), - statut: filtered.filter(&:csv?).index_by(&:statut) + time_span_type: not_filtered.filter(&:format_csv?).index_by(&:time_span_type), + statut: filtered.filter(&:format_csv?).index_by(&:statut) }, zip: { time_span_type: {}, - statut: filtered.filter(&:zip?).index_by(&:statut) + statut: filtered.filter(&:format_zip?).index_by(&:statut) } } end From 38a6b2db6379e7a3c36fd7cda1e32b939b3c6bee Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 12 Apr 2022 19:02:59 +0200 Subject: [PATCH 8/9] fix(graphql): fix AddressTypeType --- app/graphql/types/address_type.rb | 8 ++++---- app/graphql/types/personne_morale_type.rb | 2 +- spec/graphql/dossier_spec.rb | 25 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/app/graphql/types/address_type.rb b/app/graphql/types/address_type.rb index 86a1d8756..60f3370f3 100644 --- a/app/graphql/types/address_type.rb +++ b/app/graphql/types/address_type.rb @@ -1,10 +1,10 @@ module Types class AddressType < Types::BaseObject class AddressTypeType < Types::BaseEnum - value(:housenumber, "numéro « à la plaque »", value: :housenumber) - value(:street, "position « à la voie », placé approximativement au centre de celle-ci", value: :street) - value(:municipality, "numéro « à la commune »", value: :municipality) - value(:locality, "lieu-dit", value: :locality) + value(:housenumber, "numéro « à la plaque »", value: "housenumber") + value(:street, "position « à la voie », placé approximativement au centre de celle-ci", value: "street") + value(:municipality, "numéro « à la commune »", value: "municipality") + value(:locality, "lieu-dit", value: "locality") end field :label, String, "libellé complet de l’adresse", null: false diff --git a/app/graphql/types/personne_morale_type.rb b/app/graphql/types/personne_morale_type.rb index c8176befa..2d2d98d2b 100644 --- a/app/graphql/types/personne_morale_type.rb +++ b/app/graphql/types/personne_morale_type.rb @@ -104,7 +104,7 @@ module Types def address { label: object.adresse, - type: :housenumber, + type: "housenumber", street_number: object.numero_voie, street_name: object.nom_voie, street_address: object.nom_voie.present? ? [object.numero_voie, object.type_voie, object.nom_voie].compact.join(' ') : nil, diff --git a/spec/graphql/dossier_spec.rb b/spec/graphql/dossier_spec.rb index 7ff4cc1c3..6aba97515 100644 --- a/spec/graphql/dossier_spec.rb +++ b/spec/graphql/dossier_spec.rb @@ -31,6 +31,26 @@ RSpec.describe Types::DossierType, type: :graphql do let(:dossier) { create(:dossier, :accepte, :with_populated_champs, procedure: procedure) } let(:query) { DOSSIER_WITH_CHAMPS_QUERY } let(:variables) { { number: dossier.id } } + let(:address) do + { + "type" => "housenumber", + "label" => "33 Rue Rébeval 75019 Paris", + "city_code" => "75119", + "city_name" => "Paris", + "postal_code" => "75019", + "region_code" => "11", + "region_name" => "Île-de-France", + "street_name" => "Rue Rébeval", + "street_number" => "33", + "street_address" => "33 Rue Rébeval", + "department_code" => "75", + "department_name" => "Paris" + } + end + + before do + dossier.champs.second.update(data: address) + end it { expect(data[:dossier][:champs][0][:__typename]).to eq "CommuneChamp" } it { expect(data[:dossier][:champs][1][:__typename]).to eq "AddressChamp" } @@ -86,7 +106,12 @@ RSpec.describe Types::DossierType, type: :graphql do code } fragment AddressFragment on Address { + type + label cityName + cityCode + streetName + streetNumber } GRAPHQL end From 433c01b1e6a951a92ce688ce0d26c7cd0cc3c259 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 12 Apr 2022 19:20:50 +0200 Subject: [PATCH 9/9] Revert "Merge pull request #7137 from betagouv/faster_pdf" This reverts commit 9da44bd913b8400c9c90de506f375607d67340d4, reversing changes made to ebac71796caf2ecd9ec76e42614e045838179b4a. --- Gemfile | 1 + Gemfile.lock | 4 ++ app/assets/images/header/logo-ds-wide.png | Bin 18553 -> 0 bytes app/lib/active_storage/downloadable_file.rb | 5 +- app/models/dossier.rb | 5 +- app/services/pieces_justificatives_service.rb | 51 +++++------------- app/views/dossiers/dossier_vide.pdf.prawn | 2 +- app/views/dossiers/show.pdf.prawn | 23 ++++---- config/env.example.optional | 2 +- config/initializers/images.rb | 2 +- .../pieces_justificatives_service_spec.rb | 2 +- 11 files changed, 37 insertions(+), 60 deletions(-) delete mode 100644 app/assets/images/header/logo-ds-wide.png diff --git a/Gemfile b/Gemfile index 24f8c36c9..e210be466 100644 --- a/Gemfile +++ b/Gemfile @@ -59,6 +59,7 @@ gem 'openid_connect' gem 'pg' gem 'phonelib' gem 'prawn-rails' # PDF Generation +gem 'prawn-svg' gem 'premailer-rails' gem 'puma' # Use Puma as the app server gem 'pundit' diff --git a/Gemfile.lock b/Gemfile.lock index 0faaa9859..4485809aa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -459,6 +459,9 @@ GEM prawn prawn-table rails (>= 3.1.0) + prawn-svg (0.31.0) + css_parser (~> 1.6) + prawn (>= 0.11.1, < 3) prawn-table (0.2.2) prawn (>= 1.3.0, < 3.0.0) premailer (1.14.2) @@ -837,6 +840,7 @@ DEPENDENCIES pg phonelib prawn-rails + prawn-svg premailer-rails pry-byebug puma diff --git a/app/assets/images/header/logo-ds-wide.png b/app/assets/images/header/logo-ds-wide.png deleted file mode 100644 index a0ac0f35319574a377870e6f6150bf2d21b2e8d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18553 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 diff --git a/app/lib/active_storage/downloadable_file.rb b/app/lib/active_storage/downloadable_file.rb index ac1cb2a8d..3f38007be 100644 --- a/app/lib/active_storage/downloadable_file.rb +++ b/app/lib/active_storage/downloadable_file.rb @@ -1,7 +1,8 @@ class ActiveStorage::DownloadableFile def self.create_list_from_dossiers(dossiers, for_expert = false) - PiecesJustificativesService.generate_dossier_export(dossiers) + - PiecesJustificativesService.liste_documents(dossiers, for_expert) + dossiers + .map { |d| pj_and_path(d.id, PiecesJustificativesService.generate_dossier_export(d)) } + + PiecesJustificativesService.liste_documents(dossiers, for_expert) end private diff --git a/app/models/dossier.rb b/app/models/dossier.rb index aa18b21d0..e32aa99db 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -485,9 +485,8 @@ class Dossier < ApplicationRecord end def motivation - if termine? - traitement&.motivation || read_attribute(:motivation) - end + return nil if !termine? + traitement&.motivation || read_attribute(:motivation) end def update_search_terms diff --git a/app/services/pieces_justificatives_service.rb b/app/services/pieces_justificatives_service.rb index 7b8472563..aec2c0378 100644 --- a/app/services/pieces_justificatives_service.rb +++ b/app/services/pieces_justificatives_service.rb @@ -107,44 +107,21 @@ class PiecesJustificativesService end end - def self.generate_dossier_export(dossiers) - return [] if dossiers.empty? + def self.generate_dossier_export(dossier) + pdf = ApplicationController + .render(template: 'dossiers/show', formats: [:pdf], + assigns: { + include_infos_administration: true, + dossier: dossier + }) - pdfs = [] - - procedure = dossiers.first.procedure - tdc_by_id = TypeDeChamp - .joins(:revisions) - .where(revisions: { id: procedure.revisions }) - .to_a - .group_by(&:id) - - dossiers - .includes(:champs, :champs_private, :commentaires, :individual, - :traitement, :etablissement, - user: :france_connect_information, avis: :expert) - .find_each do |dossier| - pdf = ApplicationController - .render(template: 'dossiers/show', formats: [:pdf], - assigns: { - include_infos_administration: true, - dossier: dossier, - procedure: procedure, - tdc_by_id: tdc_by_id - }) - - a = 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 + FakeAttachment.new( + file: StringIO.new(pdf), + filename: "export-#{dossier.id}.pdf", + name: 'pdf_export_for_instructeur', + id: dossier.id, + created_at: dossier.updated_at + ) end private diff --git a/app/views/dossiers/dossier_vide.pdf.prawn b/app/views/dossiers/dossier_vide.pdf.prawn index f941d0537..5678ee1b0 100644 --- a/app/views/dossiers/dossier_vide.pdf.prawn +++ b/app/views/dossiers/dossier_vide.pdf.prawn @@ -181,7 +181,7 @@ prawn_document(page_size: "A4") do |pdf| italic: Rails.root.join('lib/prawn/fonts/marianne/marianne-thin.ttf' ), }) pdf.font 'marianne' - pdf.image DOSSIER_PDF_EXPORT_LOGO_SRC, width: 300, position: :center + pdf.svg IO.read(DOSSIER_PDF_EXPORT_LOGO_SRC), width: 300, position: :center pdf.move_down(40) render_in_2_columns(pdf, 'Démarche', @dossier.procedure.libelle) diff --git a/app/views/dossiers/show.pdf.prawn b/app/views/dossiers/show.pdf.prawn index 182d60fc0..b3b86eba6 100644 --- a/app/views/dossiers/show.pdf.prawn +++ b/app/views/dossiers/show.pdf.prawn @@ -130,30 +130,28 @@ def add_identite_etablissement(pdf, etablissement) end def add_single_champ(pdf, champ) - tdc = @tdc_by_id[champ.type_de_champ_id].first - case champ.type when 'Champs::PieceJustificativeChamp', 'Champs::TitreIdentiteChamp' return when 'Champs::HeaderSectionChamp' - add_section_title(pdf, tdc.libelle) + add_section_title(pdf, champ.libelle) when 'Champs::ExplicationChamp' - format_in_2_lines(pdf, tdc.libelle, tdc.description) + format_in_2_lines(pdf, champ.libelle, champ.description) when 'Champs::CarteChamp' - format_in_2_lines(pdf, tdc.libelle, champ.to_feature_collection.to_json) + format_in_2_lines(pdf, champ.libelle, champ.to_feature_collection.to_json) when 'Champs::SiretChamp' pdf.font 'marianne', style: :bold do - pdf.text tdc.libelle + pdf.text champ.libelle end if champ.etablissement.present? add_identite_etablissement(pdf, champ.etablissement) end when 'Champs::NumberChamp' value = champ.to_s.empty? ? 'Non communiqué' : number_with_delimiter(champ.to_s) - format_in_2_lines(pdf, tdc.libelle, value) + format_in_2_lines(pdf, champ.libelle, value) else value = champ.to_s.empty? ? 'Non communiqué' : champ.to_s - format_in_2_lines(pdf, tdc.libelle, value) + format_in_2_lines(pdf, champ.libelle, value) end end @@ -207,9 +205,6 @@ def add_etats_dossier(pdf, dossier) end prawn_document(page_size: "A4") do |pdf| - @procedure ||= @dossier.procedure - @tdc_by_id ||= @dossier.champs.map(&:type_de_champ).group_by(&:id) - pdf.font_families.update( 'marianne' => { normal: Rails.root.join('lib/prawn/fonts/marianne/marianne-regular.ttf' ), bold: Rails.root.join('lib/prawn/fonts/marianne/marianne-bold.ttf' ), @@ -217,12 +212,12 @@ prawn_document(page_size: "A4") do |pdf| pdf.font 'marianne' pdf.pad_bottom(40) do - pdf.image DOSSIER_PDF_EXPORT_LOGO_SRC, width: 300, position: :center + pdf.svg IO.read(DOSSIER_PDF_EXPORT_LOGO_SRC), width: 300, position: :center end format_in_2_columns(pdf, 'Dossier Nº', @dossier.id.to_s) - format_in_2_columns(pdf, 'Démarche', @procedure.libelle) - format_in_2_columns(pdf, 'Organisme', @procedure.organisation_name) + format_in_2_columns(pdf, 'Démarche', @dossier.procedure.libelle) + format_in_2_columns(pdf, 'Organisme', @dossier.procedure.organisation_name) add_etat_dossier(pdf, @dossier) diff --git a/config/env.example.optional b/config/env.example.optional index 8cee6a933..51b05c16d 100644 --- a/config/env.example.optional +++ b/config/env.example.optional @@ -69,7 +69,7 @@ DS_ENV="staging" # PROCEDURE_DEFAULT_LOGO_SRC="republique-francaise-logo.svg" # Instance customization: PDF export logo ---> to be put in "app/assets/images" -# DOSSIER_PDF_EXPORT_LOGO_SRC="app/assets/images/header/logo-ds-wide.png" +# DOSSIER_PDF_EXPORT_LOGO_SRC="app/assets/images/header/logo-ds-wide.svg" # Instance customization: watermark for identity documents # WATERMARK_FILE="" diff --git a/config/initializers/images.rb b/config/initializers/images.rb index 161c9fc24..c488aa279 100644 --- a/config/initializers/images.rb +++ b/config/initializers/images.rb @@ -17,4 +17,4 @@ MAILER_FOOTER_LOGO_SRC = ENV.fetch("MAILER_FOOTER_LOGO_SRC", "mailer/instructeur PROCEDURE_DEFAULT_LOGO_SRC = ENV.fetch("PROCEDURE_DEFAULT_LOGO_SRC", "republique-francaise-logo.svg") # Logo in PDF export of a "Dossier" -DOSSIER_PDF_EXPORT_LOGO_SRC = ENV.fetch("DOSSIER_PDF_EXPORT_LOGO_SRC", "app/assets/images/header/logo-ds-wide.png") +DOSSIER_PDF_EXPORT_LOGO_SRC = ENV.fetch("DOSSIER_PDF_EXPORT_LOGO_SRC", "app/assets/images/header/logo-ds-wide.svg") diff --git a/spec/services/pieces_justificatives_service_spec.rb b/spec/services/pieces_justificatives_service_spec.rb index a262d6817..a7b715786 100644 --- a/spec/services/pieces_justificatives_service_spec.rb +++ b/spec/services/pieces_justificatives_service_spec.rb @@ -192,7 +192,7 @@ describe PiecesJustificativesService do describe '.generate_dossier_export' do let(:dossier) { create(:dossier) } - subject { PiecesJustificativesService.generate_dossier_export(Dossier.where(id: dossier.id)) } + subject { PiecesJustificativesService.generate_dossier_export(dossier) } it "doesn't update dossier" do expect { subject }.not_to change { dossier.updated_at }