diff --git a/app/services/demarches_publiques_export_service.rb b/app/services/demarches_publiques_export_service.rb new file mode 100644 index 000000000..1d1dfbfda --- /dev/null +++ b/app/services/demarches_publiques_export_service.rb @@ -0,0 +1,99 @@ +class DemarchesPubliquesExportService + attr_reader :io + def initialize(io) + @io = io + end + + def call + end_cursor = nil + first = true + write_array_opening + loop do + write_demarches_separator if !first + execute_query(cursor: end_cursor) + end_cursor = last_cursor + io.write(jsonify(demarches)) + first = false + break if !has_next_page? + end + write_array_closing + io.close + end + + private + + def execute_query(cursor: nil) + result = API::V2::Schema.execute(query, variables: { cursor: cursor }, context: { internal_use: true, admin: true }) + raise DemarchesPubliquesExportService::Error.new(result["errors"]) if result["errors"] + @graphql_data = result["data"] + end + + def query + "query($cursor: String) { + demarchesPubliques(after: $cursor) { + pageInfo { + endCursor + hasNextPage + } + edges { + node { + number + title + description + datePublication + service { nom organisme typeOrganisme } + cadreJuridique + deliberation + revision { + champDescriptors { + type + label + description + required + options + champDescriptors { + type + label + description + required + options + } + } + } + } + } + } + }" + end + + def last_cursor + @graphql_data["demarchesPubliques"]["pageInfo"]["endCursor"] + end + + def has_next_page? + @graphql_data["demarchesPubliques"]["pageInfo"]["hasNextPage"] + end + + def demarches + @graphql_data["demarchesPubliques"]["edges"].map { |edge| edge["node"] } + end + + def jsonify(demarches) + demarches.map(&:to_json).join(',') + end + + def write_array_opening + io.write('[') + end + + def write_array_closing + io.write(']') + end + + def write_demarches_separator + io.write(',') + end +end + +class DemarchesPubliquesExportService::Error < StandardError +end diff --git a/spec/services/demarches_publiques_export_service_spec.rb b/spec/services/demarches_publiques_export_service_spec.rb new file mode 100644 index 000000000..cbce8b9bd --- /dev/null +++ b/spec/services/demarches_publiques_export_service_spec.rb @@ -0,0 +1,45 @@ +describe DemarchesPubliquesExportService do + let(:procedure) { create(:procedure, :published, :with_service, :with_type_de_champ) } + let(:io) { StringIO.new } + + describe 'call' do + it 'generate json for all closed procedures' do + expected_result = { + number: procedure.id, + title: procedure.libelle, + description: "Demande de subvention à l'intention des associations", + service: { + nom: procedure.service.nom, + organisme: "organisme", + typeOrganisme: "association" + }, + cadreJuridique: "un cadre juridique important", + deliberation: nil, + datePublication: procedure.published_at.iso8601, + revision: { + champDescriptors: [ + { + description: procedure.types_de_champ.first.description, + label: procedure.types_de_champ.first.libelle, + options: nil, + required: false, + type: "text", + champDescriptors: nil + } + ] + } + } + + DemarchesPubliquesExportService.new(io).call + expect(JSON.parse(io.string)[0] + .deep_symbolize_keys) + .to eq(expected_result) + end + it 'raises exception when procedure with bad data' do + procedure.libelle = nil + procedure.save(validate: false) + + expect { DemarchesPubliquesExportService.new(io).call }.to raise_error(DemarchesPubliquesExportService::Error) + end + end +end