feat(export_template): use in export service

This commit is contained in:
mfo 2024-11-04 17:00:25 +01:00
parent f014006542
commit c209cac62f
No known key found for this signature in database
GPG key ID: 7CE3E1F5B794A8EC
6 changed files with 283 additions and 6 deletions

View file

@ -19,8 +19,9 @@ module DossierExportConcern
types_de_champ.flat_map do |type_de_champ|
champ = filled_champ(type_de_champ, row_id)
if export_template.present?
columns = export_template.columns_for_stable_id(type_de_champ.stable_id)
columns.map { [_1.libelle, type_de_champ.champ_value_for_export(champ, _1.column)] }
export_template
.columns_for_stable_id(type_de_champ.stable_id)
.map { |exported_column| exported_column.libelle_with_value(champ) }
else
type_de_champ.libelles_for_export.map do |(libelle, path)|
[libelle, type_de_champ.champ_value_for_export(champ, path)]
@ -37,7 +38,7 @@ module DossierExportConcern
def dossier_values_for_export(with_etablissement: false, export_template: nil)
if export_template.present?
return export_template.dossier_exported_columns.map { [_1.libelle, _1.column.get_value(self)] }
return export_template.dossier_exported_columns.map { _1.libelle_with_value(self) }
end
columns = [

View file

@ -9,4 +9,8 @@ class ExportedColumn
end
def id = { id: column.id, libelle: }.to_json
def libelle_with_value(champ_or_dossier)
[libelle, column.value(champ_or_dossier)]
end
end

View file

@ -115,7 +115,7 @@ class ProcedureExportService
{
sheet_name: type_de_champ_repetition.libelle_for_export,
instances: rows,
spreadsheet_columns: Proc.new { |instance| instance.spreadsheet_columns(types_de_champ) }
spreadsheet_columns: Proc.new { |instance| instance.spreadsheet_columns(types_de_champ, export_template: @export_template) }
}
end
end
@ -152,7 +152,7 @@ class ProcedureExportService
types_de_champ = procedure.types_de_champ_for_procedure_export.to_a
Proc.new do |instance|
instance.send(:"spreadsheet_columns_#{format}", types_de_champ: types_de_champ)
instance.send(:"spreadsheet_columns_#{format}", types_de_champ: types_de_champ, export_template: @export_template)
end
end
end

View file

@ -14,6 +14,9 @@ describe Columns::DossierColumn do
expect(procedure.find_column(label: "Prénom").value(dossier)).to eq("Paul")
expect(procedure.find_column(label: "Nom").value(dossier)).to eq("Sim")
expect(procedure.find_column(label: "Civilité").value(dossier)).to eq("M.")
expect(procedure.find_column(label: "Dépôt pour un tiers").value(dossier)).to eq(true)
expect(procedure.find_column(label: "Nom du mandataire").value(dossier)).to eq("Christophe")
expect(procedure.find_column(label: "Prénom du mandataire").value(dossier)).to eq("Martin")
end
end
@ -22,7 +25,67 @@ describe Columns::DossierColumn do
let(:dossier) { create(:dossier, :en_instruction, :with_entreprise, procedure:) }
it 'retrieve entreprise information' do
expect(procedure.find_column(label: " dossier").value(dossier)).to eq(dossier.id)
expect(procedure.find_column(label: "Email").value(dossier)).to eq(dossier.user_email_for(:display))
expect(procedure.find_column(label: "France connecté ?").value(dossier)).to eq(false)
expect(procedure.find_column(label: "Entreprise forme juridique").value(dossier)).to eq("SA à conseil d'administration (s.a.i.)")
expect(procedure.find_column(label: "Entreprise SIREN").value(dossier)).to eq('440117620')
expect(procedure.find_column(label: "Entreprise nom commercial").value(dossier)).to eq('GRTGAZ')
expect(procedure.find_column(label: "Entreprise raison sociale").value(dossier)).to eq('GRTGAZ')
expect(procedure.find_column(label: "Entreprise SIRET siège social").value(dossier)).to eq('44011762001530')
expect(procedure.find_column(label: "Date de création").value(dossier)).to be_an_instance_of(ActiveSupport::TimeWithZone)
expect(procedure.find_column(label: "Établissement SIRET").value(dossier)).to eq('44011762001530')
expect(procedure.find_column(label: "Libellé NAF").value(dossier)).to eq('Transports par conduites')
expect(procedure.find_column(label: "Établissement code postal").value(dossier)).to eq('92270')
expect(procedure.find_column(label: "Établissement siège social").value(dossier)).to eq(true)
expect(procedure.find_column(label: "Établissement NAF").value(dossier)).to eq('4950Z')
expect(procedure.find_column(label: "Établissement Adresse").value(dossier)).to eq("GRTGAZ\r IMMEUBLE BORA\r 6 RUE RAOUL NORDLING\r 92270 BOIS COLOMBES\r")
expect(procedure.find_column(label: "Établissement numero voie").value(dossier)).to eq('6')
expect(procedure.find_column(label: "Établissement type voie").value(dossier)).to eq('RUE')
expect(procedure.find_column(label: "Établissement nom voie").value(dossier)).to eq('RAOUL NORDLING')
expect(procedure.find_column(label: "Établissement complément adresse").value(dossier)).to eq('IMMEUBLE BORA')
expect(procedure.find_column(label: "Établissement localité").value(dossier)).to eq('BOIS COLOMBES')
expect(procedure.find_column(label: "Établissement code INSEE localité").value(dossier)).to eq('92009')
expect(procedure.find_column(label: "Entreprise SIREN").value(dossier)).to eq('440117620')
expect(procedure.find_column(label: "Entreprise capital social").value(dossier)).to eq(537_100_000)
expect(procedure.find_column(label: "Entreprise numero TVA intracommunautaire").value(dossier)).to eq('FR27440117620')
expect(procedure.find_column(label: "Entreprise forme juridique code").value(dossier)).to eq('5599')
expect(procedure.find_column(label: "Entreprise code effectif entreprise").value(dossier)).to eq('51')
expect(procedure.find_column(label: "Entreprise état administratif").value(dossier)).to eq("actif")
expect(procedure.find_column(label: "Entreprise nom").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Entreprise prénom").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Association RNA").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Association titre").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Association objet").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Association date de création").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Association date de déclaration").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Association date de publication").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Date de création").value(dossier)).to be_an_instance_of(ActiveSupport::TimeWithZone)
expect(procedure.find_column(label: "Date du dernier évènement").value(dossier)).to be_an_instance_of(ActiveSupport::TimeWithZone)
expect(procedure.find_column(label: "Date de dépot").value(dossier)).to be_an_instance_of(ActiveSupport::TimeWithZone)
expect(procedure.find_column(label: "Date de passage en construction").value(dossier)).to be_an_instance_of(ActiveSupport::TimeWithZone)
expect(procedure.find_column(label: "Date de passage en instruction").value(dossier)).to be_an_instance_of(ActiveSupport::TimeWithZone)
expect(procedure.find_column(label: "Date de traitement").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "État du dossier").value(dossier)).to eq('en_instruction')
expect(procedure.find_column(label: "Archivé").value(dossier)).to eq(false)
expect(procedure.find_column(label: "Motivation de la décision").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Date de dernière modification (usager)").value(dossier)).to eq(nil)
expect(procedure.find_column(label: "Instructeurs").value(dossier)).to eq('')
end
end
context 'when procedure for entreprise which is also an association' do
let(:procedure) { create(:procedure, for_individual: false, groupe_instructeurs: [groupe_instructeur]) }
let(:etablissement) { create(:etablissement, :is_association) }
let(:dossier) { create(:dossier, :en_instruction, procedure:, etablissement:) }
it 'retrieve also association information' do
expect(procedure.find_column(label: "Association RNA").value(dossier)).to eq("W072000535")
expect(procedure.find_column(label: "Association titre").value(dossier)).to eq("ASSOCIATION POUR LA PROMOTION DE SPECTACLES AU CHATEAU DE ROCHEMAURE")
expect(procedure.find_column(label: "Association objet").value(dossier)).to eq("mise en oeuvre et réalisation de spectacles au chateau de rochemaure")
expect(procedure.find_column(label: "Association date de création").value(dossier)).to eq(Date.parse("1990-04-24"))
expect(procedure.find_column(label: "Association date de déclaration").value(dossier)).to eq(Date.parse("2014-11-28"))
expect(procedure.find_column(label: "Association date de publication").value(dossier)).to eq(Date.parse("1990-05-16"))
end
end

View file

@ -0,0 +1,206 @@
# frozen_string_literal: true
require 'csv'
describe ProcedureExportService do
let(:instructeur) { create(:instructeur) }
let(:procedure) { create(:procedure, types_de_champ_public:, for_individual:, ask_birthday: true, instructeurs: [instructeur]) }
let(:service) { ProcedureExportService.new(procedure, procedure.dossiers, instructeur, export_template) }
let(:export_template) { create(:export_template, kind:, exported_columns:, groupe_instructeur: procedure.defaut_groupe_instructeur) }
let(:for_individual) { true }
let(:types_de_champ_public) do
[
{ type: :text, libelle: "first champ", mandatory: true, stable_id: 1 },
{ type: :communes, libelle: "Commune", mandatory: true, stable_id: 17 },
{ type: :piece_justificative, libelle: "PJ", stable_id: 30 },
{
type: :repetition, mandatory: true, stable_id: 7, libelle: "Champ répétable", children:
[
{ type: 'text', libelle: 'child first champ', stable_id: 8 },
{ type: 'text', libelle: 'child second champ', stable_id: 9 }
]
}
]
end
let(:exported_columns) { [] }
describe 'to_xlsx' do
subject do
service
.to_xlsx
.open { |f| SimpleXlsxReader.open(f.path) }
end
let(:kind) { 'xlsx' }
let(:dossiers_sheet) { subject.sheets.first }
let(:etablissements_sheet) { subject.sheets.second }
let(:avis_sheet) { subject.sheets.third }
let(:repetition_sheet) { subject.sheets.fourth }
describe 'sheets' do
it 'should have a sheet for each record type' do
expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis'])
end
end
describe 'Dossiers sheet' do
let(:exported_columns) do
[
ExportedColumn.new(libelle: 'Date du dernier évènement', column: procedure.find_column(label: 'Date du dernier évènement')),
ExportedColumn.new(libelle: 'Email', column: procedure.find_column(label: 'Email')),
ExportedColumn.new(libelle: 'Groupe instructeur', column: procedure.find_column(label: 'Groupe instructeur')),
ExportedColumn.new(libelle: 'État du dossier', column: procedure.dossier_state_column),
ExportedColumn.new(libelle: 'first champ', column: procedure.find_column(label: 'first champ')),
ExportedColumn.new(libelle: 'Commune (Code INSEE)', column: procedure.find_column(label: 'Commune (Code INSEE)')),
ExportedColumn.new(libelle: 'PJ', column: procedure.find_column(label: 'PJ'))
]
end
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure) }
let(:selected_headers) { ["Email", "first champ", "Commune (Code INSEE)", "Groupe instructeur", "Date du dernier évènement", "État du dossier", "PJ"] }
it 'should have only headers from export template' do
expect(dossiers_sheet.headers).to match_array(selected_headers)
end
it 'should have data' do
expect(procedure.dossiers.count).to eq 1
expect(dossiers_sheet.data.size).to eq 1
expect(dossiers_sheet.data).to match_array([[anything, dossier.user_email_for_display, "défaut", "En instruction", "text", "60172", "toto.txt"]])
end
context 'with a procedure routee' do
let!(:dossier) { create(:dossier, :en_instruction, :with_individual, procedure:) }
before { create(:groupe_instructeur, label: '2', procedure:) }
it 'find groupe instructeur data' do
expect(dossiers_sheet.headers).to include('Groupe instructeur')
expect(dossiers_sheet.data[0][dossiers_sheet.headers.index('Groupe instructeur')]).to eq('défaut')
end
end
context 'with a dossier having multiple pjs' do
let(:procedure) { create(:procedure, :published, :for_individual, types_de_champ_public:) }
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure:) }
let!(:dossier_2) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure:) }
before do
dossier_2.filled_champs_public
.find { _1.is_a? Champs::PieceJustificativeChamp }
.piece_justificative_file
.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
end
it { expect(dossiers_sheet.data.last.last).to eq "toto.txt, toto.txt" }
end
end
describe 'Etablissement sheet' do
let(:types_de_champ_public) { [{ type: :siret, libelle: 'siret', stable_id: 40 }] }
let(:exported_columns) do
[
ExportedColumn.new(libelle: " dossier", column: procedure.find_column(label: " dossier")),
ExportedColumn.new(libelle: "Demandeur", column: procedure.find_column(label: "Demandeur")),
ExportedColumn.new(libelle: "siret", column: procedure.find_column(label: "siret"))
]
end
let(:procedure) { create(:procedure, :published, types_de_champ_public:) }
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_entreprise, procedure: procedure) }
let(:dossier_etablissement) { etablissements_sheet.data[1] }
let(:champ_etablissement) { etablissements_sheet.data[0] }
it 'should have siret header in dossiers sheet' do
expect(dossiers_sheet.headers).to include('siret')
end
it 'should have headers in etablissement sheet' do
expect(etablissements_sheet.headers).to eq([
"Dossier ID",
"Champ",
"Établissement SIRET",
"Etablissement enseigne",
"Établissement siège social",
"Établissement NAF",
"Établissement libellé NAF",
"Établissement Adresse",
"Établissement numero voie",
"Établissement type voie",
"Établissement nom voie",
"Établissement complément adresse",
"Établissement code postal",
"Établissement localité",
"Établissement code INSEE localité",
"Entreprise SIREN",
"Entreprise capital social",
"Entreprise numero TVA intracommunautaire",
"Entreprise forme juridique",
"Entreprise forme juridique code",
"Entreprise nom commercial",
"Entreprise raison sociale",
"Entreprise SIRET siège social",
"Entreprise code effectif entreprise",
"Entreprise date de création",
"Entreprise état administratif",
"Entreprise nom",
"Entreprise prénom",
"Association RNA",
"Association titre",
"Association objet",
"Association date de création",
"Association date de déclaration",
"Association date de publication"
])
end
end
describe 'Avis sheet' do
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure) }
let!(:avis) { create(:avis, :with_answer, dossier: dossier) }
it 'should have headers and data' do
expect(avis_sheet.headers).to eq([
"Dossier ID",
"Introduction",
"Réponse",
"Question",
"Réponse oui/non",
"Créé le",
"Répondu le",
"Instructeur",
"Expert"
])
expect(avis_sheet.data.size).to eq(1)
end
end
describe 'Repetitions sheet' do
let(:exported_columns) do
[
ExportedColumn.new(libelle: "Champ répétable child second champ", column: procedure.find_column(label: "Champ répétable child second champ"))
]
end
let!(:dossiers) do
[
create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure),
create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure)
]
end
describe 'sheets' do
it 'should have a sheet for repetition' do
expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', '(7) Champ repetable'])
end
end
it 'should have headers' do
expect(repetition_sheet.headers).to eq([
"Dossier ID", "Ligne", "Champ répétable child second champ"
])
end
it 'should have data' do
expect(repetition_sheet.data.size).to eq 4
end
end
end
end

View file

@ -41,7 +41,10 @@ describe 'Creating a new procedure', js: true do
click_on "Télécharger tous les dossiers"
expect {
click_on "Demander un export au format .xlsx"
within(:css, '#tabpanel-standard-panel') do
choose "Fichier xlsx", allow_label_click: true
click_on "Demander l'export"
end
expect(page).to have_content("Nous générons cet export. Veuillez revenir dans quelques minutes pour le télécharger.")
}.to have_enqueued_job(ExportJob).with(an_instance_of(Export))
end