module Ecoportal module API class V1 # @attr id [String] the internal unique id of this person (unique in all the system). # @attr external_id [String] the alternative unique id of this person (unique in one organization). # @attr name [String] the name of the person. # @attr supervisor_id [String] internal or external id of the supervisor of this person. # @attr_reader subordinates [Integer] the number of people this person is supervisor of. # @attr details [PersonDetails, nil] the details of the person or `nil` if missing. class Person < Common::BaseModel passthrough :id, :external_id, :name, :email, :supervisor_id, :subordinates, :filter_tags, :freemium class_resolver :person_schema_class, "Ecoportal::API::V1::PersonSchema" class_resolver :person_details_class, "Ecoportal::API::V1::PersonDetails" embeds_one :details, nullable: true, klass: :person_details_class VALID_TAG_REGEX = /^[A-Za-z0-9 &_'\/-]+$/ # Gets the supervisor (`Person`) of this person, with given his `supervisor_id`. # # **Example Usage**: # ```ruby # API_KEY = 'some-private-api-key-version' # HOST = "live.ecoportal.com" # api = Ecoportal::API::Internal.new(API_KEY, host: HOST) # person = api.people.get({"id": "my-dummy-user"}) # super = person.supervisor(api.client) # pp "#{person.name}'s supervisor is #{super.name}." # ``` # # @param client [Common::Client] the api client to make the request. def supervisor(client) return @supervisor if defined?(@supervisor) return @supervisor = nil if supervisor_id.nil? @supervisor = client.people.get(supervisor_id).result end # Sets the supervisor of a person. # @param person [Person, nil] the supervisor of this person. def supervisor=(person) self.supervisor_id = person&.id || person&.external_id end # Validates the string tags of the array, and sets the `filter_tags` property of the account. # @note all is set in upper case. # @raise [Exception] if there was any invalid string tag. # @param value [Array] array of tags. def filter_tags=(value) unless value.is_a?(Array) raise "filter_tags= needs to be passed an Array, got #{value.class}" end end_tags = value.map do |tag| unless tag.match(VALID_TAG_REGEX) raise "Invalid filter tag #{tag.inspect}" end tag.upcase end ini_tags = (original_doc && original_doc["filter_tags"]) || [] # preserve original order to avoid false updates doc["filter_tags"] = (ini_tags & end_tags) + (end_tags - ini_tags) end def as_json super.merge "details" => details&.as_json end # Sets the PersonDetails to the person, depending on the paramter received: # - `nil`: blanks the details. # - `PersonDetails`: sets a copy of the object param as details. # - `Hash`: sets respectivelly the `schema_id` and the `fields` keys of the Hash to the person details. # @note unique point of access to update the PersonDetails. # @param value [nil, PersonDetails, Hash] value to be set. # @return [nil, PersonDetails] the resulting `PersonDetails` set to the person. def details=(value) case value when NilClass doc["details"] = nil when person_details_class doc["details"] = value.as_json when Hash doc["details"] = value.slice("schema_id", "fields") else raise "Invalid type set on details. Required nil, PersonDetails or Hash; got #{value.class}" end remove_instance_variable("@details") if defined?(@details) end # Sets the PersonDetails to the person, depending on the parameter received: # - `PersonSchema`: initializes the `PersonDetails` as per the schema specified (`schema_id` and `fields`). # - `String`: it just sets the `schema_id` on the `PersonDetails` (as `fields` is not include, `details[key]=` will throw error). # (see #details=) # @note # - this method alone only sets the internal structure of the details. # - you will not be able to `reset!` after using this method. # @param schema_or_id [PersonSchema, String, nil, PersonDetails, Hash] value to be set. # @return [nil, PersonDetails] the resulting `PersonDetails` that set to the person. def add_details(schema_or_id) person_details_class.new.tap do |new_details| case schema_or_id when person_schema_class schema_or_id.initialize_details(new_details) when String new_details.schema_id = schema_or_id else raise "Invalid set on details: Requierd PersonSchema or String; got #{schema_or_id.class}" end self.details = new_details # Patch out static data from as_update original_doc["details"] = { "fields" => JSON.parse(doc["details"]["fields"].to_json) } end end end end end end