Merge pull request #7500 from mfo/US/admin_zip
ETQ admin, je souhaite pouvoir télécharger une archive.zip (mensuelle) des dossiers terminés
This commit is contained in:
commit
6cf397fda4
23 changed files with 270 additions and 135 deletions
|
@ -2,8 +2,6 @@
|
||||||
@import "constants";
|
@import "constants";
|
||||||
|
|
||||||
.breadcrumbs {
|
.breadcrumbs {
|
||||||
margin: $default-spacer 0 3 * $default-spacer;
|
|
||||||
|
|
||||||
li {
|
li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
38
app/controllers/administrateurs/archives_controller.rb
Normal file
38
app/controllers/administrateurs/archives_controller.rb
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
module Administrateurs
|
||||||
|
class ArchivesController < AdministrateurController
|
||||||
|
before_action :retrieve_procedure, only: [:index, :create]
|
||||||
|
helper_method :create_archive_url
|
||||||
|
|
||||||
|
def index
|
||||||
|
@average_dossier_weight = @procedure.average_dossier_weight
|
||||||
|
@count_dossiers_termines_by_month = Traitement.count_dossiers_termines_by_month(all_groupe_instructeurs)
|
||||||
|
@archives = Archive.for_groupe_instructeur(all_groupe_instructeurs).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
type = params[:type]
|
||||||
|
archive = Archive.find_or_create_archive(type, year_month, all_groupe_instructeurs)
|
||||||
|
if archive.pending?
|
||||||
|
ArchiveCreationJob.perform_later(@procedure, archive, current_administrateur)
|
||||||
|
flash[:notice] = "Votre demande a été prise en compte. Selon le nombre de dossiers, cela peut prendre de quelques minutes a plusieurs heures. Vous recevrez un courriel lorsque le fichier sera disponible."
|
||||||
|
else
|
||||||
|
flash[:notice] = "Cette archive a déjà été générée."
|
||||||
|
end
|
||||||
|
redirect_to admin_procedure_archives_path(@procedure)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def year_month
|
||||||
|
Date.strptime(params[:year_month], '%Y-%m') if params[:year_month].present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def all_groupe_instructeurs
|
||||||
|
@procedure.groupe_instructeurs
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_archive_url(procedure, date)
|
||||||
|
admin_procedure_archives_path(procedure, type: 'monthly', year_month: date.strftime('%Y-%m'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,55 +1,44 @@
|
||||||
module Instructeurs
|
module Instructeurs
|
||||||
class ArchivesController < InstructeurController
|
class ArchivesController < InstructeurController
|
||||||
before_action :ensure_procedure_enabled, only: [:create]
|
before_action :retrieve_procedure, only: [:index, :create]
|
||||||
|
helper_method :create_archive_url
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@procedure = procedure
|
@average_dossier_weight = @procedure.average_dossier_weight
|
||||||
@average_dossier_weight = procedure.average_dossier_weight
|
|
||||||
|
|
||||||
@count_dossiers_termines_by_month = Traitement.count_dossiers_termines_by_month(groupe_instructeurs)
|
@count_dossiers_termines_by_month = Traitement.count_dossiers_termines_by_month(groupe_instructeurs)
|
||||||
|
@archives = Archive.for_groupe_instructeur(groupe_instructeurs).to_a
|
||||||
@archives = Archive
|
|
||||||
.for_groupe_instructeur(groupe_instructeurs)
|
|
||||||
.to_a
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
type = params[:type]
|
type = params[:type]
|
||||||
month = Date.strptime(params[:month], '%Y-%m') if params[:month].present?
|
archive = Archive.find_or_create_archive(type, year_month, groupe_instructeurs)
|
||||||
|
|
||||||
archive = ProcedureArchiveService.new(procedure).create_pending_archive(current_instructeur, type, month)
|
|
||||||
if archive.pending?
|
if archive.pending?
|
||||||
ArchiveCreationJob.perform_later(procedure, archive, current_instructeur)
|
ArchiveCreationJob.perform_later(@procedure, archive, current_instructeur)
|
||||||
flash[:notice] = "Votre demande a été prise en compte. Selon le nombre de dossiers, cela peut prendre quelques minutes. Vous recevrez un courriel lorsque le fichier sera disponible."
|
flash[:notice] = "Votre demande a été prise en compte. Selon le nombre de dossiers, cela peut prendre de quelques minutes a plusieurs heures. Vous recevrez un courriel lorsque le fichier sera disponible."
|
||||||
else
|
else
|
||||||
flash[:notice] = "Cette archive a déjà été générée."
|
flash[:notice] = "Cette archive a déjà été générée."
|
||||||
end
|
end
|
||||||
redirect_to instructeur_archives_path(procedure)
|
redirect_to instructeur_archives_path(@procedure)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def ensure_procedure_enabled
|
def year_month
|
||||||
if procedure.brouillon?
|
Date.strptime(params[:year_month], '%Y-%m') if params[:year_month].present?
|
||||||
flash[:alert] = "L'accès aux archives n’est pas disponible pour cette démarche, merci d’en faire la demande à l'équipe de démarches simplifiees"
|
|
||||||
return redirect_to instructeur_procedure_path(procedure)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def procedure_id
|
def create_archive_url(procedure, date)
|
||||||
params[:procedure_id]
|
instructeur_archives_path(procedure, type: 'monthly', month: date.strftime('%Y-%m'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def groupe_instructeurs
|
def groupe_instructeurs
|
||||||
current_instructeur
|
current_instructeur
|
||||||
.groupe_instructeurs
|
.groupe_instructeurs
|
||||||
.where(procedure_id: procedure_id)
|
.where(procedure_id: params[:procedure_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def procedure
|
def retrieve_procedure
|
||||||
current_instructeur
|
@procedure = current_instructeur.procedures.find(params[:procedure_id])
|
||||||
.procedures
|
|
||||||
.find(procedure_id)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
class ArchiveCreationJob < ApplicationJob
|
class ArchiveCreationJob < ApplicationJob
|
||||||
queue_as :archives
|
queue_as :archives
|
||||||
|
|
||||||
def perform(procedure, archive, instructeur)
|
def perform(procedure, archive, administrateur_or_instructeur)
|
||||||
archive.restart! if archive.failed? # restart for AASM
|
archive.restart! if archive.failed? # restart for AASM
|
||||||
ProcedureArchiveService
|
ProcedureArchiveService
|
||||||
.new(procedure)
|
.new(procedure)
|
||||||
.make_and_upload_archive(archive, instructeur)
|
.make_and_upload_archive(archive)
|
||||||
archive.make_available!
|
archive.make_available!
|
||||||
InstructeurMailer.send_archive(instructeur, procedure, archive).deliver_later
|
UserMailer.send_archive(administrateur_or_instructeur, procedure, archive).deliver_later
|
||||||
rescue => e
|
rescue => e
|
||||||
archive.fail! # fail for observability
|
archive.fail! # fail for observability
|
||||||
raise e # re-raise for retryable behaviour
|
raise e # re-raise for retryable behaviour
|
||||||
|
|
|
@ -44,12 +44,4 @@ 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
|
||||||
|
|
|
@ -37,4 +37,22 @@ class UserMailer < ApplicationMailer
|
||||||
subject: subject,
|
subject: subject,
|
||||||
reply_to: CONTACT_EMAIL)
|
reply_to: CONTACT_EMAIL)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_archive(administrateur_or_instructeur, procedure, archive)
|
||||||
|
@archive = archive
|
||||||
|
@procedure = procedure
|
||||||
|
@archive_url = case administrateur_or_instructeur
|
||||||
|
when Instructeur then instructeur_archives_url(@procedure)
|
||||||
|
when Administrateur then admin_procedure_archives_url(@procedure)
|
||||||
|
else raise ArgumentError("send_archive expect either an Instructeur or an Administrateur")
|
||||||
|
end
|
||||||
|
@procedure_url = case administrateur_or_instructeur
|
||||||
|
when Instructeur then instructeur_procedure_url(@procedure.id)
|
||||||
|
when Administrateur then admin_procedure_url(@procedure)
|
||||||
|
else raise ArgumentError("send_archive expect either an Instructeur or an Administrateur")
|
||||||
|
end
|
||||||
|
subject = "Votre archive est disponible"
|
||||||
|
|
||||||
|
mail(to: administrateur_or_instructeur.email, subject: subject)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,15 +5,7 @@ class ProcedureArchiveService
|
||||||
@procedure = procedure
|
@procedure = procedure
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_pending_archive(instructeur, type, month = nil)
|
def make_and_upload_archive(archive)
|
||||||
groupe_instructeurs = instructeur
|
|
||||||
.groupe_instructeurs
|
|
||||||
.where(procedure: @procedure)
|
|
||||||
|
|
||||||
Archive.find_or_create_archive(type, month, groupe_instructeurs)
|
|
||||||
end
|
|
||||||
|
|
||||||
def make_and_upload_archive(archive, instructeur)
|
|
||||||
dossiers = Dossier.visible_by_administration
|
dossiers = Dossier.visible_by_administration
|
||||||
.where(groupe_instructeur: archive.groupe_instructeurs)
|
.where(groupe_instructeur: archive.groupe_instructeurs)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
.sub-header
|
.sub-header
|
||||||
.container.flex.justify-between.align-baseline.column
|
.container.flex.justify-between.align-baseline.column
|
||||||
%ul.breadcrumbs
|
%ul.breadcrumbs.mt-1.mb-3
|
||||||
- steps.each do |step|
|
- steps.each do |step|
|
||||||
%li= step
|
%li= step
|
||||||
- if defined?(preview) && preview
|
- if defined?(preview) && preview
|
||||||
.mb-2
|
.mb-2
|
||||||
= link_to "Prévisualiser le formulaire", apercu_admin_procedure_path(@procedure), target: "_blank", rel: "noopener", class: 'button'
|
= link_to "Prévisualiser le formulaire", apercu_admin_procedure_path(@procedure), target: "_blank", rel: "noopener", class: 'button'
|
||||||
= link_to "Continuer >", admin_procedure_path(@procedure), title: 'Vous pourrez revenir ici par la suite', class: 'button accepted'
|
= link_to "Continuer >", admin_procedure_path(@procedure), title: 'Vous pourrez revenir ici par la suite', class: 'button accepted'
|
||||||
|
|
||||||
- if defined?(metadatas)
|
- if defined?(metadatas)
|
||||||
%ul.admin-metadata
|
%ul.admin-metadata
|
||||||
- metadatas.each do |metadata|
|
- metadatas.each do |metadata|
|
||||||
|
|
12
app/views/administrateurs/archives/index.html.haml
Normal file
12
app/views/administrateurs/archives/index.html.haml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
= render partial: 'administrateurs/breadcrumbs',
|
||||||
|
locals: { steps: [link_to('Démarches', admin_procedures_path),
|
||||||
|
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
|
||||||
|
'Export et Archives'] }
|
||||||
|
|
||||||
|
|
||||||
|
.container
|
||||||
|
%h1.mb-2
|
||||||
|
Archives
|
||||||
|
|
||||||
|
= render partial: "shared/archives/notice"
|
||||||
|
= render partial: "shared/archives/table", locals: {count_dossiers_termines_by_month: @count_dossiers_termines_by_month, archives: @archives, average_dossier_weight: @average_dossier_weight, procedure: @procedure }
|
|
@ -4,6 +4,11 @@
|
||||||
metadatas: ["Créée le #{@procedure.created_at.strftime('%d/%m/%Y')} - n° #{@procedure.id}", "#{@procedure.close? ? "Close le #{@procedure.closed_at.strftime('%d/%m/%Y')}" : @procedure.locked? ? "Publiée - #{procedure_lien(@procedure)}" : "Brouillon"}"] }
|
metadatas: ["Créée le #{@procedure.created_at.strftime('%d/%m/%Y')} - n° #{@procedure.id}", "#{@procedure.close? ? "Close le #{@procedure.closed_at.strftime('%d/%m/%Y')}" : @procedure.locked? ? "Publiée - #{procedure_lien(@procedure)}" : "Brouillon"}"] }
|
||||||
|
|
||||||
.container.procedure-admin-container
|
.container.procedure-admin-container
|
||||||
|
- if !@procedure.brouillon?
|
||||||
|
= link_to admin_procedure_archives_path(@procedure), class: 'button', id: "archive-procedure" do
|
||||||
|
%span.icon.download
|
||||||
|
Télécharger
|
||||||
|
|
||||||
= link_to @procedure.active_revision.draft? ? commencer_dossier_vide_test_path(path: @procedure.path) : commencer_dossier_vide_path(path: @procedure.path), target: "_blank", rel: "noopener", class: 'button', id: "pdf-procedure" do
|
= link_to @procedure.active_revision.draft? ? commencer_dossier_vide_test_path(path: @procedure.path) : commencer_dossier_vide_path(path: @procedure.path), target: "_blank", rel: "noopener", class: 'button', id: "pdf-procedure" do
|
||||||
%span.icon.printer
|
%span.icon.printer
|
||||||
PDF
|
PDF
|
||||||
|
|
|
@ -7,54 +7,5 @@
|
||||||
.container
|
.container
|
||||||
%h1.mb-2 Archives
|
%h1.mb-2 Archives
|
||||||
|
|
||||||
.card.featured
|
= render partial: "shared/archives/notice"
|
||||||
.card-title Gestion de vos archives
|
= render partial: "shared/archives/table", locals: {count_dossiers_termines_by_month: @count_dossiers_termines_by_month, archives: @archives, average_dossier_weight: @average_dossier_weight, procedure: @procedure }
|
||||||
%p
|
|
||||||
L'archivage de votre démarche se fait mensuellement. Ainsi pour chaque mois depuis la publication de votre démarche vous pouvez faire une demande de création d'archive.
|
|
||||||
|
|
||||||
%p
|
|
||||||
Cette archive contient uniquement les dossiers terminés, les demandes déposées par l'usager et la liste des pièces justificatives transmises.
|
|
||||||
|
|
||||||
%p
|
|
||||||
Les archives dont le poid est estimé à plus de #{number_to_human_size(Archive::MAX_SIZE)} ne sont pas supportées.
|
|
||||||
Nous vous invitons à regarder
|
|
||||||
= link_to 'la documentation', ARCHIVAGE_DOC_URL
|
|
||||||
afin de voir les options à votre disposition pour mettre en place un système d’archive.
|
|
||||||
|
|
||||||
%table.table.hoverable.archive-table
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th
|
|
||||||
%th.text-right Nombre de dossiers terminés
|
|
||||||
%th.text-right Poids estimé
|
|
||||||
%th.center Télécharger
|
|
||||||
|
|
||||||
%tbody
|
|
||||||
- @count_dossiers_termines_by_month.each do |count_by_month|
|
|
||||||
- month = count_by_month["month"].to_date
|
|
||||||
- nb_dossiers_termines = count_by_month["count"]
|
|
||||||
- matching_archive = @archives.find { |archive| archive.time_span_type == 'monthly' && archive.month == month }
|
|
||||||
- weight = estimate_weight(matching_archive, nb_dossiers_termines, @average_dossier_weight)
|
|
||||||
|
|
||||||
%tr
|
|
||||||
%td
|
|
||||||
= I18n.l(month, format: "%B %Y").capitalize
|
|
||||||
%td.text-right
|
|
||||||
= nb_dossiers_termines
|
|
||||||
%td.text-right
|
|
||||||
= number_to_human_size(weight)
|
|
||||||
%td.center
|
|
||||||
- if matching_archive.present?
|
|
||||||
- if matching_archive.status == 'generated' && matching_archive.file.attached?
|
|
||||||
= link_to url_for(matching_archive.file), class: 'button primary' do
|
|
||||||
%span.icon.download-white
|
|
||||||
= t(:archive_ready_html, scope: [:instructeurs, :procedure], generated_period: time_ago_in_words(matching_archive.updated_at))
|
|
||||||
- else
|
|
||||||
%span.icon.retry
|
|
||||||
= t(:archive_pending_html, scope: [:instructeurs, :procedure], created_period: time_ago_in_words(matching_archive.created_at))
|
|
||||||
- elsif weight < Archive::MAX_SIZE
|
|
||||||
= link_to instructeur_archives_path(@procedure, type:'monthly', month: month.strftime('%Y-%m')), method: :post, class: "button" do
|
|
||||||
%span.icon.new-folder
|
|
||||||
Demander la création
|
|
||||||
- else
|
|
||||||
Archive trop volumineuse
|
|
||||||
|
|
15
app/views/shared/archives/_notice.html.haml
Normal file
15
app/views/shared/archives/_notice.html.haml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
.card.featured
|
||||||
|
.card-title Gestion de vos archives
|
||||||
|
%p
|
||||||
|
L'archivage de votre démarche se fait mensuellement. Ainsi pour chaque mois depuis la publication de votre démarche vous pouvez faire une demande de création d'archive.
|
||||||
|
|
||||||
|
%p
|
||||||
|
Cette archive contient uniquement les dossiers terminés, les demandes déposées par l'usager et la liste des pièces justificatives transmises.
|
||||||
|
|
||||||
|
%p
|
||||||
|
Les archives dont le poid est estimé à plus de #{number_to_human_size(Archive::MAX_SIZE)} ne sont pas supportées.
|
||||||
|
Nous vous invitons à regarder
|
||||||
|
= link_to 'la documentation', ARCHIVAGE_DOC_URL
|
||||||
|
afin de voir les options à votre disposition pour mettre en place un système d’archive.
|
||||||
|
|
||||||
|
|
37
app/views/shared/archives/_table.html.haml
Normal file
37
app/views/shared/archives/_table.html.haml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
%table.table.hoverable.archive-table
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th
|
||||||
|
%th.text-right Nombre de dossiers terminés
|
||||||
|
%th.text-right Poids estimé
|
||||||
|
%th.center Télécharger
|
||||||
|
|
||||||
|
%tbody
|
||||||
|
- count_dossiers_termines_by_month.each do |count_by_month|
|
||||||
|
- month = count_by_month["month"].to_date
|
||||||
|
- nb_dossiers_termines = count_by_month["count"]
|
||||||
|
- matching_archive = archives.find { |archive| archive.time_span_type == 'monthly' && archive.month == month }
|
||||||
|
- weight = estimate_weight(matching_archive, nb_dossiers_termines, average_dossier_weight)
|
||||||
|
|
||||||
|
%tr
|
||||||
|
%td
|
||||||
|
= I18n.l(month, format: "%B %Y").capitalize
|
||||||
|
%td.text-right
|
||||||
|
= nb_dossiers_termines
|
||||||
|
%td.text-right
|
||||||
|
= number_to_human_size(weight)
|
||||||
|
%td.center
|
||||||
|
- if matching_archive.present?
|
||||||
|
- if matching_archive.status == 'generated' && matching_archive.file.attached?
|
||||||
|
= link_to url_for(matching_archive.file), class: 'button primary' do
|
||||||
|
%span.icon.download-white
|
||||||
|
= t(:archive_ready_html, scope: [:instructeurs, :procedure], generated_period: time_ago_in_words(matching_archive.updated_at))
|
||||||
|
- else
|
||||||
|
%span.icon.retry
|
||||||
|
= t(:archive_pending_html, scope: [:instructeurs, :procedure], created_period: time_ago_in_words(matching_archive.created_at))
|
||||||
|
- elsif weight < Archive::MAX_SIZE
|
||||||
|
= link_to create_archive_url(procedure, month), method: :post, class: "button" do
|
||||||
|
%span.icon.new-folder
|
||||||
|
Demander la création
|
||||||
|
- else
|
||||||
|
Archive trop volumineuse
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
%p
|
%p
|
||||||
Votre archive pour la démarche
|
Votre archive pour la démarche
|
||||||
= link_to("#{@procedure.id} − #{@procedure.libelle}", instructeur_procedure_url(@procedure.id))
|
= link_to("#{@procedure.id} − #{@procedure.libelle}", @procedure_url)
|
||||||
est disponible.
|
est disponible.
|
||||||
Vous pouvez la télécharger dans votre espace de gestion des archives.
|
Vous pouvez la télécharger dans votre espace de gestion des archives.
|
||||||
|
|
||||||
%p
|
%p
|
||||||
= round_button('Consulter mes archives', instructeur_archives_url(@procedure), :primary)
|
= round_button('Consulter mes archives', @archive_url, :primary)
|
||||||
|
|
||||||
%p
|
%p
|
||||||
Ce fichier est
|
Ce fichier est
|
|
@ -397,7 +397,7 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :archives, only: [:index, :create, :show], controller: 'archives'
|
resources :archives, only: [:index, :create]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -408,6 +408,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
scope module: 'administrateurs', path: 'admin', as: 'admin' do
|
scope module: 'administrateurs', path: 'admin', as: 'admin' do
|
||||||
resources :procedures do
|
resources :procedures do
|
||||||
|
resources :archives, only: [:index, :create]
|
||||||
collection do
|
collection do
|
||||||
get 'new_from_existing'
|
get 'new_from_existing'
|
||||||
end
|
end
|
||||||
|
|
43
spec/controllers/administrateurs/archives_controller_spec.rb
Normal file
43
spec/controllers/administrateurs/archives_controller_spec.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
describe Administrateurs::ArchivesController, type: :controller do
|
||||||
|
let(:admin) { create(:administrateur) }
|
||||||
|
let(:procedure) { create :procedure, administrateur: admin, groupe_instructeurs: [groupe_instructeur1, groupe_instructeur2] }
|
||||||
|
let(:groupe_instructeur1) { create(:groupe_instructeur) }
|
||||||
|
let(:groupe_instructeur2) { create(:groupe_instructeur) }
|
||||||
|
|
||||||
|
describe 'GET #index' do
|
||||||
|
subject { get :index, params: { procedure_id: procedure.id } }
|
||||||
|
|
||||||
|
context 'when logged out' do
|
||||||
|
it { is_expected.to have_http_status(302) }
|
||||||
|
end
|
||||||
|
context 'when logged in' do
|
||||||
|
before do
|
||||||
|
sign_in(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to have_http_status(200) }
|
||||||
|
|
||||||
|
it 'use all procedure.groupe_instructeurs' do
|
||||||
|
expect(Archive).to receive(:for_groupe_instructeur).with([groupe_instructeur1, groupe_instructeur2]).and_return([])
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
describe 'GET #create' do
|
||||||
|
subject { post :create, params: { procedure_id: procedure.id, month: '22-06', type: 'monthly' } }
|
||||||
|
|
||||||
|
context 'when logged out' do
|
||||||
|
it { is_expected.to have_http_status(302) }
|
||||||
|
end
|
||||||
|
context 'when logged in' do
|
||||||
|
before do
|
||||||
|
sign_in(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to redirect_to(admin_procedure_archives_path(procedure)) }
|
||||||
|
it 'enqueue the creation job' do
|
||||||
|
expect { subject }.to have_enqueued_job(ArchiveCreationJob).with(procedure, an_instance_of(Archive), admin)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -31,14 +31,12 @@ describe Instructeurs::ArchivesController, type: :controller do
|
||||||
describe '#create' do
|
describe '#create' do
|
||||||
let(:month) { '21-03' }
|
let(:month) { '21-03' }
|
||||||
let(:date_month) { Date.strptime(month, "%Y-%m") }
|
let(:date_month) { Date.strptime(month, "%Y-%m") }
|
||||||
let(:archive) { create(:archive) }
|
|
||||||
let(:subject) do
|
let(:subject) do
|
||||||
post :create, params: { procedure_id: procedure1.id, type: 'monthly', month: month }
|
post :create, params: { procedure_id: procedure1.id, type: 'monthly', month: month }
|
||||||
end
|
end
|
||||||
|
|
||||||
it "performs archive creation job" do
|
it "performs archive creation job" do
|
||||||
allow_any_instance_of(ProcedureArchiveService).to receive(:create_pending_archive).and_return(archive)
|
expect { subject }.to have_enqueued_job(ArchiveCreationJob).with(procedure1, an_instance_of(Archive), instructeur)
|
||||||
expect { subject }.to have_enqueued_job(ArchiveCreationJob).with(procedure1, archive, instructeur)
|
|
||||||
expect(flash.notice).to include("Votre demande a été prise en compte")
|
expect(flash.notice).to include("Votre demande a été prise en compte")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ describe ArchiveCreationJob, type: :job do
|
||||||
context 'when it fails' do
|
context 'when it fails' do
|
||||||
let(:status) { :pending }
|
let(:status) { :pending }
|
||||||
let(:mailer) { double('mailer', deliver_later: true) }
|
let(:mailer) { double('mailer', deliver_later: true) }
|
||||||
before { expect(InstructeurMailer).not_to receive(:send_archive) }
|
before { expect(UserMailer).not_to receive(:send_archive) }
|
||||||
|
|
||||||
it 'does not send email and forward error for retry' do
|
it 'does not send email and forward error for retry' do
|
||||||
allow(DownloadableFileService).to receive(:download_and_zip).and_raise(StandardError, "kaboom")
|
allow(DownloadableFileService).to receive(:download_and_zip).and_raise(StandardError, "kaboom")
|
||||||
|
@ -21,7 +21,7 @@ describe ArchiveCreationJob, type: :job do
|
||||||
let(:mailer) { double('mailer', deliver_later: true) }
|
let(:mailer) { double('mailer', deliver_later: true) }
|
||||||
before do
|
before do
|
||||||
allow(DownloadableFileService).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)
|
expect(UserMailer).to receive(:send_archive).and_return(mailer)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when archive failed previously' do
|
context 'when archive failed previously' do
|
||||||
|
|
|
@ -16,6 +16,10 @@ class UserMailerPreview < ActionMailer::Preview
|
||||||
UserMailer.france_connect_merge_confirmation('new.exemple.fr', '123456', 15.minutes.from_now)
|
UserMailer.france_connect_merge_confirmation('new.exemple.fr', '123456', 15.minutes.from_now)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_archive
|
||||||
|
UserMailer.send_archive(Instructeur.first, Procedure.first, Archive.first)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def user
|
def user
|
||||||
|
|
|
@ -35,4 +35,24 @@ RSpec.describe UserMailer, type: :mailer do
|
||||||
it { expect(subject.to).to eq([email]) }
|
it { expect(subject.to).to eq([email]) }
|
||||||
it { expect(subject.body).to include(france_connect_particulier_mail_merge_with_existing_account_url(merge_token: code)) }
|
it { expect(subject.body).to include(france_connect_particulier_mail_merge_with_existing_account_url(merge_token: code)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.send_archive' do
|
||||||
|
let(:procedure) { create(:procedure) }
|
||||||
|
let(:archive) { create(:archive) }
|
||||||
|
subject { described_class.send_archive(role, procedure, archive) }
|
||||||
|
|
||||||
|
context 'instructeur' do
|
||||||
|
let(:role) { create(:instructeur) }
|
||||||
|
it { expect(subject.to).to eq([role.user.email]) }
|
||||||
|
it { expect(subject.body).to have_link('Consulter mes archives', href: instructeur_archives_url(procedure)) }
|
||||||
|
it { expect(subject.body).to have_link("#{procedure.id} − #{procedure.libelle}", href: instructeur_procedure_url(procedure)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'instructeur' do
|
||||||
|
let(:role) { create(:administrateur) }
|
||||||
|
it { expect(subject.to).to eq([role.user.email]) }
|
||||||
|
it { expect(subject.body).to have_link('Consulter mes archives', href: admin_procedure_archives_url(procedure)) }
|
||||||
|
it { expect(subject.body).to have_link("#{procedure.id} − #{procedure.libelle}", href: admin_procedure_url(procedure)) }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,28 +11,6 @@ describe ProcedureArchiveService do
|
||||||
procedure.defaut_groupe_instructeur.add(instructeur)
|
procedure.defaut_groupe_instructeur.add(instructeur)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#create_pending_archive' do
|
|
||||||
context 'for a specific month' do
|
|
||||||
it 'creates a pending archive' do
|
|
||||||
archive = service.create_pending_archive(instructeur, 'monthly', date_month)
|
|
||||||
|
|
||||||
expect(archive.time_span_type).to eq 'monthly'
|
|
||||||
expect(archive.month).to eq date_month
|
|
||||||
expect(archive.pending?).to be_truthy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'for all months' do
|
|
||||||
it 'creates a pending archive' do
|
|
||||||
archive = service.create_pending_archive(instructeur, 'everything')
|
|
||||||
|
|
||||||
expect(archive.time_span_type).to eq 'everything'
|
|
||||||
expect(archive.month).to eq nil
|
|
||||||
expect(archive.pending?).to be_truthy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#make_and_upload_archive' do
|
describe '#make_and_upload_archive' do
|
||||||
let!(:dossier) { create_dossier_for_month(year, month) }
|
let!(:dossier) { create_dossier_for_month(year, month) }
|
||||||
let!(:dossier_2020) { create_dossier_for_month(2020, month) }
|
let!(:dossier_2020) { create_dossier_for_month(2020, month) }
|
||||||
|
@ -47,7 +25,7 @@ describe ProcedureArchiveService do
|
||||||
allow_any_instance_of(ActiveStorage::Attachment).to receive(:url).and_return("https://opengraph.githubassets.com/d0e7862b24d8026a3c03516d865b28151eb3859029c6c6c2e86605891fbdcd7a/socketry/async-io")
|
allow_any_instance_of(ActiveStorage::Attachment).to receive(:url).and_return("https://opengraph.githubassets.com/d0e7862b24d8026a3c03516d865b28151eb3859029c6c6c2e86605891fbdcd7a/socketry/async-io")
|
||||||
|
|
||||||
VCR.use_cassette('archive/new_file_to_get_200') do
|
VCR.use_cassette('archive/new_file_to_get_200') do
|
||||||
service.make_and_upload_archive(archive, instructeur)
|
service.make_and_upload_archive(archive)
|
||||||
end
|
end
|
||||||
|
|
||||||
archive.file.open do |f|
|
archive.file.open do |f|
|
||||||
|
@ -69,7 +47,7 @@ describe ProcedureArchiveService do
|
||||||
allow_any_instance_of(ActiveStorage::Attached::One).to receive(:url).and_return("https://www.demarches-simplifiees.fr/error_1")
|
allow_any_instance_of(ActiveStorage::Attached::One).to receive(:url).and_return("https://www.demarches-simplifiees.fr/error_1")
|
||||||
|
|
||||||
VCR.use_cassette('archive/new_file_to_get_400.html') do
|
VCR.use_cassette('archive/new_file_to_get_400.html') do
|
||||||
service.make_and_upload_archive(archive, instructeur)
|
service.make_and_upload_archive(archive)
|
||||||
end
|
end
|
||||||
archive.file.open do |f|
|
archive.file.open do |f|
|
||||||
files = ZipTricks::FileReader.read_zip_structure(io: f)
|
files = ZipTricks::FileReader.read_zip_structure(io: f)
|
||||||
|
@ -112,11 +90,11 @@ describe ProcedureArchiveService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'collect files without raising exception' do
|
it 'collect files without raising exception' do
|
||||||
expect { service.make_and_upload_archive(archive, instructeur) }.not_to raise_exception
|
expect { service.make_and_upload_archive(archive) }.not_to raise_exception
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'add bug report to archive' do
|
it 'add bug report to archive' do
|
||||||
service.make_and_upload_archive(archive, instructeur)
|
service.make_and_upload_archive(archive)
|
||||||
|
|
||||||
archive.file.open do |f|
|
archive.file.open do |f|
|
||||||
zip_entries = ZipTricks::FileReader.read_zip_structure(io: f)
|
zip_entries = ZipTricks::FileReader.read_zip_structure(io: f)
|
||||||
|
@ -148,7 +126,7 @@ describe ProcedureArchiveService do
|
||||||
allow_any_instance_of(ActiveStorage::Attachment).to receive(:url).and_return("https://opengraph.githubassets.com/5e61989aecb78e369c93674f877d7bf4ecde378850114a9563cdf8b6a2472536/typhoeus/typhoeus/issues/110")
|
allow_any_instance_of(ActiveStorage::Attachment).to receive(:url).and_return("https://opengraph.githubassets.com/5e61989aecb78e369c93674f877d7bf4ecde378850114a9563cdf8b6a2472536/typhoeus/typhoeus/issues/110")
|
||||||
|
|
||||||
VCR.use_cassette('archive/old_file_to_get_200') do
|
VCR.use_cassette('archive/old_file_to_get_200') do
|
||||||
service.make_and_upload_archive(archive, instructeur)
|
service.make_and_upload_archive(archive)
|
||||||
end
|
end
|
||||||
|
|
||||||
archive = Archive.last
|
archive = Archive.last
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
require 'system/administrateurs/procedure_spec_helper'
|
||||||
|
|
||||||
|
describe 'Creating a new procedure', js: true do
|
||||||
|
include ProcedureSpecHelper
|
||||||
|
|
||||||
|
let(:administrateur) { create(:administrateur) }
|
||||||
|
let(:procedure) do
|
||||||
|
create(:procedure, :with_service, :with_instructeur,
|
||||||
|
aasm_state: :publiee,
|
||||||
|
administrateurs: [administrateur],
|
||||||
|
libelle: 'libellé de la procédure',
|
||||||
|
path: 'libelle-de-la-procedure')
|
||||||
|
end
|
||||||
|
let!(:dossiers) do
|
||||||
|
create(:dossier, :accepte, procedure: procedure)
|
||||||
|
end
|
||||||
|
|
||||||
|
before { login_as administrateur.user, scope: :user }
|
||||||
|
|
||||||
|
scenario "download archive" do
|
||||||
|
visit admin_procedure_path(id: procedure.id)
|
||||||
|
|
||||||
|
# check button
|
||||||
|
expect(page).to have_selector('#archive-procedure')
|
||||||
|
click_on "Télécharger"
|
||||||
|
|
||||||
|
# check page loading
|
||||||
|
expect(page).to have_content("Archives")
|
||||||
|
|
||||||
|
# check archive
|
||||||
|
expect {
|
||||||
|
page.first(".archive-table .button").click
|
||||||
|
}.to have_enqueued_job(ArchiveCreationJob).with(procedure, an_instance_of(Archive), administrateur)
|
||||||
|
expect(page).to have_content("Votre demande a été prise en compte. Selon le nombre de dossiers, cela peut prendre de quelques minutes a plusieurs heures. Vous recevrez un courriel lorsque le fichier sera disponible.")
|
||||||
|
end
|
||||||
|
end
|
|
@ -24,6 +24,10 @@ describe 'administrateurs/procedures/show.html.haml', type: :view do
|
||||||
describe 'procedure path is not customized' do
|
describe 'procedure path is not customized' do
|
||||||
it { expect(rendered).to have_content('Brouillon') }
|
it { expect(rendered).to have_content('Brouillon') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'archive button' do
|
||||||
|
it { expect(rendered).not_to have_css('#archive-procedure') }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,6 +42,9 @@ describe 'administrateurs/procedures/show.html.haml', type: :view do
|
||||||
it { expect(rendered).not_to have_css('#publish-procedure-link') }
|
it { expect(rendered).not_to have_css('#publish-procedure-link') }
|
||||||
it { expect(rendered).to have_css('#close-procedure-link') }
|
it { expect(rendered).to have_css('#close-procedure-link') }
|
||||||
end
|
end
|
||||||
|
describe 'archive button' do
|
||||||
|
it { expect(rendered).to have_css('#archive-procedure') }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'procedure is closed' do
|
describe 'procedure is closed' do
|
||||||
|
|
Loading…
Reference in a new issue