diff --git a/app/services/procedure_archive_service.rb b/app/services/procedure_archive_service.rb index 0d66cb319..1d170c789 100644 --- a/app/services/procedure_archive_service.rb +++ b/app/services/procedure_archive_service.rb @@ -1,5 +1,4 @@ require 'tempfile' -require 'utils/retryable' class ProcedureArchiveService include Utils::Retryable @@ -18,7 +17,15 @@ class ProcedureArchiveService end def collect_files_archive(archive, instructeur) - ## faux, ca ne doit prendre que certains groupe instructeur + if Flipper.enabled?(:zip_using_binary, @procedure) + new_collect_files_archive(archive, instructeur) + else + old_collect_files_archive(archive, instructeur) + end + end + + def new_collect_files_archive(archive, instructeur) + ## faux, ca ne doit prendre que certains groupe instructeur ? if archive.time_span_type == 'everything' dossiers = @procedure.dossiers.state_termine else @@ -26,7 +33,7 @@ class ProcedureArchiveService end attachments = create_list_of_attachments(dossiers) - zip(attachments) do |zip_file| + download_and_zip(attachments) do |zip_file| archive.file.attach( io: File.open(zip_file), filename: archive.filename(@procedure), @@ -38,6 +45,44 @@ class ProcedureArchiveService InstructeurMailer.send_archive(instructeur, @procedure, archive).deliver_later end + def old_collect_files_archive(archive, instructeur) + if archive.time_span_type == 'everything' + dossiers = @procedure.dossiers.state_termine + else + dossiers = @procedure.dossiers.processed_in_month(archive.month) + end + + files = create_list_of_attachments(dossiers) + + tmp_file = Tempfile.new(['tc', '.zip']) + + Zip::OutputStream.open(tmp_file) do |zipfile| + bug_reports = '' + files.each do |attachment, pj_filename| + zipfile.put_next_entry("#{zip_root_folder}/#{pj_filename}") + begin + zipfile.puts(attachment.download) + rescue + bug_reports += "Impossible de récupérer le fichier #{pj_filename}\n" + end + end + if !bug_reports.empty? + zipfile.put_next_entry("#{zip_root_folder}/LISEZMOI.txt") + zipfile.puts(bug_reports) + end + end + + archive.file.attach( + io: File.open(tmp_file), + filename: archive.filename(@procedure), + # we don't want to run virus scanner on this file + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + ) + tmp_file.delete + archive.make_available! + InstructeurMailer.send_archive(instructeur, @procedure, archive).deliver_later + end + def self.procedure_files_size(procedure) dossiers_files_size(procedure.dossiers) end @@ -50,7 +95,7 @@ class ProcedureArchiveService private - def zip(attachments, &block) + def download_and_zip(attachments, &block) Dir.mktmpdir(nil, ARCHIVE_CREATION_DIR) do |tmp_dir| archive_dir = File.join(tmp_dir, zip_root_folder) zip_path = File.join(ARCHIVE_CREATION_DIR, "#{zip_root_folder}.zip") diff --git a/spec/services/procedure_archive_service_spec.rb b/spec/services/procedure_archive_service_spec.rb index feb6e568b..58bd75d34 100644 --- a/spec/services/procedure_archive_service_spec.rb +++ b/spec/services/procedure_archive_service_spec.rb @@ -1,4 +1,3 @@ - describe ProcedureArchiveService do let(:procedure) { create(:procedure, :published) } let(:instructeur) { create(:instructeur) } @@ -29,7 +28,97 @@ describe ProcedureArchiveService do end end - describe '#collect_files_archive' do + describe '#old_collect_files_archive' do + before do + create_dossier_for_month(year, month) + create_dossier_for_month(2020, month) + end + + after { Timecop.return } + + context 'for a specific month' do + let(:archive) { create(:archive, time_span_type: 'monthly', status: 'pending', month: date_month) } + let(:year) { 2021 } + let(:mailer) { double('mailer', deliver_later: true) } + + it 'collect files' do + expect(InstructeurMailer).to receive(:send_archive).and_return(mailer) + + service.collect_files_archive(archive, instructeur) + + archive.file.open do |f| + files = ZipTricks::FileReader.read_zip_structure(io: f) + expect(files.size).to be 2 + expect(files.first.filename).to include("export") + expect(files.last.filename).to include("attestation") + end + expect(archive.file.attached?).to be_truthy + end + + context 'with a missing file' do + let(:pj) do + PiecesJustificativesService::FakeAttachment.new( + file: StringIO.new('coucou'), + filename: "export-dossier.pdf", + name: 'pdf_export_for_instructeur', + id: 1, + created_at: Time.zone.now + ) + end + + let(:bad_pj) do + PiecesJustificativesService::FakeAttachment.new( + file: nil, + filename: "cni.png", + name: 'cni.png', + id: 2, + created_at: Time.zone.now + ) + end + + let(:documents) { [pj, bad_pj] } + before do + allow(PiecesJustificativesService).to receive(:liste_documents).and_return(documents) + end + + it 'collect files without raising exception' do + expect { service.collect_files_archive(archive, instructeur) }.not_to raise_exception + end + + it 'add bug report to archive' do + service.collect_files_archive(archive, instructeur) + + archive.file.open do |f| + files = ZipTricks::FileReader.read_zip_structure(io: f) + expect(files.size).to be 4 + expect(files.last.filename).to eq("procedure-#{procedure.id}/LISEZMOI.txt") + expect(extract(f, files.last)).to match(/Impossible de .*cni.*png/) + end + end + end + end + + context 'for all months' do + let(:archive) { create(:archive, time_span_type: 'everything', status: 'pending') } + let(:mailer) { double('mailer', deliver_later: true) } + + it 'collect files' do + expect(InstructeurMailer).to receive(:send_archive).and_return(mailer) + + service.collect_files_archive(archive, instructeur) + + archive = Archive.last + archive.file.open do |f| + files = ZipTricks::FileReader.read_zip_structure(io: f) + expect(files.size).to be 4 + end + expect(archive.file.attached?).to be_truthy + end + end + end + + describe '#new_collect_files_archive' do + before { Flipper.enable_actor(:zip_using_binary, procedure) } let!(:dossier) { create_dossier_for_month(year, month) } let!(:dossier_2020) { create_dossier_for_month(2020, month) }