diff --git a/app/assets/stylesheets/buttons.scss b/app/assets/stylesheets/buttons.scss
index 4e399e8ef..c9e3edb6d 100644
--- a/app/assets/stylesheets/buttons.scss
+++ b/app/assets/stylesheets/buttons.scss
@@ -130,6 +130,11 @@
}
}
+.icon-size {
+ width: 18px;
+ height: 18px;
+}
+
.state-button {
display: inline-block;
}
diff --git a/app/controllers/instructeurs/archives_controller.rb b/app/controllers/instructeurs/archives_controller.rb
deleted file mode 100644
index 2917520be..000000000
--- a/app/controllers/instructeurs/archives_controller.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-module Instructeurs
- class ArchivesController < InstructeurController
- before_action :ensure_procedure_enabled
-
- def index
- @procedure = procedure
-
- @archivable_months = archivable_months
- @dossiers_termines = @procedure.dossiers.state_termine
- @poids_total = ProcedureArchiveService.procedure_files_size(@procedure)
- groupe_instructeur = current_instructeur.groupe_instructeurs.where(procedure: @procedure.id).first
- @archives = Archive.for_groupe_instructeur(groupe_instructeur)
- end
-
- def create
- type = params[:type]
- month = Date.strptime(params[:month], '%Y-%m') if params[:month].present?
-
- archive = ProcedureArchiveService.new(procedure).create_pending_archive(current_instructeur, type, month)
- if archive.pending?
- 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."
- else
- flash[:notice] = "Cette archive a déjà été générée."
- end
- redirect_to instructeur_archives_path(procedure)
- end
-
- private
-
- def ensure_procedure_enabled
- if !procedure.feature_enabled?(:archive_zip_globale) || procedure.brouillon?
- 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
-
- def archivable_months
- start_date = procedure.published_at.to_date
- end_date = Time.zone.now.to_date
-
- (start_date...end_date)
- .map(&:beginning_of_month)
- .uniq
- .reverse
- end
-
- def procedure
- current_instructeur
- .procedures
- .for_download
- .find(params[:procedure_id])
- end
- end
-end
diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb
index e6fb16d21..37b7e1d4c 100644
--- a/app/controllers/instructeurs/dossiers_controller.rb
+++ b/app/controllers/instructeurs/dossiers_controller.rb
@@ -213,6 +213,7 @@ module Instructeurs
def telecharger_pjs
return head(:forbidden) if !dossier.attachments_downloadable?
+ generate_pdf_for_instructeur_export
files = ActiveStorage::DownloadableFile.create_list_from_dossier(dossier)
zipline(files, "dossier-#{dossier.id}.zip")
@@ -238,6 +239,12 @@ module Instructeurs
.find(params[:dossier_id])
end
+ def generate_pdf_for_instructeur_export
+ @include_infos_administration = true
+ pdf = render_to_string(template: 'dossiers/show', formats: [:pdf])
+ dossier.pdf_export_for_instructeur.attach(io: StringIO.open(pdf), filename: "export-#{dossier.id}.pdf", content_type: 'application/pdf')
+ end
+
def commentaire_params
params.require(:commentaire).permit(:body, :piece_jointe)
end
diff --git a/app/helpers/archive_helper.rb b/app/helpers/archive_helper.rb
deleted file mode 100644
index b349b8793..000000000
--- a/app/helpers/archive_helper.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module ArchiveHelper
- def can_generate_archive?(dossiers_termines, poids_total)
- dossiers_termines.count < 100 && poids_total < 1.gigabyte
- end
-end
diff --git a/app/javascript/components/ComboMultipleDropdownList.jsx b/app/javascript/components/ComboMultipleDropdownList.jsx
index a10c74215..1e25987ec 100644
--- a/app/javascript/components/ComboMultipleDropdownList.jsx
+++ b/app/javascript/components/ComboMultipleDropdownList.jsx
@@ -241,7 +241,7 @@ function ComboboxToken({ value, ...props }) {
onRemove(value);
}}
>
-
+
Désélectionner
{value}
diff --git a/app/javascript/components/TypesDeChampEditor/components/MoveButton.jsx b/app/javascript/components/TypesDeChampEditor/components/MoveButton.jsx
index 5aa94f983..c8ec442f9 100644
--- a/app/javascript/components/TypesDeChampEditor/components/MoveButton.jsx
+++ b/app/javascript/components/TypesDeChampEditor/components/MoveButton.jsx
@@ -1,16 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { ArrowDownIcon, ArrowUpIcon } from '@heroicons/react/solid';
function MoveButton({ isEnabled, icon, title, onClick }) {
return (
);
}
diff --git a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.jsx b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.jsx
index 6dca0c980..00ce93494 100644
--- a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.jsx
+++ b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { sortableElement, sortableHandle } from 'react-sortable-hoc';
import { useInView } from 'react-intersection-observer';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { TrashIcon } from '@heroicons/react/outline';
import DescriptionInput from './DescriptionInput';
import LibelleInput from './LibelleInput';
@@ -77,7 +77,8 @@ const TypeDeChamp = sortableElement(
});
}}
>
-
+
+ Supprimer
diff --git a/app/javascript/components/TypesDeChampEditor/components/TypeDeChampRepetitionOptions.jsx b/app/javascript/components/TypesDeChampEditor/components/TypeDeChampRepetitionOptions.jsx
index 888d7d3ba..1b8497ff3 100644
--- a/app/javascript/components/TypesDeChampEditor/components/TypeDeChampRepetitionOptions.jsx
+++ b/app/javascript/components/TypesDeChampEditor/components/TypeDeChampRepetitionOptions.jsx
@@ -1,6 +1,6 @@
import React, { useReducer } from 'react';
import PropTypes from 'prop-types';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { PlusIcon } from '@heroicons/react/outline';
import { SortableContainer, addChampLabel } from '../utils';
import TypeDeChamp from './TypeDeChamp';
@@ -45,7 +45,7 @@ function TypeDeChampRepetitionOptions({
})
}
>
-
+
{addChampLabel(state.isAnnotation)}
diff --git a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamps.jsx b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamps.jsx
index fa909b5b5..3b7c172cc 100644
--- a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamps.jsx
+++ b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamps.jsx
@@ -1,6 +1,6 @@
import React, { useReducer } from 'react';
import PropTypes from 'prop-types';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { PlusIcon, ArrowCircleDownIcon } from '@heroicons/react/outline';
import { SortableContainer, addChampLabel } from '../utils';
import TypeDeChamp from './TypeDeChamp';
@@ -38,7 +38,7 @@ function TypeDeChamps({ state: rootState, typeDeChamps }) {
{state.typeDeChamps.length === 0 && (
-
+
Cliquez sur le bouton «
{addChampLabel(state.isAnnotation)} » pour créer votre premier
champ.
@@ -56,7 +56,7 @@ function TypeDeChamps({ state: rootState, typeDeChamps }) {
})
}
>
-
+
{addChampLabel(state.isAnnotation)}
diff --git a/app/javascript/components/TypesDeChampEditor/index.jsx b/app/javascript/components/TypesDeChampEditor/index.jsx
index 5e0068f40..d2ec2d494 100644
--- a/app/javascript/components/TypesDeChampEditor/index.jsx
+++ b/app/javascript/components/TypesDeChampEditor/index.jsx
@@ -1,27 +1,10 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import { library } from '@fortawesome/fontawesome-svg-core';
-
-import { faArrowCircleDown } from '@fortawesome/free-solid-svg-icons/faArrowCircleDown';
-import { faArrowDown } from '@fortawesome/free-solid-svg-icons/faArrowDown';
-import { faArrowsAltV } from '@fortawesome/free-solid-svg-icons/faArrowsAltV';
-import { faArrowUp } from '@fortawesome/free-solid-svg-icons/faArrowUp';
-import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus';
-import { faTrash } from '@fortawesome/free-solid-svg-icons/faTrash';
import Flash from './Flash';
import OperationsQueue from './OperationsQueue';
import TypeDeChamps from './components/TypeDeChamps';
-library.add(
- faArrowCircleDown,
- faArrowDown,
- faArrowsAltV,
- faArrowUp,
- faPlus,
- faTrash
-);
-
class TypesDeChampEditor extends Component {
constructor(props) {
super(props);
diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb
index e858bae90..6b59ba733 100644
--- a/app/jobs/application_job.rb
+++ b/app/jobs/application_job.rb
@@ -1,7 +1,7 @@
class ApplicationJob < ActiveJob::Base
- DEFAULT_MAX_ATTEMPTS_JOBS = 25
+ include ActiveJob::RetryOnTransientErrors
- retry_on ::Excon::Error::BadRequest
+ DEFAULT_MAX_ATTEMPTS_JOBS = 25
before_perform do |job|
Rails.logger.info("#{job.class.name} started at #{Time.zone.now}")
diff --git a/app/jobs/archive_creation_job.rb b/app/jobs/archive_creation_job.rb
deleted file mode 100644
index 255af07db..000000000
--- a/app/jobs/archive_creation_job.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class ArchiveCreationJob < ApplicationJob
- def perform(procedure, archive, instructeur)
- ProcedureArchiveService
- .new(procedure)
- .collect_files_archive(archive, instructeur)
- end
-end
diff --git a/app/jobs/cron/purge_stale_archives_job.rb b/app/jobs/cron/purge_stale_archives_job.rb
deleted file mode 100644
index 4ce48784a..000000000
--- a/app/jobs/cron/purge_stale_archives_job.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class Cron::PurgeStaleArchivesJob < Cron::CronJob
- self.schedule_expression = "every 5 minutes"
-
- def perform
- Archive.stale.destroy_all
- end
-end
diff --git a/app/lib/active_job/retry_on_transient_errors.rb b/app/lib/active_job/retry_on_transient_errors.rb
new file mode 100644
index 000000000..b3790359c
--- /dev/null
+++ b/app/lib/active_job/retry_on_transient_errors.rb
@@ -0,0 +1,17 @@
+module ActiveJob::RetryOnTransientErrors
+ extend ActiveSupport::Concern
+
+ TRANSIENT_ERRORS = [
+ Excon::Error::InternalServerError,
+ Excon::Error::GatewayTimeout,
+ Excon::Error::BadRequest
+ ]
+
+ included do
+ if handler_for_rescue(TRANSIENT_ERRORS.first).nil?
+ TRANSIENT_ERRORS.each do |error_type|
+ retry_on error_type, attempts: 5, wait: :exponentially_longer
+ end
+ end
+ end
+end
diff --git a/app/lib/active_storage/downloadable_file.rb b/app/lib/active_storage/downloadable_file.rb
index d8ca5cf4c..db86efc73 100644
--- a/app/lib/active_storage/downloadable_file.rb
+++ b/app/lib/active_storage/downloadable_file.rb
@@ -1,12 +1,14 @@
class ActiveStorage::DownloadableFile
def self.create_list_from_dossier(dossier)
pjs = PiecesJustificativesService.liste_pieces_justificatives(dossier)
- pjs.map do |piece_justificative|
+ files = pjs.map do |piece_justificative|
[
piece_justificative,
- "dossier-#{dossier.id}/#{self.timestamped_filename(piece_justificative)}"
+ self.timestamped_filename(piece_justificative)
]
end
+ files << [dossier.pdf_export_for_instructeur, self.timestamped_filename(dossier.pdf_export_for_instructeur)]
+ files
end
private
@@ -20,23 +22,19 @@ class ActiveStorage::DownloadableFile
timestamp = attachment.created_at.strftime("%d-%m-%Y-%H-%M")
id = attachment.id % 10000
- [folder, "#{basename}-#{timestamp}-#{id}#{extension}"].join
+ "#{folder}/#{basename}-#{timestamp}-#{id}#{extension}"
end
def self.folder(attachment)
- if attachment.name == 'pdf_export_for_instructeur'
- return ''
- end
-
case attachment.record_type
when 'Dossier'
- 'dossier/'
+ 'dossier'
when 'DossierOperationLog', 'BillSignature'
- 'horodatage/'
+ 'horodatage'
when 'Commentaire'
- 'messagerie/'
+ 'messagerie'
else
- 'pieces_justificatives/'
+ 'pieces_justificatives'
end
end
diff --git a/app/mailers/instructeur_mailer.rb b/app/mailers/instructeur_mailer.rb
index 55332cf38..89c58864c 100644
--- a/app/mailers/instructeur_mailer.rb
+++ b/app/mailers/instructeur_mailer.rb
@@ -1,7 +1,5 @@
# Preview all emails at http://localhost:3000/rails/mailers/instructeur_mailer
class InstructeurMailer < ApplicationMailer
- helper MailerHelper
-
layout 'mailers/layout'
def user_to_instructeur(email)
@@ -44,12 +42,4 @@ class InstructeurMailer < ApplicationMailer
mail(to: instructeur.email, subject: subject)
end
-
- def send_archive(instructeur, procedure, archive)
- @archive = archive
- @procedure = procedure
- subject = "Votre archive est disponible"
-
- mail(to: instructeur.email, subject: subject)
- end
end
diff --git a/app/models/archive.rb b/app/models/archive.rb
deleted file mode 100644
index 7ee93720f..000000000
--- a/app/models/archive.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# == Schema Information
-#
-# Table name: archives
-#
-# id :bigint not null, primary key
-# key :text not null
-# month :date
-# status :string not null
-# time_span_type :string not null
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-class Archive < ApplicationRecord
- include AASM
-
- RETENTION_DURATION = 1.week
-
- has_and_belongs_to_many :groupe_instructeurs
-
- has_one_attached :file
-
- scope :stale, -> { where('updated_at < ?', (Time.zone.now - RETENTION_DURATION)) }
- scope :for_groupe_instructeur, -> (groupe_instructeur) {
- joins(:archives_groupe_instructeurs)
- .where(
- archives_groupe_instructeurs: { groupe_instructeur: groupe_instructeur }
- )
- }
-
- enum time_span_type: {
- everything: 'everything',
- monthly: 'monthly'
- }
-
- enum status: {
- pending: 'pending',
- generated: 'generated'
- }
-
- aasm whiny_persistence: true, column: :status, enum: true do
- state :pending, initial: true
- state :generated
-
- event :make_available do
- transitions from: :pending, to: :generated
- end
- end
-
- def available?
- status == 'generated' && file.attached?
- end
-
- def filename(procedure)
- if time_span_type == 'everything'
- "procedure-#{procedure.id}.zip"
- else
- "procedure-#{procedure.id}-mois-#{I18n.l(month, format: '%Y-%m')}.zip"
- end
- end
-
- def self.find_or_create_archive(time_span_type, month, groupe_instructeurs)
- create_with(groupe_instructeurs: groupe_instructeurs)
- .create_or_find_by(time_span_type: time_span_type, month: month, key: generate_cache_key(groupe_instructeurs))
- end
-
- private
-
- def self.generate_cache_key(groupe_instructeurs)
- groupe_instructeurs.map(&:id).sort.join('-')
- end
-end
diff --git a/app/models/dossier.rb b/app/models/dossier.rb
index 8b8a1e60e..a0add0355 100644
--- a/app/models/dossier.rb
+++ b/app/models/dossier.rb
@@ -172,12 +172,7 @@ class Dossier < ApplicationRecord
scope :en_construction, -> { not_archived.state_en_construction }
scope :en_instruction, -> { not_archived.state_en_instruction }
scope :termine, -> { not_archived.state_termine }
- 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, -> {
+ scope :downloadable_sorted, -> {
state_not_brouillon
.includes(
:user,
diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb
index d3e2fc21b..f43eda8fb 100644
--- a/app/models/instructeur.rb
+++ b/app/models/instructeur.rb
@@ -25,7 +25,6 @@ class Instructeur < ApplicationRecord
has_many :followed_dossiers, through: :follows, source: :dossier
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
has_many :trusted_device_tokens, dependent: :destroy
- has_many :archives
has_one :user, dependent: :nullify
diff --git a/app/models/procedure.rb b/app/models/procedure.rb
index b4760c353..ea0b4e570 100644
--- a/app/models/procedure.rb
+++ b/app/models/procedure.rb
@@ -156,20 +156,6 @@ class Procedure < ApplicationRecord
includes(:draft_revision, :published_revision, administrateurs: :user)
}
- scope :for_download, -> {
- includes(
- :groupe_instructeurs,
- dossiers: {
- champs: [
- piece_justificative_file_attachment: :blob,
- champs: [
- piece_justificative_file_attachment: :blob
- ]
- ]
- }
- )
- }
-
validates :libelle, presence: true, allow_blank: false, allow_nil: false
validates :description, presence: true, allow_blank: false, allow_nil: false
validates :administrateurs, presence: true
diff --git a/app/services/pieces_justificatives_service.rb b/app/services/pieces_justificatives_service.rb
index f3cd8303c..a5903531b 100644
--- a/app/services/pieces_justificatives_service.rb
+++ b/app/services/pieces_justificatives_service.rb
@@ -1,11 +1,10 @@
class PiecesJustificativesService
def self.liste_pieces_justificatives(dossier)
- dossier_export = generate_dossier_export(dossier)
pjs_champs = pjs_for_champs(dossier)
pjs_commentaires = pjs_for_commentaires(dossier)
pjs_dossier = pjs_for_dossier(dossier)
- ([dossier_export] + pjs_champs + pjs_commentaires + pjs_dossier)
+ (pjs_champs + pjs_commentaires + pjs_dossier)
.filter(&:attached?)
end
@@ -44,17 +43,6 @@ class PiecesJustificativesService
private
- def self.generate_dossier_export(dossier)
- pdf = ApplicationController
- .render(template: 'dossiers/show', formats: [:pdf],
- assigns: {
- include_infos_administration: true,
- dossier: dossier
- })
- dossier.pdf_export_for_instructeur.attach(io: StringIO.open(pdf), filename: "export-#{dossier.id}.pdf", content_type: 'application/pdf')
- dossier.pdf_export_for_instructeur
- end
-
def self.pjs_for_champs(dossier)
allowed_champs = dossier.champs + dossier.champs_private
diff --git a/app/services/procedure_archive_service.rb b/app/services/procedure_archive_service.rb
deleted file mode 100644
index b26757210..000000000
--- a/app/services/procedure_archive_service.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-require 'tempfile'
-
-class ProcedureArchiveService
- def initialize(procedure)
- @procedure = procedure
- end
-
- def create_pending_archive(instructeur, type, month = nil)
- groupe_instructeurs = instructeur
- .groupe_instructeurs
- .where(procedure: @procedure)
-
- Archive.find_or_create_archive(type, month, groupe_instructeurs)
- end
-
- def 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|
- 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
diff --git a/app/views/instructeur_mailer/send_archive.html.haml b/app/views/instructeur_mailer/send_archive.html.haml
deleted file mode 100644
index 11857c69f..000000000
--- a/app/views/instructeur_mailer/send_archive.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-- 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"
diff --git a/app/views/instructeurs/archives/create.js.haml b/app/views/instructeurs/archives/create.js.haml
deleted file mode 100644
index 7fe9f7f0b..000000000
--- a/app/views/instructeurs/archives/create.js.haml
+++ /dev/null
@@ -1 +0,0 @@
-= render_flash(sticky: true)
diff --git a/app/views/instructeurs/archives/index.html.haml b/app/views/instructeurs/archives/index.html.haml
deleted file mode 100644
index 82ec92f1d..000000000
--- a/app/views/instructeurs/archives/index.html.haml
+++ /dev/null
@@ -1,91 +0,0 @@
-- content_for(:title, "Archives pour #{@procedure.libelle}")
-
-= render partial: 'new_administrateur/breadcrumbs',
- locals: { steps: [link_to(@procedure.libelle, instructeur_procedure_path(@procedure)),
- 'Archives'] }
-
-.container
- %h1 Archives
-
- .card.featured
- .card-title Gestion de vos archives
- %p
- Vous pouvez télécharger les archives des dossiers terminés depuis la publication de la procédure au format Zip.
-
- %p
- Cet export contient les demande déposée par l'usager et la liste des pièces justificatives transmises.
-
- %p
- Cet export n'est pas possible pour le moment pour les démarches à forte volumétrie.
- 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
- %thead
- %tr
- %th
- %th Nombre de dossiers terminés
- %th Poids estimé
- %th Télécharger
-
- %tbody
- - if can_generate_archive?(@dossiers_termines, @poids_total)
- %tr
- - matching_archive = @archives.find_by(time_span_type: 'everything')
- %td
- Tous les dossiers
- %td
- = @dossiers_termines.count
- %td
- - if matching_archive.present? && matching_archive.available?
- - weight = matching_archive.file.byte_size
- - else
- - weight = @poids_total
- = number_to_human_size(weight)
- %td
- - if matching_archive.try(&:available?)
- = link_to url_for(matching_archive.file), class: 'button primary' do
- %span.icon.download-white
- = t(:archive_ready_html, generated_period: time_ago_in_words(matching_archive.updated_at), scope: [:instructeurs, :procedure])
- - elsif matching_archive.try(&:pending?)
- %span.icon.retry
- = t(:archive_pending_html, created_period: time_ago_in_words(matching_archive.created_at), scope: [:instructeurs, :procedure])
- - elsif @dossiers_termines.count > 0
- = link_to instructeur_archives_path(@procedure, type: 'everything'), method: :post, class: "button" do
- %span.icon.new-folder
- Demander la création
- - else
- Rien à télécharger !
- - @archivable_months.each do |month|
- - dossiers_termines = @procedure.dossiers.processed_in_month(month)
- - nb_dossiers_termines = dossiers_termines.count
- - matching_archive = @archives.find_by(time_span_type: 'monthly', month: month)
- %tr
- %td
- = I18n.l(month, format: "%B %Y")
- %td
- = nb_dossiers_termines
- %td
- - if matching_archive.present? && matching_archive.available?
- - weight = matching_archive.file.byte_size
- - else
- - weight = ProcedureArchiveService::dossiers_files_size(dossiers_termines)
- = number_to_human_size(weight)
- %td
- - if nb_dossiers_termines > 0
- - 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, generated_period: time_ago_in_words(matching_archive.updated_at), scope: [:instructeurs, :procedure])
- - else
- %span.icon.retry
- = t(:archive_pending_html, created_period: time_ago_in_words(matching_archive.created_at), scope: [:instructeurs, :procedure])
- - else
- = link_to instructeur_archives_path(@procedure, type:'monthly', month: month.strftime('%Y-%m')), method: :post, class: "button" do
- %span.icon.new-folder
- Démander la création
- - else
- Rien à télécharger !
-
diff --git a/app/views/instructeurs/procedures/_download_dossiers.html.haml b/app/views/instructeurs/procedures/_download_dossiers.html.haml
index b3be64c10..a465eb9c9 100644
--- a/app/views/instructeurs/procedures/_download_dossiers.html.haml
+++ b/app/views/instructeurs/procedures/_download_dossiers.html.haml
@@ -16,6 +16,3 @@
- else
%span{ 'data-export-poll-url': download_export_instructeur_procedure_path(procedure, export_format: format, no_progress_notification: true) }
= t(:export_pending_html, export_time: time_ago_in_words(export.created_at), export_format: ".#{format}", scope: [:instructeurs, :procedure])
- - if procedure.feature_enabled?(:archive_zip_globale)
- %li
- = link_to t(:download_archive, scope: [:instructeurs, :procedure]), instructeur_archives_path(procedure)
diff --git a/config/initializers/active_storage.rb b/config/initializers/active_storage.rb
index 45d529258..dfa8c8582 100644
--- a/config/initializers/active_storage.rb
+++ b/config/initializers/active_storage.rb
@@ -14,6 +14,12 @@ ActiveSupport.on_load(:active_storage_attachment) do
include AttachmentVirusScannerConcern
end
+Rails.application.reloader.to_prepare do
+ class ActiveStorage::BaseJob
+ include ActiveJob::RetryOnTransientErrors
+ end
+end
+
# When an OpenStack service is initialized it makes a request to fetch
# `publicURL` to use for all operations. We intercept the method that reads
# this url and replace the host with DS_Proxy host. This way all the operation
diff --git a/config/locales/views/instructeurs/fr.yml b/config/locales/views/instructeurs/fr.yml
index ef2b1987b..3cc5fabdc 100644
--- a/config/locales/views/instructeurs/fr.yml
+++ b/config/locales/views/instructeurs/fr.yml
@@ -8,6 +8,3 @@ fr:
ods_html: Demander un export au format .ods
export_ready_html: Télécharger l’export au format %{export_format}
(généré il y a %{export_time})
export_pending_html: Un export au format %{export_format} est en train d’être généré
(demandé il y a %{export_time})
- download_archive: Télécharger une archive au format .zip de tous les dossiers et leurs pièces jointes
- archive_pending_html: Archive en cours de création
(demandée il y a %{created_period})
- archive_ready_html: Télécharger l'archive
(demandée il y a %{generated_period})
diff --git a/config/routes.rb b/config/routes.rb
index acdac88ea..bb953ffa4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -383,8 +383,6 @@ Rails.application.routes.draw do
get 'telecharger_pjs' => 'dossiers#telecharger_pjs'
end
end
-
- resources :archives, only: [:index, :create, :show], controller: 'archives'
end
end
get "recherche" => "recherche#index"
diff --git a/db/migrate/20201104163658_create_archive_for_groupe_instructeur.rb b/db/migrate/20201104163658_create_archive_for_groupe_instructeur.rb
deleted file mode 100644
index 51793681c..000000000
--- a/db/migrate/20201104163658_create_archive_for_groupe_instructeur.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-class CreateArchiveForGroupeInstructeur < ActiveRecord::Migration[6.0]
- def change
- create_table :archives do |t|
- t.string :status, null: false
- t.date :month
- t.string :content_type, null: false
- t.timestamps
- end
-
- create_table "archives_groupe_instructeurs", force: :cascade do |t|
- t.belongs_to :archive, foreign_key: true, null: false
- t.belongs_to :groupe_instructeur, foreign_key: true, null: false
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20210427112642_rename_content_type_to_to_time_span_type_for_archives.rb b/db/migrate/20210427112642_rename_content_type_to_to_time_span_type_for_archives.rb
deleted file mode 100644
index be6d5a404..000000000
--- a/db/migrate/20210427112642_rename_content_type_to_to_time_span_type_for_archives.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class RenameContentTypeToToTimeSpanTypeForArchives < ActiveRecord::Migration[6.1]
- def change
- rename_column :archives, :content_type, :time_span_type
- end
-end
diff --git a/db/migrate/20210427124500_add_key_to_archives.rb b/db/migrate/20210427124500_add_key_to_archives.rb
deleted file mode 100644
index 08559a0dc..000000000
--- a/db/migrate/20210427124500_add_key_to_archives.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddKeyToArchives < ActiveRecord::Migration[6.1]
- def change
- add_column :archives, :key, :text, null: false
- add_index :archives, [:key, :time_span_type, :month], unique: true
- end
-end
diff --git a/db/schema.rb b/db/schema.rb
index eefe0112f..956e5a302 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2021_04_27_124500) do
+ActiveRecord::Schema.define(version: 2021_04_27_120002) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -81,25 +81,6 @@ ActiveRecord::Schema.define(version: 2021_04_27_124500) do
t.index ["procedure_id"], name: "index_administrateurs_procedures_on_procedure_id"
end
- create_table "archives", force: :cascade do |t|
- t.string "status", null: false
- t.date "month"
- t.string "time_span_type", null: false
- t.datetime "created_at", precision: 6, null: false
- t.datetime "updated_at", precision: 6, null: false
- t.text "key", null: false
- t.index ["key", "time_span_type", "month"], name: "index_archives_on_key_and_time_span_type_and_month", unique: true
- end
-
- create_table "archives_groupe_instructeurs", force: :cascade do |t|
- t.bigint "archive_id", null: false
- t.bigint "groupe_instructeur_id", null: false
- t.datetime "created_at", precision: 6, null: false
- t.datetime "updated_at", precision: 6, null: false
- t.index ["archive_id"], name: "index_archives_groupe_instructeurs_on_archive_id"
- t.index ["groupe_instructeur_id"], name: "index_archives_groupe_instructeurs_on_groupe_instructeur_id"
- end
-
create_table "assign_tos", id: :serial, force: :cascade do |t|
t.integer "instructeur_id"
t.datetime "created_at"
@@ -754,8 +735,6 @@ ActiveRecord::Schema.define(version: 2021_04_27_124500) do
end
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
- add_foreign_key "archives_groupe_instructeurs", "archives"
- add_foreign_key "archives_groupe_instructeurs", "groupe_instructeurs"
add_foreign_key "assign_tos", "groupe_instructeurs"
add_foreign_key "attestation_templates", "procedures"
add_foreign_key "attestations", "dossiers"
diff --git a/package.json b/package.json
index d825b40e0..102d3b750 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,6 @@
{
"dependencies": {
"@babel/preset-react": "^7.12.13",
- "@fortawesome/fontawesome-svg-core": "^1.2.34",
- "@fortawesome/free-solid-svg-icons": "^5.15.2",
- "@fortawesome/react-fontawesome": "^0.1.14",
"@heroicons/react": "^1.0.1",
"@mapbox/mapbox-gl-draw": "^1.2.2",
"@rails/actiontext": "^6.0.3",
diff --git a/spec/controllers/instructeurs/archives_controller_spec.rb b/spec/controllers/instructeurs/archives_controller_spec.rb
deleted file mode 100644
index 7ce7e4d22..000000000
--- a/spec/controllers/instructeurs/archives_controller_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-describe Instructeurs::ArchivesController, type: :controller do
- let(:procedure1) { create(:procedure, :published, groupe_instructeurs: [gi1]) }
- let(:procedure2) { create(:procedure, :published, groupe_instructeurs: [gi2]) }
- let!(:instructeur) { create(:instructeur, groupe_instructeurs: [gi1, gi2]) }
- let!(:archive1) { create(:archive, :generated, groupe_instructeurs: [gi1]) }
- let!(:archive2) { create(:archive, :generated, groupe_instructeurs: [gi2]) }
- let(:gi1) { create(:groupe_instructeur) }
- let(:gi2) { create(:groupe_instructeur) }
-
- before do
- sign_in(instructeur.user)
- Flipper.enable(:archive_zip_globale, procedure1)
- end
-
- after { Timecop.return }
-
- describe '#index' do
- before do
- create_dossier_for_month(procedure1, 2021, 3)
- create_dossier_for_month(procedure1, 2021, 3)
- create_dossier_for_month(procedure1, 2021, 2)
- Timecop.freeze(Time.zone.local(2021, 3, 5))
- end
-
- it 'displays archives' do
- get :index, { params: { procedure_id: procedure1.id } }
-
- expect(assigns(:dossiers_termines).size).to eq(3)
- expect(assigns(:archives)).to eq([archive1])
- end
- end
-
- describe '#create' do
- let(:month) { '21-03' }
- let(:date_month) { Date.strptime(month, "%Y-%m") }
- let(:archive) { create(:archive) }
- let(:subject) do
- post :create, {
- params: { procedure_id: procedure1.id, type: 'monthly', month: month }
- }
- end
-
- 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, archive, instructeur)
- expect(flash.notice).to include("Votre demande a été prise en compte")
- end
- end
-
- private
-
- def create_dossier_for_month(procedure, year, month)
- Timecop.freeze(Time.zone.local(year, month, 5))
- create(:dossier, :accepte, :with_attestation, procedure: procedure)
- end
-end
diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb
index ab6d9ff5a..b31cb81c0 100644
--- a/spec/controllers/instructeurs/dossiers_controller_spec.rb
+++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb
@@ -712,6 +712,13 @@ describe Instructeurs::DossiersController, type: :controller do
dossier_id: dossier.id
}
end
+
+ context 'when zip download is disabled through flipflop' do
+ it 'is forbidden' do
+ subject
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
end
describe "#delete_dossier" do
diff --git a/spec/factories/archive.rb b/spec/factories/archive.rb
deleted file mode 100644
index 41fbc2542..000000000
--- a/spec/factories/archive.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-FactoryBot.define do
- factory :archive do
- time_span_type { 'everything' }
- groupe_instructeurs { [association(:groupe_instructeur)] }
- key { 'unique-key' }
-
- trait :pending do
- status { 'pending' }
- end
-
- trait :generated do
- status { 'generated' }
- end
- end
-end
diff --git a/spec/features/instructeurs/expert_spec.rb b/spec/features/instructeurs/expert_spec.rb
index a384687b6..d361b3cf3 100644
--- a/spec/features/instructeurs/expert_spec.rb
+++ b/spec/features/instructeurs/expert_spec.rb
@@ -12,8 +12,6 @@ feature 'Inviting an expert:', js: true do
context 'as an Instructeur' do
scenario 'I can invite an expert' do
- allow(ClamavService).to receive(:safe_file?).and_return(true)
-
# assign instructeur to linked dossier
instructeur.assign_to_procedure(linked_dossier.procedure)
diff --git a/spec/features/instructeurs/instruction_spec.rb b/spec/features/instructeurs/instruction_spec.rb
index 257ca2a73..e24f3c48c 100644
--- a/spec/features/instructeurs/instruction_spec.rb
+++ b/spec/features/instructeurs/instruction_spec.rb
@@ -165,10 +165,10 @@ feature 'Instructing a dossier:', js: true do
expect(DownloadHelpers.download).to include "dossier-#{dossier.id}.zip"
expect(files.size).to be 3
- expect(files[0].filename.include?('export')).to be_truthy
- expect(files[1].filename.include?('piece_justificative_0')).to be_truthy
- expect(files[1].uncompressed_size).to be File.size(path)
- expect(files[2].filename.include?('horodatage/operation')).to be_truthy
+ expect(files[0].filename.include?('piece_justificative_0')).to be_truthy
+ expect(files[0].uncompressed_size).to be File.size(path)
+ expect(files[1].filename.include?('horodatage/operation')).to be_truthy
+ expect(files[2].filename.include?('dossier/export')).to be_truthy
end
scenario 'A instructeur can download an archive containing several identical attachments' do
@@ -180,13 +180,13 @@ feature 'Instructing a dossier:', js: true do
expect(DownloadHelpers.download).to include "dossier-#{dossier.id}.zip"
expect(files.size).to be 4
- expect(files[0].filename.include?('export')).to be_truthy
+ expect(files[0].filename.include?('piece_justificative_0')).to be_truthy
expect(files[1].filename.include?('piece_justificative_0')).to be_truthy
- expect(files[2].filename.include?('piece_justificative_0')).to be_truthy
- expect(files[1].filename).not_to eq files[2].filename
+ expect(files[0].filename).not_to eq files[1].filename
+ expect(files[0].uncompressed_size).to be File.size(path)
expect(files[1].uncompressed_size).to be File.size(path)
- expect(files[2].uncompressed_size).to be File.size(path)
- expect(files[3].filename.include?('horodatage/operation')).to be_truthy
+ expect(files[2].filename.include?('horodatage/operation')).to be_truthy
+ expect(files[3].filename.include?('dossier/export')).to be_truthy
end
before { DownloadHelpers.clear_downloads }
diff --git a/spec/jobs/active_storage/base_job_spec.rb b/spec/jobs/active_storage/base_job_spec.rb
new file mode 100644
index 000000000..2a565623b
--- /dev/null
+++ b/spec/jobs/active_storage/base_job_spec.rb
@@ -0,0 +1,3 @@
+describe ActiveStorage::BaseJob do
+ it_behaves_like 'a job retrying transient errors'
+end
diff --git a/spec/jobs/application_job_spec.rb b/spec/jobs/application_job_spec.rb
index 8de03c541..e2d00b7fb 100644
--- a/spec/jobs/application_job_spec.rb
+++ b/spec/jobs/application_job_spec.rb
@@ -1,6 +1,8 @@
include ActiveJob::TestHelper
RSpec.describe ApplicationJob, type: :job do
+ it_behaves_like 'a job retrying transient errors'
+
describe 'perform' do
before do
allow(Rails.logger).to receive(:info)
@@ -13,23 +15,7 @@ RSpec.describe ApplicationJob, type: :job do
end
end
- context 'when ::Excon::Error::BadRequest is raised' do
- # https://api.rubyonrails.org/classes/ActiveJob/Exceptions/ClassMethods.html#method-i-retry_on
- # retry on will try 5 times and then bubble up the error
- it 'makes 5 attempts' do
- assert_performed_jobs 5 do
- ExconErrJob.perform_later rescue ::Excon::Error::BadRequest
- end
- end
- end
-
class ChildJob < ApplicationJob
def perform; end
end
-
- class ExconErrJob < ApplicationJob
- def perform
- raise ::Excon::Error::BadRequest.new('bad request')
- end
- end
end
diff --git a/spec/lib/active_job/retry_on_transient_errors_spec.rb b/spec/lib/active_job/retry_on_transient_errors_spec.rb
new file mode 100644
index 000000000..b1ee46ccd
--- /dev/null
+++ b/spec/lib/active_job/retry_on_transient_errors_spec.rb
@@ -0,0 +1,9 @@
+describe ActiveJob::RetryOnTransientErrors do
+ # rubocop:disable Rails/ApplicationJob
+ class Job < ActiveJob::Base
+ include ActiveJob::RetryOnTransientErrors
+ end
+ # rubocop:enable Rails/ApplicationJob
+
+ it_behaves_like 'a job retrying transient errors', Job
+end
diff --git a/spec/models/archive_spec.rb b/spec/models/archive_spec.rb
deleted file mode 100644
index 5753340d3..000000000
--- a/spec/models/archive_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-describe Dossier do
- include ActiveJob::TestHelper
-
- before { Timecop.freeze(Time.zone.now) }
- after { Timecop.return }
-
- let(:archive) { create(:archive) }
-
- describe 'scopes' do
- describe 'staled' do
- let(:recent_archive) { create(:archive) }
- let(:staled_archive) { create(:archive, updated_at: (Archive::RETENTION_DURATION + 2).days.ago) }
-
- subject do
- archive; recent_archive; staled_archive
- Archive.stale
- end
-
- it { is_expected.to match_array([staled_archive]) }
- end
- end
-
- describe '.status' do
- it { expect(archive.status).to eq('pending') }
- end
-
- describe '#make_available!' do
- before { archive.make_available! }
- it { expect(archive.status).to eq('generated') }
- end
-
- describe '#available?' do
- subject { archive.available? }
- context 'without attachment' do
- let(:archive) { create(:archive, file: nil) }
- it { is_expected.to eq(false) }
- end
-
- context 'with an attachment' do
- context 'when the attachment was created but the process was not over' do
- let(:archive) { create(:archive, :pending, file: Rack::Test::UploadedFile.new('spec/fixtures/files/file.pdf', 'application/pdf')) }
- it { is_expected.to eq(false) }
- end
-
- context 'when the attachment was created but the process was not over' do
- let(:archive) { create(:archive, :generated, file: Rack::Test::UploadedFile.new('spec/fixtures/files/file.pdf', 'application/pdf')) }
- it { is_expected.to eq(true) }
- end
- end
- end
-end
diff --git a/spec/services/pieces_justificatives_service_spec.rb b/spec/services/pieces_justificatives_service_spec.rb
index fc151f908..d0ad55499 100644
--- a/spec/services/pieces_justificatives_service_spec.rb
+++ b/spec/services/pieces_justificatives_service_spec.rb
@@ -16,12 +16,7 @@ describe PiecesJustificativesService do
# to be exported
it 'ensures no titre identite is given' do
expect(champ_identite.piece_justificative_file).to be_attached
- expect(subject.any? { |piece| piece.name == 'piece_justificative_file' }).to be_falsy
- end
-
- it 'returns export pdf of the dossier' do
- expect(champ_identite.piece_justificative_file).to be_attached
- expect(subject.any? { |piece| piece.name == 'pdf_export_for_instructeur' }).to be_truthy
+ expect(subject).to eq([])
end
end
end
diff --git a/spec/services/procedure_archive_service_spec.rb b/spec/services/procedure_archive_service_spec.rb
deleted file mode 100644
index 80e013f74..000000000
--- a/spec/services/procedure_archive_service_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-describe ProcedureArchiveService 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") }
- 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 '#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
- 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
-
- 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
diff --git a/spec/support/shared_examples_for_jobs.rb b/spec/support/shared_examples_for_jobs.rb
new file mode 100644
index 000000000..f30a67769
--- /dev/null
+++ b/spec/support/shared_examples_for_jobs.rb
@@ -0,0 +1,29 @@
+RSpec.shared_examples 'a job retrying transient errors' do |job_class = described_class|
+ context 'when a transient network error is raised' do
+ ExconErrorJob = Class.new(job_class) do
+ def perform
+ raise Excon::Error::InternalServerError, 'msg'
+ end
+ end
+
+ it 'makes 5 attempts before raising the exception up' do
+ assert_performed_jobs 5 do
+ ExconErrorJob.perform_later rescue Excon::Error::InternalServerError
+ end
+ end
+ end
+
+ context 'when another type of error is raised' do
+ StandardErrorJob = Class.new(job_class) do
+ def perform
+ raise StandardError
+ end
+ end
+
+ it 'makes only 1 attempt before raising the exception up' do
+ assert_performed_jobs 1 do
+ StandardErrorJob.perform_later rescue StandardError
+ end
+ end
+ end
+end
diff --git a/spec/views/instructeur/procedures/_download_dossiers.html.haml_spec.rb b/spec/views/instructeur/procedures/_download_dossiers.html.haml_spec.rb
index 8fb8f346e..947ce178f 100644
--- a/spec/views/instructeur/procedures/_download_dossiers.html.haml_spec.rb
+++ b/spec/views/instructeur/procedures/_download_dossiers.html.haml_spec.rb
@@ -12,15 +12,5 @@ describe 'instructeurs/procedures/_download_dossiers.html.haml', type: :view do
context "when procedure has at least 1 dossier" do
let(:dossier_count) { 1 }
it { is_expected.to include("Télécharger tous les dossiers") }
-
- context "With zip archive enabled" do
- before { Flipper.enable(:archive_zip_globale, procedure) }
- it { is_expected.to include("Télécharger une archive au format .zip") }
- end
-
- context "With zip archive disabled" do
- before { Flipper.disable(:archive_zip_globale, procedure) }
- it { is_expected.not_to include("Télécharger une archive au format .zip") }
- end
end
end
diff --git a/yarn.lock b/yarn.lock
index c653dddfe..322c51cbd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1005,32 +1005,6 @@
enabled "2.0.x"
kuler "^2.0.0"
-"@fortawesome/fontawesome-common-types@^0.2.34":
- version "0.2.34"
- resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.34.tgz#0a8c348bb23b7b760030f5b1d912e582be4ec915"
- integrity sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA==
-
-"@fortawesome/fontawesome-svg-core@^1.2.34":
- version "1.2.34"
- resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.34.tgz#1d1a7c92537cbc2b8a83eef6b6d824b4b5b46b26"
- integrity sha512-0KNN0nc5eIzaJxlv43QcDmTkDY1CqeN6J7OCGSs+fwGPdtv0yOQqRjieopBCmw+yd7uD3N2HeNL3Zm5isDleLg==
- dependencies:
- "@fortawesome/fontawesome-common-types" "^0.2.34"
-
-"@fortawesome/free-solid-svg-icons@^5.15.2":
- version "5.15.2"
- resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.2.tgz#25bb035de57cf85aee8072965732368ccc8e8943"
- integrity sha512-ZfCU+QjaFsdNZmOGmfqEWhzI3JOe37x5dF4kz9GeXvKn/sTxhqMtZ7mh3lBf76SvcYY5/GKFuyG7p1r4iWMQqw==
- dependencies:
- "@fortawesome/fontawesome-common-types" "^0.2.34"
-
-"@fortawesome/react-fontawesome@^0.1.14":
- version "0.1.14"
- resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz#bf28875c3935b69ce2dc620e1060b217a47f64ca"
- integrity sha512-4wqNb0gRLVaBm/h+lGe8UfPPivcbuJ6ecI4hIgW0LjI7kzpYB9FkN0L9apbVzg+lsBdcTf0AlBtODjcSX5mmKA==
- dependencies:
- prop-types "^15.7.2"
-
"@heroicons/react@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.1.tgz#66d25f6441920bd5c2146ea27fd33995885452dd"