2024-11-04 17:00:25 +01:00
|
|
|
|
# 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(: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
|
|
|
|
|
let(:kind) { 'xlsx' }
|
2024-11-14 09:12:25 +01:00
|
|
|
|
let(:export_template) { create(:export_template, kind:, exported_columns:, groupe_instructeur: procedure.defaut_groupe_instructeur) }
|
2024-11-04 17:00:25 +01:00
|
|
|
|
let(:dossiers_sheet) { subject.sheets.first }
|
|
|
|
|
let(:etablissements_sheet) { subject.sheets.second }
|
|
|
|
|
let(:avis_sheet) { subject.sheets.third }
|
|
|
|
|
let(:repetition_sheet) { subject.sheets.fourth }
|
|
|
|
|
|
2024-11-14 09:12:25 +01:00
|
|
|
|
subject do
|
|
|
|
|
service
|
|
|
|
|
.to_xlsx
|
|
|
|
|
.open { |f| SimpleXlsxReader.open(f.path) }
|
|
|
|
|
end
|
|
|
|
|
|
2024-11-04 17:00:25 +01:00
|
|
|
|
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
|
2024-11-14 09:55:10 +01:00
|
|
|
|
context 'with multiple columns' do
|
2024-11-04 17:01:36 +01:00
|
|
|
|
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')),
|
2024-11-12 17:03:31 +01:00
|
|
|
|
ExportedColumn.new(libelle: 'Commune', column: procedure.find_column(label: 'Commune')),
|
2024-11-04 17:01:36 +01:00
|
|
|
|
ExportedColumn.new(libelle: 'PJ', column: procedure.find_column(label: 'PJ'))
|
|
|
|
|
]
|
|
|
|
|
end
|
2024-11-04 17:00:25 +01:00
|
|
|
|
|
2024-11-04 17:01:36 +01:00
|
|
|
|
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure) }
|
2024-11-12 17:03:31 +01:00
|
|
|
|
let(:selected_headers) { ["Email", "first champ", "Commune", "Groupe instructeur", "Date du dernier évènement", "État du dossier", "PJ"] }
|
2024-11-04 17:00:25 +01:00
|
|
|
|
|
2024-11-04 17:01:36 +01:00
|
|
|
|
it 'should have only headers from export template' do
|
|
|
|
|
expect(dossiers_sheet.headers).to match_array(selected_headers)
|
|
|
|
|
end
|
2024-11-04 17:00:25 +01:00
|
|
|
|
|
2024-11-04 17:01:36 +01:00
|
|
|
|
it 'should have data' do
|
|
|
|
|
expect(procedure.dossiers.count).to eq 1
|
|
|
|
|
expect(dossiers_sheet.data.size).to eq 1
|
2024-11-04 17:00:25 +01:00
|
|
|
|
|
2024-11-12 17:03:31 +01:00
|
|
|
|
expect(dossiers_sheet.data).to match_array([[anything, dossier.user_email_for_display, "défaut", "En instruction", "text", "Coye-la-Forêt", "toto.txt"]])
|
2024-11-04 17:01:36 +01:00
|
|
|
|
end
|
2024-11-04 17:00:25 +01:00
|
|
|
|
end
|
|
|
|
|
|
2024-11-14 09:55:10 +01:00
|
|
|
|
context 'with multiple groupe instructeur' do
|
2024-11-04 17:01:36 +01:00
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'Groupe instructeur', column: procedure.find_column(label: 'Groupe instructeur'))] }
|
|
|
|
|
let(:types_de_champ_public) { [] }
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
create(:groupe_instructeur, label: '2', procedure:)
|
|
|
|
|
create(:dossier, :en_instruction, procedure:)
|
|
|
|
|
end
|
2024-11-04 17:00:25 +01:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2024-11-14 09:55:10 +01:00
|
|
|
|
context 'with multiple pjs' do
|
2024-11-04 17:01:36 +01:00
|
|
|
|
let(:types_de_champ_public) { [{ type: :piece_justificative, libelle: "PJ" }] }
|
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'PJ', column: procedure.find_column(label: 'PJ'))] }
|
2024-11-04 17:00:25 +01:00
|
|
|
|
before do
|
2024-11-04 17:01:36 +01:00
|
|
|
|
dossier = create(:dossier, :en_instruction, :with_populated_champs, procedure:)
|
|
|
|
|
dossier.filled_champs_public
|
2024-11-04 17:00:25 +01:00
|
|
|
|
.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
|
2024-11-04 17:01:36 +01:00
|
|
|
|
|
2024-11-14 09:55:10 +01:00
|
|
|
|
context 'with TypeDeChamp::MutlipleDropDownListTypeDeChamp' do
|
2024-11-04 17:01:36 +01:00
|
|
|
|
let(:types_de_champ_public) { [{ type: :multiple_drop_down_list, libelle: "multiple_drop_down_list", mandatory: true }] }
|
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'Date du dernier évènement', column: procedure.find_column(label: 'multiple_drop_down_list'))] }
|
|
|
|
|
before { create(:dossier, :with_populated_champs, procedure:) }
|
|
|
|
|
it { expect(dossiers_sheet.data.last.last).to eq "val1, val2" }
|
|
|
|
|
end
|
2024-11-14 09:12:25 +01:00
|
|
|
|
|
2024-11-14 09:55:10 +01:00
|
|
|
|
context 'with TypeDeChamp:YesNoTypeDeChamp' do
|
2024-11-14 09:12:25 +01:00
|
|
|
|
let(:types_de_champ_public) { [{ type: :yes_no, libelle: "yes_no", mandatory: true }] }
|
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'yes_no', column: procedure.find_column(label: 'yes_no'))] }
|
|
|
|
|
before { create(:dossier, :with_populated_champs, procedure:) }
|
|
|
|
|
it { expect(dossiers_sheet.data.last.last).to eq true }
|
|
|
|
|
end
|
|
|
|
|
|
2024-11-14 09:55:10 +01:00
|
|
|
|
context 'with TypeDeChamp:CheckboxTypeDeChamp' do
|
2024-11-14 09:12:25 +01:00
|
|
|
|
let(:types_de_champ_public) { [{ type: :checkbox, libelle: "checkbox", mandatory: true }] }
|
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'checkbox', column: procedure.find_column(label: 'checkbox'))] }
|
|
|
|
|
before { create(:dossier, :with_populated_champs, procedure:) }
|
|
|
|
|
it { expect(dossiers_sheet.data.last.last).to eq true }
|
|
|
|
|
end
|
|
|
|
|
|
2024-11-14 09:55:10 +01:00
|
|
|
|
context 'with TypeDeChamp:DecimalNumberTypeDeChamp' do
|
2024-11-14 09:12:25 +01:00
|
|
|
|
let(:types_de_champ_public) { [{ type: :decimal_number, libelle: "decimal", mandatory: true }] }
|
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'decimal', column: procedure.find_column(label: 'decimal'))] }
|
|
|
|
|
before { create(:dossier, :with_populated_champs, procedure:) }
|
|
|
|
|
it { expect(dossiers_sheet.data.last.last).to eq 42.1 }
|
|
|
|
|
end
|
2024-11-14 09:55:10 +01:00
|
|
|
|
|
|
|
|
|
context 'with TypeDeChamp:IntegerNumberTypeDeChamp' do
|
2024-11-14 09:12:25 +01:00
|
|
|
|
let(:types_de_champ_public) { [{ type: :integer_number, libelle: "integer", mandatory: true }] }
|
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'integer', column: procedure.find_column(label: 'integer'))] }
|
|
|
|
|
before { create(:dossier, :with_populated_champs, procedure:) }
|
|
|
|
|
it { expect(dossiers_sheet.data.last.last).to eq 42.0 }
|
|
|
|
|
end
|
2024-11-14 09:55:10 +01:00
|
|
|
|
|
|
|
|
|
context 'with having TypesDeChamp::LinkedDropDownListTypeDeChamp' do
|
|
|
|
|
let(:types_de_champ_public) { [{ type: :linked_drop_down_list, libelle: "linked_drop_down_list", mandatory: true }] }
|
|
|
|
|
let(:exported_columns) { [ExportedColumn.new(libelle: 'linked_drop_down_list', column: procedure.find_column(label: 'linked_drop_down_list'))] }
|
|
|
|
|
before { create(:dossier, :with_populated_champs, procedure:) }
|
|
|
|
|
it { expect(dossiers_sheet.data.last.last).to eq "primary / secondary" }
|
|
|
|
|
end
|
2024-11-04 17:00:25 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
describe 'Etablissement sheet' do
|
|
|
|
|
let(:types_de_champ_public) { [{ type: :siret, libelle: 'siret', stable_id: 40 }] }
|
|
|
|
|
let(:exported_columns) do
|
|
|
|
|
[
|
|
|
|
|
ExportedColumn.new(libelle: "Nº dossier", column: procedure.find_column(label: "Nº 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
|