From 2a61ed5b1c034f2d88a9b8365a426fcafd89e2c7 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 6 Nov 2019 15:55:01 +0100 Subject: [PATCH 1/2] Export etablissement information in csv fix #4440 --- app/models/dossier.rb | 47 +++++++++- app/services/procedure_export_v2_service.rb | 12 +-- .../procedure_export_v2_service_spec.rb | 86 +++++++++++++++++++ 3 files changed, 138 insertions(+), 7 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index d7d25ad7f..466948a7a 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -472,7 +472,19 @@ class Dossier < ApplicationRecord log_dossier_operation(avis.claimant, :demander_un_avis, avis) end - def spreadsheet_columns + def spreadsheet_columns_csv + spreadsheet_columns(with_etablissement: true) + end + + def spreadsheet_columns_xlsx + spreadsheet_columns + end + + def spreadsheet_columns_ods + spreadsheet_columns + end + + def spreadsheet_columns(with_etablissement: false) columns = [ ['ID', id.to_s], ['Email', user.email] @@ -485,6 +497,39 @@ class Dossier < ApplicationRecord ['Prénom', individual&.prenom], ['Date de naissance', individual&.birthdate] ] + elsif with_etablissement + columns += [ + ['Établissement SIRET', etablissement&.siret], + ['Établissement siège social', etablissement&.siege_social], + ['Établissement NAF', etablissement&.naf], + ['Établissement libellé NAF', etablissement&.libelle_naf], + ['Établissement Adresse', etablissement&.adresse], + ['Établissement numero voie', etablissement&.numero_voie], + ['Établissement type voie', etablissement&.type_voie], + ['Établissement nom voie', etablissement&.nom_voie], + ['Établissement complément adresse', etablissement&.complement_adresse], + ['Établissement code postal', etablissement&.code_postal], + ['Établissement localité', etablissement&.localite], + ['Établissement code INSEE localité', etablissement&.code_insee_localite], + ['Entreprise SIREN', etablissement&.entreprise_siren], + ['Entreprise capital social', etablissement&.entreprise_capital_social], + ['Entreprise numero TVA intracommunautaire', etablissement&.entreprise_numero_tva_intracommunautaire], + ['Entreprise forme juridique', etablissement&.entreprise_forme_juridique], + ['Entreprise forme juridique code', etablissement&.entreprise_forme_juridique_code], + ['Entreprise nom commercial', etablissement&.entreprise_nom_commercial], + ['Entreprise raison sociale', etablissement&.entreprise_raison_sociale], + ['Entreprise SIRET siège social', etablissement&.entreprise_siret_siege_social], + ['Entreprise code effectif entreprise', etablissement&.entreprise_code_effectif_entreprise], + ['Entreprise date de création', etablissement&.entreprise_date_creation], + ['Entreprise nom', etablissement&.entreprise_nom], + ['Entreprise prénom', etablissement&.entreprise_prenom], + ['Association RNA', etablissement&.association_rna], + ['Association titre', etablissement&.association_titre], + ['Association objet', etablissement&.association_objet], + ['Association date de création', etablissement&.association_date_creation], + ['Association date de déclaration', etablissement&.association_date_declaration], + ['Association date de publication', etablissement&.association_date_publication] + ] else columns << ['Entreprise raison sociale', etablissement&.entreprise_raison_sociale] end diff --git a/app/services/procedure_export_v2_service.rb b/app/services/procedure_export_v2_service.rb index 67409b723..bef8b0ec7 100644 --- a/app/services/procedure_export_v2_service.rb +++ b/app/services/procedure_export_v2_service.rb @@ -16,21 +16,21 @@ class ProcedureExportV2Service @tables = [:dossiers, :etablissements, :avis] + champs_repetables_options end - def to_csv(table = :dossiers) - SpreadsheetArchitect.to_csv(options_for(table)) + def to_csv + SpreadsheetArchitect.to_csv(options_for(:dossiers, :csv)) end def to_xlsx # We recursively build multi page spreadsheet @tables.reduce(nil) do |package, table| - SpreadsheetArchitect.to_axlsx_package(options_for(table), package) + SpreadsheetArchitect.to_axlsx_package(options_for(table, :xlsx), package) end.to_stream.read end def to_ods # We recursively build multi page spreadsheet @tables.reduce(nil) do |spreadsheet, table| - SpreadsheetArchitect.to_rodf_spreadsheet(options_for(table), spreadsheet) + SpreadsheetArchitect.to_rodf_spreadsheet(options_for(table, :ods), spreadsheet) end.bytes end @@ -74,10 +74,10 @@ class ProcedureExportV2Service ActiveStorage::Filename.new(name.to_s).sanitized.truncate(30) end - def options_for(table) + def options_for(table, format) case table when :dossiers - { instances: dossiers.to_a, sheet_name: 'Dossiers' }.merge(DEFAULT_STYLES) + { instances: dossiers.to_a, sheet_name: 'Dossiers', spreadsheet_columns: :"spreadsheet_columns_#{format}" }.merge(DEFAULT_STYLES) when :etablissements { instances: etablissements.to_a, sheet_name: 'Etablissements' }.merge(DEFAULT_STYLES) when :avis diff --git a/spec/services/procedure_export_v2_service_spec.rb b/spec/services/procedure_export_v2_service_spec.rb index 5635c0380..932bffebf 100644 --- a/spec/services/procedure_export_v2_service_spec.rb +++ b/spec/services/procedure_export_v2_service_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'csv' describe ProcedureExportV2Service do describe 'to_data' do @@ -150,6 +151,91 @@ describe ProcedureExportV2Service do ] end + context 'as csv' do + subject do + Tempfile.create do |f| + f << ProcedureExportV2Service.new(procedure, procedure.dossiers).to_csv + f.rewind + CSV.read(f.path) + end + end + + let(:nominal_headers) do + [ + "ID", + "Email", + "Établissement SIRET", + "É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 nom", + "Entreprise prénom", + "Association RNA", + "Association titre", + "Association objet", + "Association date de création", + "Association date de déclaration", + "Association date de publication", + "Archivé", + "État du dossier", + "Dernière mise à jour le", + "Déposé le", + "Passé en instruction le", + "Traité le", + "Motivation de la décision", + "Instructeurs", + "textarea", + "date", + "datetime", + "number", + "decimal_number", + "integer_number", + "checkbox", + "civilite", + "email", + "phone", + "address", + "yes_no", + "simple_drop_down_list", + "multiple_drop_down_list", + "linked_drop_down_list", + "pays", + "regions", + "departements", + "engagement", + "dossier_link", + "piece_justificative", + "siret", + "carte", + "text" + ] + end + + let(:dossiers_sheet_headers) { subject.first } + + it 'should have headers' do + expect(dossiers_sheet_headers).to match(nominal_headers) + end + end + it 'should have headers' do expect(dossiers_sheet.headers).to match(nominal_headers) From f22b39b7c53be865970e9a693dc51f0efef976b5 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 6 Nov 2019 17:03:07 +0100 Subject: [PATCH 2/2] Handle non unique champ repetable labels fix #4466 --- app/models/champs/repetition_champ.rb | 6 ++++++ app/services/procedure_export_v2_service.rb | 9 ++------- spec/services/procedure_export_v2_service_spec.rb | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/app/models/champs/repetition_champ.rb b/app/models/champs/repetition_champ.rb index 9296dbdca..7d31812cd 100644 --- a/app/models/champs/repetition_champ.rb +++ b/app/models/champs/repetition_champ.rb @@ -33,6 +33,12 @@ class Champs::RepetitionChamp < Champ end end + # We have to truncate the label here as spreadsheets have a (30 char) limit on length. + def libelle_for_export + str = "(#{type_de_champ.stable_id}) #{libelle}" + ActiveStorage::Filename.new(str).sanitized.truncate(30) + end + class Row < Hashie::Dash property :index property :dossier_id diff --git a/app/services/procedure_export_v2_service.rb b/app/services/procedure_export_v2_service.rb index bef8b0ec7..c8ba3bffe 100644 --- a/app/services/procedure_export_v2_service.rb +++ b/app/services/procedure_export_v2_service.rb @@ -53,7 +53,7 @@ class ProcedureExportV2Service [dossier.champs, dossier.champs_private] .flatten .filter { |champ| champ.is_a?(Champs::RepetitionChamp) } - end.group_by(&:libelle) + end.group_by(&:libelle_for_export) end def champs_repetables_options @@ -70,10 +70,6 @@ class ProcedureExportV2Service row_style: { background_color: nil, color: "000000", font_size: 12 } } - def sanitize_sheet_name(name) - ActiveStorage::Filename.new(name.to_s).sanitized.truncate(30) - end - def options_for(table, format) case table when :dossiers @@ -83,8 +79,7 @@ class ProcedureExportV2Service when :avis { instances: avis.to_a, sheet_name: 'Avis' }.merge(DEFAULT_STYLES) when Array - # We have to truncate the label here as spreadsheets have a (30 char) limit on length. - { instances: table.last, sheet_name: sanitize_sheet_name(table.first) }.merge(DEFAULT_STYLES) + { instances: table.last, sheet_name: table.first }.merge(DEFAULT_STYLES) end end end diff --git a/spec/services/procedure_export_v2_service_spec.rb b/spec/services/procedure_export_v2_service_spec.rb index 932bffebf..d8c30ecd7 100644 --- a/spec/services/procedure_export_v2_service_spec.rb +++ b/spec/services/procedure_export_v2_service_spec.rb @@ -311,7 +311,7 @@ describe ProcedureExportV2Service do let(:champ_repetition) { dossiers.first.champs.find { |champ| champ.type_champ == 'repetition' } } it 'should have sheets' do - expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', champ_repetition.libelle]) + expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', champ_repetition.libelle_for_export]) end it 'should have headers' do @@ -333,7 +333,18 @@ describe ProcedureExportV2Service do end it 'should have valid sheet name' do - expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', "A - B - C"]) + expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', "(#{champ_repetition.type_de_champ.stable_id}) A - B - C"]) + end + end + + context 'with non unique labels' do + let(:dossier) { create(:dossier, :en_instruction, :with_all_champs, :for_individual, procedure: procedure) } + let(:champ_repetition) { dossier.champs.find { |champ| champ.type_champ == 'repetition' } } + let(:type_de_champ_repetition) { create(:type_de_champ_repetition, procedure: procedure, libelle: champ_repetition.libelle) } + let!(:another_champ_repetition) { create(:champ_repetition, type_de_champ: type_de_champ_repetition, dossier: dossier) } + + it 'should have sheets' do + expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', champ_repetition.libelle_for_export, another_champ_repetition.libelle_for_export]) end end end