module Ecoportal module API class V1 # @attr_reader client [Common::Client] a `Common::Client` object that # holds the configuration of the api connection. class People extend Common::BaseClass include Common::DocHelpers include Enumerable class_resolver :person_class, "Ecoportal::API::V1::Person" attr_reader :client # @param client [Common::Client] a `Common::Client` object that holds the configuration of the api connection. # @return [People] an instance object ready to make people api requests. def initialize(client) @client = client end # Iterates all the people of the organization. # @note # - it ignores the key `cursor_id:` of `params:`. # - `each` is called by `to_a` # @param params [Hash] # @option params [String] :per_page the number of people you get per request. # @option params [String] :q some text to search. Omit this parameter to target all the people. # @param silent [Boolean] `false` to show percentage of progress. # @yield [person] does some stuff with the person. # @yieldparam person [Person] def each(params: {}, silent: false) # rubocop:disable Metrics/AbcSize return to_enum(:each, params: params, silent: silent) unless block_given? cursor_id = nil results = 0 puts "\n" unless silent loop do params.update(cursor_id: cursor_id) if cursor_id body = nil response = nil count = 5 loop do response = client.get("/people", params: params) body = response && body_data(response.body) break if response.success? || count <= 0 puts "Request failed - Status #{response.status}: #{body}" count -= 1 sleep(0.5) end raise "Request failed - Status #{response.status}: #{body}" unless response.success? unless silent || (total = body["total_results"])&.zero? results += body["results"].length percent = results * 100 / total msg = "People GET" msg << " (search=#{params[:q]})" if params.key?(:q) print "#{msg}: #{percent.round}% (of #{total}): #{results}\r" $stdout.flush end body["results"].each do |person| yield person_class.new(person) end break unless (cursor_id = body["cursor_id"]) end self end # Gets all the people via api requests. # @note it ignores the key `:cursor_id` in `params:`. # @param params [Hash] # @option params [Integer] :per_page the number of people you get per request. # @option params [String] :q some text to search. # @param silent [Boolean] `false` to show percentage of progress. # @return [Array] the array of people got via api. def get_all(params: {}, silent: false) each(params: params, silent: silent).to_a end # Gets a person via api. # @note if the request has `success?` the returned `object.result` gives an object with that `Person`. # @param doc [String, Hash, Person] data containing an `id` (internal or external) of the target person. # @return [Person] the person with `id` (internal or external) contained in `doc`. def get(doc) id = get_id(doc) response = client.get("/people/#{CGI.escape(id)}") body = body_data(response.body) return person_class.new(body) if response.success? raise "Could not get person #{id} - Error #{response.status}: #{body}" end # Requests an update of a person via api. # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person. # @return [Response] an object with the api response. def update(doc) body = get_body(doc) id = get_id(doc) client.patch("/people/#{CGI.escape(id)}", data: body) end # Requests to create a person via api. # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person. # @return [Response] an object with the api response. def create(doc) body = get_body(doc) client.post("/people", data: body) end # Requests to update an existing person or if it does not exist, to create it, via api. # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person. # @return [Response] an object with the api response. def upsert(doc) body = get_body(doc) id = get_id(doc) client.post("/people/#{CGI.escape(id)}", data: body) end # Requests to completelly remove from an organization an existing person via api. # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person. # @return [Response] an object with the api response. def delete(doc) id = get_id(doc) client.delete("/people/#{CGI.escape(id)}") end # Creates a `BatchOperation` and yields it to the given bock. # @yield [batch_op] adds multiple api requests for the current batch. # @yieldparam batch_op [BatchOperation] # @param job_mode [Boolean] whether or not it should use batch jobs # @return [Ecoportal::API::Common::Response] the results of the batch def batch(job_mode: true, &block) return job.batch(&block) if job_mode operation = Common::BatchOperation.new( "/people", person_class, logger: client.logger ) yield operation # The batch operation is responsible for logging the output client.post("/people/batch", data: operation.as_json).tap do |response| operation.process_response(response) end end # @return [Ecoportal::API::V1::Job] def job(preserve_stats: true) return @last_job = Job.new(client, person_class: person_class) unless preserve_stats && @last_job @last_job = @last_job.new end # Creates a new `Person` object. # @return [Person] new empty person object of the current version. def new person_class.new end private # Hook for other api versions to obtain the raw data of a response # @note this was introduced to allow `v2` to reuse this class def body_data(body) body end end end end end require 'ecoportal/api/v1/schema_field_value' require 'ecoportal/api/v1/person_details' require 'ecoportal/api/v1/person' require 'ecoportal/api/v1/job'