add service to create procedure archive
This commit is contained in:
parent
fba0d78153
commit
07cc4fa97f
6 changed files with 182 additions and 1 deletions
|
@ -1,5 +1,7 @@
|
||||||
# Preview all emails at http://localhost:3000/rails/mailers/instructeur_mailer
|
# Preview all emails at http://localhost:3000/rails/mailers/instructeur_mailer
|
||||||
class InstructeurMailer < ApplicationMailer
|
class InstructeurMailer < ApplicationMailer
|
||||||
|
helper MailerHelper
|
||||||
|
|
||||||
layout 'mailers/layout'
|
layout 'mailers/layout'
|
||||||
|
|
||||||
def user_to_instructeur(email)
|
def user_to_instructeur(email)
|
||||||
|
@ -42,4 +44,12 @@ class InstructeurMailer < ApplicationMailer
|
||||||
|
|
||||||
mail(to: instructeur.email, subject: subject)
|
mail(to: instructeur.email, subject: subject)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_archive(instructeur, procedure, archive)
|
||||||
|
@archive = archive
|
||||||
|
@procedure = procedure
|
||||||
|
subject = "Votre archive est disponible"
|
||||||
|
|
||||||
|
mail(to: instructeur.email, subject: subject)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,4 +48,12 @@ class Archive < ApplicationRecord
|
||||||
def available?
|
def available?
|
||||||
status == 'generated' && file.attached?
|
status == 'generated' && file.attached?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filename(procedure)
|
||||||
|
if content_type == 'everything'
|
||||||
|
"procedure-#{procedure.id}.zip"
|
||||||
|
else
|
||||||
|
"procedure-#{procedure.id}-mois-#{I18n.l(month, format: '%Y-%m')}.zip"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -172,7 +172,12 @@ class Dossier < ApplicationRecord
|
||||||
scope :en_construction, -> { not_archived.state_en_construction }
|
scope :en_construction, -> { not_archived.state_en_construction }
|
||||||
scope :en_instruction, -> { not_archived.state_en_instruction }
|
scope :en_instruction, -> { not_archived.state_en_instruction }
|
||||||
scope :termine, -> { not_archived.state_termine }
|
scope :termine, -> { not_archived.state_termine }
|
||||||
scope :downloadable_sorted, -> {
|
scope :processed_in_month, -> (month) do
|
||||||
|
state_termine
|
||||||
|
.joins(:traitements)
|
||||||
|
.where(traitements: { processed_at: month.beginning_of_month..month.end_of_month })
|
||||||
|
end
|
||||||
|
scope :downloadable_sorted, -> {
|
||||||
state_not_brouillon
|
state_not_brouillon
|
||||||
.includes(
|
.includes(
|
||||||
:user,
|
:user,
|
||||||
|
|
74
app/services/procedure_archive_service.rb
Normal file
74
app/services/procedure_archive_service.rb
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
require 'tempfile'
|
||||||
|
|
||||||
|
class ProcedureArchiveService
|
||||||
|
def initialize(procedure)
|
||||||
|
@procedure = procedure
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_archive(instructeur, type, month = nil)
|
||||||
|
groupe_instructeurs = instructeur
|
||||||
|
.groupe_instructeurs
|
||||||
|
.where(procedure: @procedure)
|
||||||
|
|
||||||
|
if type == 'everything'
|
||||||
|
dossiers = @procedure.dossiers.state_termine
|
||||||
|
else
|
||||||
|
dossiers = @procedure.dossiers.processed_in_month(month)
|
||||||
|
end
|
||||||
|
|
||||||
|
files = create_list_of_attachments(dossiers)
|
||||||
|
|
||||||
|
archive = Archive.create!(
|
||||||
|
content_type: type,
|
||||||
|
month: month,
|
||||||
|
groupe_instructeurs: groupe_instructeurs
|
||||||
|
)
|
||||||
|
|
||||||
|
tmp_file = Tempfile.new(['tc', '.zip'])
|
||||||
|
|
||||||
|
Zip::OutputStream.open(tmp_file) do |zipfile|
|
||||||
|
files.each do |attachment, pj_filename|
|
||||||
|
zipfile.put_next_entry(pj_filename)
|
||||||
|
zipfile.puts(attachment.download)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
archive.file.attach(io: File.open(tmp_file), filename: archive.filename(@procedure))
|
||||||
|
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
|
||||||
|
|
||||||
|
def self.dossiers_files_size(dossiers)
|
||||||
|
dossiers.map do |dossier|
|
||||||
|
liste_pieces_justificatives_for_archive(dossier).sum(&:byte_size)
|
||||||
|
end.sum
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_list_of_attachments(dossiers)
|
||||||
|
dossiers.flat_map do |dossier|
|
||||||
|
ActiveStorage::DownloadableFile.create_list_from_dossier(dossier)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.attachments_from_champs_piece_justificative(champs)
|
||||||
|
champs
|
||||||
|
.filter { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:piece_justificative) }
|
||||||
|
.filter { |pj| pj.piece_justificative_file.attached? }
|
||||||
|
.map(&:piece_justificative_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.liste_pieces_justificatives_for_archive(dossier)
|
||||||
|
champs_blocs_repetables = dossier.champs
|
||||||
|
.filter { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:repetition) }
|
||||||
|
.flat_map(&:champs)
|
||||||
|
|
||||||
|
attachments_from_champs_piece_justificative(champs_blocs_repetables + dossier.champs)
|
||||||
|
end
|
||||||
|
end
|
21
app/views/instructeur_mailer/send_archive.html.haml
Normal file
21
app/views/instructeur_mailer/send_archive.html.haml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
- content_for(:title, 'Votre archive est disponible')
|
||||||
|
|
||||||
|
%p
|
||||||
|
Bonjour,
|
||||||
|
|
||||||
|
%p
|
||||||
|
Votre archive pour la démarche
|
||||||
|
= link_to("#{@procedure.id} − #{@procedure.libelle}", instructeur_procedure_url(@procedure.id))
|
||||||
|
est disponible.
|
||||||
|
Vous pouvez la télécharger dans votre espace de gestion des archives.
|
||||||
|
|
||||||
|
%p
|
||||||
|
= round_button('Consulter mes archives', instructeur_archives_url(@procedure), :primary)
|
||||||
|
|
||||||
|
%p
|
||||||
|
Ce fichier est
|
||||||
|
%b valide une semaine
|
||||||
|
et peut-être téléchargé
|
||||||
|
%b plusieurs fois.
|
||||||
|
|
||||||
|
= render partial: "layouts/mailers/signature"
|
63
spec/services/procedure_archive_service_spec.rb
Normal file
63
spec/services/procedure_archive_service_spec.rb
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
describe ProcedureArchiveService do
|
||||||
|
describe '#create_archive' do
|
||||||
|
let(:procedure) { create(:procedure, :published) }
|
||||||
|
let(:instructeur) { create(:instructeur) }
|
||||||
|
let(:service) { ProcedureArchiveService.new(procedure) }
|
||||||
|
let(:year) { 2020 }
|
||||||
|
let(:month) { 3 }
|
||||||
|
let(:date_month) { Date.strptime("#{year}-#{month}", "%Y-%m") }
|
||||||
|
|
||||||
|
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(:year) { 2021 }
|
||||||
|
let(:mailer) { double('mailer', deliver_later: true) }
|
||||||
|
|
||||||
|
it 'creates a monthly archive' do
|
||||||
|
expect(InstructeurMailer).to receive(:send_archive).and_return(mailer)
|
||||||
|
|
||||||
|
service.create_archive(instructeur, 'monthly', date_month)
|
||||||
|
|
||||||
|
archive = Archive.last
|
||||||
|
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.content_type).to eq 'monthly'
|
||||||
|
expect(archive.file.attached?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for all months' do
|
||||||
|
let(:mailer) { double('mailer', deliver_later: true) }
|
||||||
|
|
||||||
|
it 'creates a everything archive' do
|
||||||
|
expect(InstructeurMailer).to receive(:send_archive).and_return(mailer)
|
||||||
|
|
||||||
|
service.create_archive(instructeur, 'everything')
|
||||||
|
|
||||||
|
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.content_type).to eq 'everything'
|
||||||
|
expect(archive.file.attached?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_dossier_for_month(year, month)
|
||||||
|
Timecop.freeze(Time.zone.local(year, month, 5))
|
||||||
|
create(:dossier, :accepte, :with_attestation, procedure: procedure)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue