demarches-normaliennes/app/services/procedure_export_service.rb

94 lines
2.8 KiB
Ruby

class ProcedureExportService
attr_reader :dossiers
def initialize(procedure, dossiers)
@procedure = procedure
@dossiers = dossiers.downloadable_sorted
@tables = [:dossiers, :etablissements, :avis] + champs_repetables_options
end
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, :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, :ods), spreadsheet)
end.bytes
end
private
def etablissements
@etablissements ||= dossiers.flat_map do |dossier|
[dossier.champs, dossier.champs_private]
.flatten
.filter { |champ| champ.is_a?(Champs::SiretChamp) }
end.map(&:etablissement).compact + dossiers.map(&:etablissement).compact
end
def avis
@avis ||= dossiers.flat_map(&:avis)
end
def champs_repetables
@champs_repetables ||= dossiers.flat_map do |dossier|
[dossier.champs, dossier.champs_private]
.flatten
.filter { |champ| champ.is_a?(Champs::RepetitionChamp) }
end.group_by(&:libelle_for_export)
end
def champs_repetables_options
champs_repetables.map do |libelle, champs|
[
libelle,
champs.flat_map(&:rows_for_export)
]
end
end
DEFAULT_STYLES = {
header_style: { background_color: "000000", color: "FFFFFF", font_size: 12, bold: true },
row_style: { background_color: nil, color: "000000", font_size: 12 }
}
def options_for(table, format)
options = case table
when :dossiers
{ instances: dossiers.to_a, sheet_name: 'Dossiers', spreadsheet_columns: spreadsheet_columns(format) }
when :etablissements
{ instances: etablissements.to_a, sheet_name: 'Etablissements' }
when :avis
{ instances: avis.to_a, sheet_name: 'Avis' }
when Array
{ instances: table.last, sheet_name: table.first }
end.merge(DEFAULT_STYLES)
# transliterate: convert to ASCII characters
# to ensure truncate respects 30 bytes
# /\*?[] are invalid Excel worksheet characters
options[:sheet_name] = I18n.transliterate(options[:sheet_name], '', locale: :en)
.delete('/\*?[]')
.truncate(30, omission: '')
options
end
def spreadsheet_columns(format)
types_de_champ = @procedure.types_de_champ_for_export
types_de_champ_private = @procedure.types_de_champ_private_for_export
Proc.new do |instance|
instance.send(:"spreadsheet_columns_#{format}", types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private)
end
end
end