class ProcedureExportV2Service attr_reader :dossiers def initialize(procedure, ids: nil, since: nil, limit: nil) @procedure = procedure @dossiers = procedure.dossiers.downloadable_sorted if ids @dossiers = @dossiers.where(id: ids) end if since @dossiers = @dossiers.since(since) end if limit @dossiers = @dossiers.limit(limit) end @tables = [:dossiers, :etablissements, :avis] + champs_repetables_options end def to_csv(table = :dossiers) SpreadsheetArchitect.to_csv(options_for(table)) end def to_xlsx # We recursively build multi page spreadsheet @tables.reduce(nil) do |package, table| SpreadsheetArchitect.to_axlsx_package(options_for(table), 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) 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) 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 sanitize_sheet_name(name) ActiveStorage::Filename.new(name.to_s).sanitized.truncate(30) end def options_for(table) case table when :dossiers { instances: dossiers.to_a, sheet_name: 'Dossiers' }.merge(DEFAULT_STYLES) when :etablissements { instances: etablissements.to_a, sheet_name: 'Etablissements' }.merge(DEFAULT_STYLES) 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) end end end