demarches-normaliennes/spec/services/procedure_export_service_tabular_spec.rb

283 lines
13 KiB
Ruby
Raw Permalink Normal View History

# 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' }
let(:export_template) { create(:export_template, kind:, exported_columns:, groupe_instructeur: procedure.defaut_groupe_instructeur) }
let(:dossiers_sheet) { subject.sheets.first }
let(:etablissements_sheet) { subject.sheets.second }
let(:avis_sheet) { subject.sheets.third }
let(:repetition_sheet) { subject.sheets.fourth }
subject do
service
.to_xlsx
.open { |f| SimpleXlsxReader.open(f.path) }
end
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
context 'with multiple columns' 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', column: procedure.find_column(label: 'Commune')),
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", "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", "Coye-la-Forêt", "toto.txt"]])
end
end
context 'with multiple groupe instructeur' do
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
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 multiple pjs' do
let(:types_de_champ_public) { [{ type: :piece_justificative, libelle: "PJ" }] }
let(:exported_columns) { [ExportedColumn.new(libelle: 'PJ', column: procedure.find_column(label: 'PJ'))] }
before do
dossier = create(:dossier, :en_instruction, :with_populated_champs, procedure:)
dossier.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
context 'with TypeDeChamp::MutlipleDropDownListTypeDeChamp' do
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
context 'with TypeDeChamp:YesNoTypeDeChamp' do
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
context 'with TypeDeChamp:CheckboxTypeDeChamp' do
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
context 'with TypeDeChamp:DecimalNumberTypeDeChamp' do
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
context 'with TypeDeChamp:IntegerNumberTypeDeChamp' do
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
context 'with 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
context 'with TypesDeChamp::DateTimeTypeDeChamp' do
let(:types_de_champ_public) { [{ type: :datetime, libelle: "datetime", mandatory: true }] }
let(:exported_columns) { [ExportedColumn.new(libelle: 'datetime', column: procedure.find_column(label: 'datetime'))] }
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
before { dossier }
it do
champ_value = Time.zone.parse(dossier.champs.first.value)
offset = champ_value.utc_offset
sheet_value = Time.zone.at(dossiers_sheet.data.last.last - offset.seconds)
expect(sheet_value).to eq(champ_value.round)
end
end
context 'with TypesDeChamp::Date' do
let(:types_de_champ_public) { [{ type: :date, libelle: "date", mandatory: true }] }
let(:exported_columns) { [ExportedColumn.new(libelle: 'date', column: procedure.find_column(label: 'date'))] }
before { create(:dossier, :with_populated_champs, procedure:) }
it { expect(dossiers_sheet.data.last.last).to be_an_instance_of(Date) }
end
context 'with DossierColumn as datetime' do
let(:types_de_champ_public) { [] }
let(:exported_columns) { [ExportedColumn.new(libelle: 'Date de passage en instruction', column: procedure.find_column(label: 'Date de passage en instruction'))] }
before { create(:dossier, :en_instruction, :with_populated_champs, procedure:) }
it { expect(dossiers_sheet.data.last.last).to be_an_instance_of(Time) }
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