chore(exports): dropdown menu re-uses the same pending export or create a fresh one
Pour permettre d'avoir des données fraiches dans un export tout en conservant l'historique des exports, la demande d'export depuis le menu créé toujours un nouvel export sauf: - si un autre export identique est déjà en préparation - si un autre export identique s'est terminé il y a moins de 5 minutes Co-Authored-By: Lisa Durand <lisa.c.durand@gmail.com>
This commit is contained in:
parent
de7d60e18e
commit
d4198869fb
7 changed files with 62 additions and 50 deletions
|
@ -21,11 +21,10 @@ class Dossiers::ExportDropdownComponent < ApplicationComponent
|
|||
item.fetch(:format) != :json || @procedure.active_revision.carte?
|
||||
end
|
||||
|
||||
def download_export_path(export_format:, force_export: false, no_progress_notification: nil)
|
||||
def download_export_path(export_format:, no_progress_notification: nil)
|
||||
@export_url.call(@procedure,
|
||||
export_format: export_format,
|
||||
statut: @statut,
|
||||
force_export: force_export,
|
||||
no_progress_notification: no_progress_notification)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,10 +11,9 @@ class Dossiers::ExportLinkComponent < ApplicationComponent
|
|||
@export_url = export_url
|
||||
end
|
||||
|
||||
def download_export_path(export_format:, statut:, force_export: false, no_progress_notification: nil)
|
||||
def download_export_path(export_format:, statut:, no_progress_notification: nil)
|
||||
@export_url.call(@procedure,
|
||||
export_format: export_format,
|
||||
force_export: force_export,
|
||||
statut: statut,
|
||||
no_progress_notification: no_progress_notification)
|
||||
end
|
||||
|
@ -63,11 +62,9 @@ class Dossiers::ExportLinkComponent < ApplicationComponent
|
|||
|
||||
def refresh_button_options(export)
|
||||
{
|
||||
title: t(".refresh_old_export", export_format: ".#{export.format}"),
|
||||
"aria-label" => t(".refresh_old_export", export_format: ".#{export.format}"),
|
||||
class: class_names("fr-btn fr-btn--sm fr-icon-refresh-line fr-btn--tertiary" => true,
|
||||
"fr-btn--icon" => !export.failed?,
|
||||
"fr-btn--icon-left" => export.failed?)
|
||||
title: t(".refresh_old_export"),
|
||||
"aria-label" => t(".refresh_old_export"),
|
||||
class: "fr-btn fr-btn--sm fr-icon-refresh-line fr-btn--tertiary fr-btn--icon-left"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
.flex.flex-gap-2
|
||||
= export_button(export)
|
||||
|
||||
- if export.old? || export.failed?
|
||||
= button_to refresh_button_options(export)[:title], download_export_path(export_format: export.format, statut: export.statut, force_export: true), refresh_button_options(export)
|
||||
- if export.failed?
|
||||
= button_to refresh_button_options(export)[:title], download_export_path(export_format: export.format, statut: export.statut), refresh_button_options(export)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ module Administrateurs
|
|||
before_action :ensure_not_super_admin!
|
||||
|
||||
def download
|
||||
export = Export.find_or_create_export(export_format, all_groupe_instructeurs, force: force_export?, **export_options)
|
||||
export = Export.find_or_create_fresh_export(export_format, all_groupe_instructeurs, **export_options)
|
||||
@dossiers_count = export.count
|
||||
|
||||
if export.available?
|
||||
|
@ -37,10 +37,6 @@ module Administrateurs
|
|||
@export_format ||= params[:export_format]
|
||||
end
|
||||
|
||||
def force_export?
|
||||
@force_export ||= params[:force_export].present?
|
||||
end
|
||||
|
||||
def export_options
|
||||
@export_options ||= {
|
||||
time_span_type: params[:time_span_type],
|
||||
|
|
|
@ -172,7 +172,7 @@ module Instructeurs
|
|||
.visible_by_administration
|
||||
.exists?(groupe_instructeur_id: groupe_instructeur_ids) && !instructeur_as_manager?
|
||||
|
||||
export = Export.find_or_create_export(export_format, groupe_instructeurs, force: force_export?, **export_options)
|
||||
export = Export.find_or_create_fresh_export(export_format, groupe_instructeurs, **export_options)
|
||||
|
||||
@procedure = procedure
|
||||
@statut = export_options[:statut]
|
||||
|
@ -309,10 +309,6 @@ module Instructeurs
|
|||
@export_format ||= params[:export_format]
|
||||
end
|
||||
|
||||
def force_export?
|
||||
@force_export ||= params[:force_export].present?
|
||||
end
|
||||
|
||||
def export_options
|
||||
@export_options ||= {
|
||||
time_span_type: params[:time_span_type],
|
||||
|
|
|
@ -59,27 +59,28 @@ class Export < ApplicationRecord
|
|||
time_span_type == Export.time_span_types.fetch(:monthly) ? 30.days.ago : nil
|
||||
end
|
||||
|
||||
def old?
|
||||
updated_at < 10.minutes.ago || filters_changed?
|
||||
end
|
||||
|
||||
def filters_changed?
|
||||
procedure_presentation&.snapshot != procedure_presentation_snapshot
|
||||
end
|
||||
|
||||
def filtered?
|
||||
procedure_presentation_id.present?
|
||||
end
|
||||
|
||||
def self.find_or_create_export(format, groupe_instructeurs, time_span_type: time_span_types.fetch(:everything), statut: statuts.fetch(:tous), procedure_presentation: nil, force: false)
|
||||
export = create_or_find_export(format, groupe_instructeurs, time_span_type: time_span_type, statut: statut, procedure_presentation: procedure_presentation)
|
||||
def self.find_or_create_fresh_export(format, groupe_instructeurs, time_span_type: time_span_types.fetch(:everything), statut: statuts.fetch(:tous), procedure_presentation: nil)
|
||||
attributes = {
|
||||
format:,
|
||||
time_span_type:,
|
||||
statut:,
|
||||
key: generate_cache_key(groupe_instructeurs.map(&:id), procedure_presentation)
|
||||
}
|
||||
|
||||
if export.available? && export.old? && force
|
||||
export.destroy!
|
||||
create_or_find_export(format, groupe_instructeurs, time_span_type: time_span_type, statut: statut, procedure_presentation: procedure_presentation)
|
||||
else
|
||||
export
|
||||
end
|
||||
recent_export = pending
|
||||
.or(generated.where(updated_at: (5.minutes.ago)..))
|
||||
.includes(:procedure_presentation)
|
||||
.find_by(attributes)
|
||||
|
||||
return recent_export if recent_export.present?
|
||||
|
||||
create!(**attributes, groupe_instructeurs:,
|
||||
procedure_presentation:,
|
||||
procedure_presentation_snapshot: procedure_presentation&.snapshot)
|
||||
end
|
||||
|
||||
def self.for_groupe_instructeurs(groupe_instructeurs_ids)
|
||||
|
@ -93,15 +94,6 @@ class Export < ApplicationRecord
|
|||
])
|
||||
end
|
||||
|
||||
def self.create_or_find_export(format, groupe_instructeurs, time_span_type:, statut:, procedure_presentation:)
|
||||
create_with(groupe_instructeurs: groupe_instructeurs, procedure_presentation: procedure_presentation, procedure_presentation_snapshot: procedure_presentation&.snapshot)
|
||||
.includes(:procedure_presentation)
|
||||
.create_or_find_by(format: format,
|
||||
time_span_type: time_span_type,
|
||||
statut: statut,
|
||||
key: generate_cache_key(groupe_instructeurs.map(&:id), procedure_presentation))
|
||||
end
|
||||
|
||||
def self.generate_cache_key(groupe_instructeurs_ids, procedure_presentation = nil)
|
||||
if procedure_presentation.present?
|
||||
[
|
||||
|
|
|
@ -79,7 +79,7 @@ RSpec.describe Export, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.find_or_create_export' do
|
||||
describe '.find_or_create_fresh_export' do
|
||||
let!(:procedure) { create(:procedure) }
|
||||
let!(:gi_1) { create(:groupe_instructeur, procedure: procedure, instructeurs: [create(:instructeur)]) }
|
||||
let!(:pp) { gi_1.instructeurs.first.procedure_presentation_and_errors_for_procedure_id(procedure.id).first }
|
||||
|
@ -87,18 +87,50 @@ RSpec.describe Export, type: :model do
|
|||
|
||||
context 'with procedure_presentation having different filters' do
|
||||
it 'works once' do
|
||||
expect { Export.find_or_create_export(:zip, [gi_1], time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||
expect { Export.find_or_create_fresh_export(:zip, [gi_1], time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||
.to change { Export.count }.by(1)
|
||||
end
|
||||
|
||||
it 'works once, changes procedure_presentation, recreate a new' do
|
||||
expect { Export.find_or_create_export(:zip, [gi_1], time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||
expect { Export.find_or_create_fresh_export(:zip, [gi_1], time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||
.to change { Export.count }.by(1)
|
||||
pp.add_filter('tous', 'self/updated_at', '10/12/2021')
|
||||
expect { Export.find_or_create_export(:zip, [gi_1], time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||
expect { Export.find_or_create_fresh_export(:zip, [gi_1], time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||
.to change { Export.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with existing matching export' do
|
||||
def find_or_create =
|
||||
Export.find_or_create_fresh_export(:zip, [gi_1], time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp)
|
||||
|
||||
context 'freshly generate export' do
|
||||
before { find_or_create.update!(job_status: :generated, updated_at: 1.second.ago) }
|
||||
|
||||
it 'returns current pending export' do
|
||||
current_export = find_or_create
|
||||
|
||||
expect(find_or_create).to eq(current_export)
|
||||
end
|
||||
end
|
||||
|
||||
context 'old generated export' do
|
||||
before { find_or_create.update!(job_status: :generated, updated_at: 1.hour.ago) }
|
||||
|
||||
it 'returns a new export' do
|
||||
expect { find_or_create }.to change { Export.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'pending export' do
|
||||
before { find_or_create.update!(updated_at: 1.hour.ago) }
|
||||
|
||||
it 'returns current pending export' do
|
||||
current_export = find_or_create
|
||||
expect(find_or_create).to eq(current_export)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.dossiers_for_export' do
|
||||
|
|
Loading…
Reference in a new issue