2019-06-25 15:46:10 +02:00
|
|
|
require 'csv'
|
2018-11-22 00:14:16 +01:00
|
|
|
|
|
|
|
describe ProcedureExportService do
|
|
|
|
describe 'to_data' do
|
2019-06-25 15:46:10 +02:00
|
|
|
let(:procedure) { create(:procedure, :published, :for_individual, :with_all_champs) }
|
|
|
|
subject do
|
2022-04-08 17:12:34 +02:00
|
|
|
ProcedureExportService.new(procedure, procedure.dossiers)
|
|
|
|
.to_xlsx
|
|
|
|
.open { |f| SimpleXlsxReader.open(f.path) }
|
2019-06-25 15:46:10 +02:00
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02: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 }
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2018-12-10 15:33:34 +01:00
|
|
|
before do
|
|
|
|
# change one tdc place to check if the header is ordered
|
2020-08-27 19:57:21 +02:00
|
|
|
tdc_first = procedure.active_revision.revision_types_de_champ.first
|
|
|
|
tdc_last = procedure.active_revision.revision_types_de_champ.last
|
2018-12-10 15:33:34 +01:00
|
|
|
|
2020-08-27 19:57:21 +02:00
|
|
|
tdc_first.update(position: tdc_last.position + 1)
|
2018-12-20 12:00:27 +01:00
|
|
|
procedure.reload
|
2018-12-10 15:33:34 +01:00
|
|
|
end
|
|
|
|
|
2020-05-13 15:57:40 +02:00
|
|
|
describe 'sheets' do
|
|
|
|
it 'should have a sheet for each record type' do
|
2019-06-25 15:46:10 +02:00
|
|
|
expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis'])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-13 15:57:40 +02:00
|
|
|
describe 'Dossiers sheet' do
|
2021-11-03 15:52:53 +01:00
|
|
|
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure) }
|
2019-06-25 15:46:10 +02:00
|
|
|
|
|
|
|
let(:nominal_headers) do
|
2019-09-18 17:52:02 +02:00
|
|
|
[
|
2019-06-25 15:46:10 +02:00
|
|
|
"ID",
|
|
|
|
"Email",
|
|
|
|
"Civilité",
|
|
|
|
"Nom",
|
|
|
|
"Prénom",
|
|
|
|
"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",
|
2020-01-14 18:46:07 +01:00
|
|
|
"communes",
|
2021-08-18 14:13:10 +02:00
|
|
|
"communes (Code insee)",
|
2019-06-25 15:46:10 +02:00
|
|
|
"engagement",
|
|
|
|
"dossier_link",
|
|
|
|
"piece_justificative",
|
|
|
|
"siret",
|
|
|
|
"carte",
|
2020-09-17 17:09:16 +02:00
|
|
|
"titre_identite",
|
2020-09-22 16:04:57 +02:00
|
|
|
"iban",
|
2021-01-14 17:29:57 +01:00
|
|
|
"annuaire_education",
|
2021-09-24 14:21:13 +02:00
|
|
|
"cnaf",
|
2021-11-24 17:30:35 +01:00
|
|
|
"dgfip",
|
2021-12-01 10:21:30 +01:00
|
|
|
"pole_emploi",
|
2021-12-15 15:25:02 +01:00
|
|
|
"mesri",
|
2019-06-25 15:46:10 +02:00
|
|
|
"text"
|
2019-09-18 17:52:02 +02:00
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have headers' do
|
2019-06-25 15:46:10 +02:00
|
|
|
expect(dossiers_sheet.headers).to match(nominal_headers)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have data' do
|
|
|
|
expect(dossiers_sheet.data.size).to eq(1)
|
|
|
|
expect(etablissements_sheet.data.size).to eq(1)
|
|
|
|
|
|
|
|
# SimpleXlsxReader is transforming datetimes in utc... It is only used in test so we just hack around.
|
2021-12-06 15:49:17 +01:00
|
|
|
offset = dossier.depose_at.utc_offset
|
|
|
|
depose_at = Time.zone.at(dossiers_sheet.data[0][8] - offset.seconds)
|
2020-05-13 15:57:56 +02:00
|
|
|
en_instruction_at = Time.zone.at(dossiers_sheet.data[0][9] - offset.seconds)
|
2021-12-06 15:49:17 +01:00
|
|
|
expect(depose_at).to eq(dossier.depose_at.round)
|
2019-06-25 15:46:10 +02:00
|
|
|
expect(en_instruction_at).to eq(dossier.en_instruction_at.round)
|
2019-09-18 17:52:02 +02:00
|
|
|
end
|
|
|
|
|
2020-05-13 15:57:56 +02:00
|
|
|
context 'with a birthdate' do
|
|
|
|
before { procedure.update(ask_birthday: true) }
|
|
|
|
|
|
|
|
let(:birthdate_headers) { nominal_headers.insert(nominal_headers.index('Archivé'), 'Date de naissance') }
|
|
|
|
|
|
|
|
it { expect(dossiers_sheet.headers).to match(birthdate_headers) }
|
|
|
|
it { expect(dossiers_sheet.data[0][dossiers_sheet.headers.index('Date de naissance')]).to be_a(Date) }
|
|
|
|
end
|
|
|
|
|
2019-09-18 17:52:02 +02:00
|
|
|
context 'with a procedure routee' do
|
|
|
|
before { procedure.groupe_instructeurs.create(label: '2') }
|
|
|
|
|
2020-05-13 15:57:40 +02:00
|
|
|
let(:routee_headers) { nominal_headers.insert(nominal_headers.index('textarea'), 'Groupe instructeur') }
|
2019-09-18 17:52:02 +02:00
|
|
|
|
2020-05-13 15:57:40 +02:00
|
|
|
it { expect(dossiers_sheet.headers).to match(routee_headers) }
|
2019-06-25 15:46:10 +02:00
|
|
|
it { expect(dossiers_sheet.data[0][dossiers_sheet.headers.index('Groupe instructeur')]).to eq('défaut') }
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
2019-06-25 15:46:10 +02:00
|
|
|
end
|
|
|
|
|
2020-05-13 15:57:40 +02:00
|
|
|
describe 'Etablissement sheet' do
|
2019-06-25 15:46:10 +02:00
|
|
|
let(:procedure) { create(:procedure, :published, :with_all_champs) }
|
2021-11-03 15:52:53 +01:00
|
|
|
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_entreprise, procedure: procedure) }
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
let(:dossier_etablissement) { etablissements_sheet.data[1] }
|
|
|
|
let(:champ_etablissement) { etablissements_sheet.data[0] }
|
|
|
|
|
|
|
|
let(:nominal_headers) do
|
|
|
|
[
|
|
|
|
"ID",
|
|
|
|
"Email",
|
|
|
|
"Entreprise raison sociale",
|
|
|
|
"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",
|
2020-01-14 18:46:07 +01:00
|
|
|
"communes",
|
2021-08-18 14:13:10 +02:00
|
|
|
"communes (Code insee)",
|
2019-06-25 15:46:10 +02:00
|
|
|
"engagement",
|
|
|
|
"dossier_link",
|
|
|
|
"piece_justificative",
|
|
|
|
"siret",
|
|
|
|
"carte",
|
2020-09-17 17:09:16 +02:00
|
|
|
"titre_identite",
|
2020-09-22 16:04:57 +02:00
|
|
|
"iban",
|
2021-01-14 17:29:57 +01:00
|
|
|
"annuaire_education",
|
2021-09-24 14:21:13 +02:00
|
|
|
"cnaf",
|
2021-11-24 17:30:35 +01:00
|
|
|
"dgfip",
|
2021-12-01 10:21:30 +01:00
|
|
|
"pole_emploi",
|
2021-12-15 15:25:02 +01:00
|
|
|
"mesri",
|
2019-06-25 15:46:10 +02:00
|
|
|
"text"
|
|
|
|
]
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
context 'as csv' do
|
|
|
|
subject do
|
2022-04-08 17:12:34 +02:00
|
|
|
ProcedureExportService.new(procedure, procedure.dossiers)
|
|
|
|
.to_csv
|
|
|
|
.open { |f| CSV.read(f.path) }
|
2019-06-25 15:46:10 +02:00
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
let(:nominal_headers) do
|
2018-11-22 00:14:16 +01:00
|
|
|
[
|
2019-06-25 15:46:10 +02:00
|
|
|
"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",
|
2020-01-14 18:46:07 +01:00
|
|
|
"communes",
|
2021-08-18 14:13:10 +02:00
|
|
|
"communes (Code insee)",
|
2019-06-25 15:46:10 +02:00
|
|
|
"engagement",
|
|
|
|
"dossier_link",
|
|
|
|
"piece_justificative",
|
|
|
|
"siret",
|
|
|
|
"carte",
|
2020-09-17 17:09:16 +02:00
|
|
|
"titre_identite",
|
2020-09-22 16:04:57 +02:00
|
|
|
"iban",
|
2021-01-14 17:29:57 +01:00
|
|
|
"annuaire_education",
|
2021-09-24 14:21:13 +02:00
|
|
|
"cnaf",
|
2021-11-24 17:30:35 +01:00
|
|
|
"dgfip",
|
2021-12-01 10:21:30 +01:00
|
|
|
"pole_emploi",
|
2021-12-15 15:25:02 +01:00
|
|
|
"mesri",
|
2019-06-25 15:46:10 +02:00
|
|
|
"text"
|
2018-11-22 00:14:16 +01:00
|
|
|
]
|
2019-06-25 15:46:10 +02:00
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
let(:dossiers_sheet_headers) { subject.first }
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
it 'should have headers' do
|
|
|
|
expect(dossiers_sheet_headers).to match(nominal_headers)
|
|
|
|
end
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
it 'should have headers' do
|
|
|
|
expect(dossiers_sheet.headers).to match(nominal_headers)
|
|
|
|
|
|
|
|
expect(etablissements_sheet.headers).to eq([
|
|
|
|
"Dossier ID",
|
|
|
|
"Champ",
|
|
|
|
"Établissement SIRET",
|
2020-08-20 10:21:34 +02:00
|
|
|
"Etablissement enseigne",
|
2019-06-25 15:46:10 +02:00
|
|
|
"É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"
|
|
|
|
])
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
it 'should have data' do
|
|
|
|
expect(etablissements_sheet.data.size).to eq(2)
|
|
|
|
expect(dossier_etablissement[1]).to eq("Dossier")
|
|
|
|
expect(champ_etablissement[1]).to eq("siret")
|
|
|
|
end
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2020-05-13 15:57:40 +02:00
|
|
|
describe 'Avis sheet' do
|
2021-11-03 15:52:53 +01:00
|
|
|
let!(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure) }
|
2019-06-25 15:46:10 +02:00
|
|
|
let!(:avis) { create(:avis, :with_answer, dossier: dossier) }
|
2019-09-18 17:52:02 +02:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
it 'should have headers' do
|
|
|
|
expect(avis_sheet.headers).to eq([
|
|
|
|
"Dossier ID",
|
|
|
|
"Question / Introduction",
|
|
|
|
"Réponse",
|
|
|
|
"Créé le",
|
2020-01-28 12:42:30 +01:00
|
|
|
"Répondu le",
|
|
|
|
"Instructeur",
|
|
|
|
"Expert"
|
2019-06-25 15:46:10 +02:00
|
|
|
])
|
|
|
|
end
|
2019-09-18 17:52:02 +02:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
it 'should have data' do
|
|
|
|
expect(avis_sheet.data.size).to eq(1)
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-13 15:57:40 +02:00
|
|
|
describe 'Repetitions sheet' do
|
2019-06-25 15:46:10 +02:00
|
|
|
let!(:dossiers) do
|
|
|
|
[
|
2021-11-03 15:52:53 +01:00
|
|
|
create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure),
|
|
|
|
create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure)
|
2019-06-25 15:46:10 +02:00
|
|
|
]
|
|
|
|
end
|
|
|
|
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_for_export])
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2021-11-10 20:45:32 +01:00
|
|
|
context 'with cloned procedure' do
|
|
|
|
let(:other_parent) { create(:type_de_champ_repetition, stable_id: champ_repetition.stable_id) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
create(:procedure_revision_type_de_champ, type_de_champ: other_parent, revision: create(:procedure).active_revision)
|
|
|
|
create(:type_de_champ, parent: other_parent)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have headers' do
|
|
|
|
expect(repetition_sheet.headers).to eq([
|
|
|
|
"Dossier ID",
|
|
|
|
"Ligne",
|
|
|
|
"Nom",
|
|
|
|
"Age"
|
|
|
|
])
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
it 'should have data' do
|
|
|
|
expect(repetition_sheet.data.size).to eq(4)
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
context 'with invalid characters' do
|
|
|
|
before do
|
2020-01-29 11:33:28 +01:00
|
|
|
champ_repetition.type_de_champ.update(libelle: 'A / B \ C *[]?')
|
2019-06-25 15:46:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have valid sheet name' do
|
|
|
|
expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', "(#{champ_repetition.type_de_champ.stable_id}) A - B - C"])
|
|
|
|
end
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2020-09-29 14:01:27 +02:00
|
|
|
context 'with long libelle composed of utf8 characteres' do
|
2020-09-24 14:24:53 +02:00
|
|
|
before do
|
|
|
|
procedure.types_de_champ.each do |c|
|
2020-09-29 17:29:36 +02:00
|
|
|
c.update!(libelle: "#{c.id} - ?/[] ééé ééé ééééééé ééééééé éééééééé. ééé éé éééééééé éé ééé. ééééé éééééééé ééé ééé.")
|
2020-09-24 14:24:53 +02:00
|
|
|
end
|
|
|
|
champ_repetition.champs.each do |c|
|
|
|
|
c.type_de_champ.update!(libelle: "#{c.id} - Quam rem nam maiores numquam dolorem nesciunt. Cum et possimus et aut. Fugit voluptas qui qui.")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have valid sheet name' do
|
2021-02-04 12:38:02 +01:00
|
|
|
expect { subject }.not_to raise_error
|
2020-09-24 14:24:53 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
context 'with non unique labels' do
|
2021-11-03 15:52:53 +01:00
|
|
|
let(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure) }
|
2019-06-25 15:46:10 +02:00
|
|
|
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) }
|
2018-11-22 00:14:16 +01:00
|
|
|
|
2019-06-25 15:46:10 +02:00
|
|
|
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])
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|