Class: Eco::API::MicroCases

Inherits:
Common::Session::BaseSession show all
Defined in:
lib/eco/api/microcases.rb,
lib/eco/api/microcases/set_core.rb,
lib/eco/api/microcases/with_each.rb,
lib/eco/api/microcases/people_load.rb,
lib/eco/api/microcases/set_account.rb,
lib/eco/api/microcases/people_cache.rb,
lib/eco/api/microcases/core_excluded.rb,
lib/eco/api/microcases/people_search.rb,
lib/eco/api/microcases/person_update.rb,
lib/eco/api/microcases/strict_search.rb,
lib/eco/api/microcases/people_refresh.rb,
lib/eco/api/microcases/set_supervisor.rb,
lib/eco/api/microcases/fix_filter_tags.rb,
lib/eco/api/microcases/with_supervisor.rb,
lib/eco/api/microcases/account_excluded.rb,
lib/eco/api/microcases/s3upload_targets.rb,
lib/eco/api/microcases/with_each_leaver.rb,
lib/eco/api/microcases/append_usergroups.rb,
lib/eco/api/microcases/fix_default_group.rb,
lib/eco/api/microcases/with_each_present.rb,
lib/eco/api/microcases/with_each_starter.rb,
lib/eco/api/microcases/refresh_default_tag.rb,
lib/eco/api/microcases/preserve_default_tag.rb,
lib/eco/api/microcases/preserve_filter_tags.rb,
lib/eco/api/microcases/with_each_subordinate.rb,
lib/eco/api/microcases/preserve_policy_groups.rb,
lib/eco/api/microcases/take_email_from_account.rb,
lib/eco/api/microcases/set_core_with_supervisor.rb

Instance Attribute Summary

Attributes inherited from Common::Session::BaseSession

#config, #environment, #session

Attributes included from Language::AuxiliarLogger

#logger

Instance Method Summary collapse

Methods inherited from Common::Session::BaseSession

#api, #api?, #fatal, #file_manager, #initialize, #logger, #mailer, #mailer?, #s3uploader, #s3uploader?, #sftp, #sftp?

Methods included from Language::AuxiliarLogger

#log

Constructor Details

This class inherits a constructor from Eco::API::Common::Session::BaseSession

Instance Method Details

#account_excluded(person, options) ⇒ Array<String>

Returns the account parameters that should not be included.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.

Returns:

  • (Array<String>)

    the account parameters that should not be included.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/eco/api/microcases/account_excluded.rb', line 7

def (person, options)
  [].tap do ||
    unless person.new?
      if options.dig(:exclude, :policy_groups)
        .push("policy_group_ids")
      end

      if options.dig(:exclude, :default_tag)
        .push("default_tag")
      end

      if options.dig(:exclude, :login_providers)
        .push("login_provider_ids")
      end
    end
  end
end

#append_usergroups(entry, person, options) ⇒ Object

It preserves the usergroups of person and appends those defined in policy_group_ids of the entry

Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.



8
9
10
11
12
13
# File 'lib/eco/api/microcases/append_usergroups.rb', line 8

def append_usergroups(entry, person, options)
  return if options.dig(:exclude, :account)
  return unless person.

  person..policy_group_ids |= entry.policy_group_ids
end

#core_excluded(person, options) ⇒ Array<String>

Note:

by default supervisor_id is always excluded.

Returns the core parameters that should not be included.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.

Returns:

  • (Array<String>)

    the core parameters that should not be included.



8
9
10
11
12
13
14
15
16
17
# File 'lib/eco/api/microcases/core_excluded.rb', line 8

def core_excluded(person, options)
  ["supervisor_id"].tap do |core_excluded|
    can_exclude = person.new?? ["filter_tags"] : %w[name external_id email filter_tags]

    exclusions  = can_exclude.select do |attr|
      options.dig(:exclude, attr.to_sym)
    end
    core_excluded.concat(exclusions)
  end
end

#fix_default_group(entry, person, options) ⇒ Object

If defined, it sets the default usergroup, only when the policy_group_ids was not part of the input data.

Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/eco/api/microcases/fix_default_group.rb', line 8

def fix_default_group(entry, person, options)
  return if options.dig(:exclude, :account)
  return if options.dig(:exclude, :policy_groups) && !person.new?

  end_pg_ids = person..policy_group_ids

  if person. && __def_usergroup_id && !entry.policy_group_ids?
    # on account creation, if missing policy_group_ids column in the input
    # use default_usergroup, if it's defined
    end_pg_ids = [__def_usergroup_id]
  end

  person..policy_group_ids = end_pg_ids
end

#fix_filter_tags(person, options) ⇒ Object

Note:
  • this feature is essential to preserve custom tags in users that have register tags.
  • for this to work out, it requires a tagtree to be defined.

Helper that makes sure the custom tags are preserved.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes already done.

  • options (Hash)

    the options.

Options Hash (options):

  • :filter_tags (Hash<Symbol, Object>)

    options around filter_tags.

    • :preserve_custom (Boolean) [true] indicates if original tags that are not in the tree should be added/preserved.
    • :add_custom (Boolean) [true] indicates if target tags that are not in the tree should be really added.


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/eco/api/microcases/fix_filter_tags.rb', line 13

def fix_filter_tags(person, options)
  return unless session.tagtree

  filter_tags_excluded =
    options.dig(:exclude, :core) ||
    options.dig(:exclude, :filter_tags)

  return if !person.new? && filter_tags_excluded

  person.filter_tags = session.tagtree.user_tags(
    initial:         person.original_doc["filter_tags"] || [],
    final:           person.filter_tags,
    preserve_custom: _fix_filter_tags_preserve_custom?(options),
    add_custom:      _fix_filter_tags_add_custom?(options)
  )
end

#microObject



4
5
6
# File 'lib/eco/api/microcases.rb', line 4

def micro
  self
end

#people_cache(filename = enviro.config.people.cache) ⇒ Eco::API::Organization::People

Helper to locally cache the people manager.

Parameters:

  • filename (String) (defaults to: enviro.config.people.cache)

    the name of the file where the data should be cached.

Returns:



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/eco/api/microcases/people_cache.rb', line 7

def people_cache(filename = enviro.config.people.cache)
  log(:info) { "Going to get all the people via API" }

  start   = Time.now
  people  = session.batch.get_people
  secs    = (Time.now - start).round(3)
  cnt     = people.count
  per_sec = (cnt.to_f / secs).round(2)

  log(:info) {
    "Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)"
  }

  file = file_manager.save_json(people, filename, :timestamp)

  log(:info) {
    "#{people.length} people loaded and saved locally to #{file}."
  }

  Eco::API::Organization::People.new(people)
end

#people_load(filename = enviro.config.people.cache, modifier: %i[newest api])) ⇒ Eco::API::Organization::People

Note:
  • filename will be relative to the working directory (the one of the session enviro set by the user).

Helper to load People that works in different phases:

  1. first tries to get the newest cached file that follows filename pattern
    • if not the newest, it tries to find the specific filename
  2. if it succeeds to identify a cached file, it loads it
    • if it fails, it tries to get people from the server

Parameters:

  • filename (String) (defaults to: enviro.config.people.cache)

    the name of the file where the cached data is to be found.

  • modifier (Array<Symbol>) (defaults to: %i[newest api]))

    modifiers to specify how this function should proceed:

    • :newest if it should try to find the newest file (pattern alike).
    • :api if it should try to get people from the server in case there's no cache.
    • :file if it is supposed to load people from a file.
    • :save if it is supposed to cache/save the data locally once obtained people from the server (:api)

Returns:



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/eco/api/microcases/people_load.rb', line 18

def people_load(filename = enviro.config.people.cache, modifier: %i[newest api]) # rubocop:disable Metrics/AbcSize
  modifier  = [modifier].flatten
  load_file = %i[file newest].any? {|flag| modifier.include?(flag)}

  case
  when filename && load_file
    file = people_load_filename(filename, newest: modifier.include?(:newest))

    if file
      file_manager.load_json(file).tap do |people|
        next unless people.is_a?(Array)

        log(:info) {
          "#{people&.length} people loaded from file #{file}"
        }
      end
    else
      log(:error) {
        "could not find the file #{file_manager.dir.file(filename)}"
      }

      exit unless modifier.include?(:api)

      people_load(modifier: modifier - %i[newest file])
    end
  when modifier.include?(:api)
    log(:info) { "Going to get all the people via API (load)" }

    start = Time.now
    session.batch.get_people.tap do |people|
      secs    = (Time.now - start).round(3)
      cnt     = people.count
      per_sec = (cnt.to_f / secs).round(2)

      log(:info) {
        "Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)"
      }

      if modifier.include?(:save) && people && people.length.positive?
        file = file_manager.save_json(people, filename, :timestamp)
        log(:info) { "#{people.length} people saved to file #{file}." }
      end
    end
  end.then do |people|
    Eco::API::Organization::People.new(people)
  end
end

#people_refresh(people:, include_created: true) ⇒ Eco::API::Organization::People

Note:
  1. This helper is normally used to run consecutive usecases, where data needs refresh.
  2. It only includes new people if they are not dirty (they do not have pending updates)
    • This contingency wouldn't be necessary if the server worked perfectly.

Helper to obtain all the elements of people anew from the People Manager.

Parameters:

  • people (Eco::API::Organization::People)

    the people that needs refresh.

  • include_created (Boolean) (defaults to: true)

    include people created during this session? (will check :create batch jobs).

Returns:



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/eco/api/microcases/people_refresh.rb', line 12

def people_refresh(people:, include_created: true) # rubocop:disable Metrics/AbcSize
  people = people.newFrom people.select do |person|
    !person.new? || !person.dirty?
  end

  ini = people.length

  if include_created
    session.job_groups.find_jobs(type: :create).map do |job|
      to_add = job.people.reject(&:dirty?)
      people = people.merge(to_add)
    end
  end

  created = people.length - ini
  msg    = "Going to refresh #{people.length} people with server data"
  msg   += " (including #{created} that were created)" if created.positive?
  log(:info) { msg }

  start   = Time.now
  entries = session.batch.get_people(people, silent: true)
  secs    = (Time.now - start).round(3)
  cnt     = entries.count
  per_sec = (cnt.to_f / secs).round(2)

  log(:info) {
    "Re-loaded #{cnt} people (out of #{people.length}) in #{secs} seconds (#{per_sec} people/sec)"
  }

  missing = people.length - entries.length

  if missing.positive?
    log(:error) {
      "Missed to obtain #{missing} people during the refresh"
    }
  end

  Eco::API::Organization::People.new(entries)
end

#people_search(data, options: {}, silent: true) ⇒ Eco::API::Organization::People

Note:
  • this helper is normally used to get partial part of the people manager.
  • therefore, normally used with delta input files (files with only the differences).

Helper to search/obtain people from data against the server (People Manager).

Parameters:

  • data (Eco::API::Organization::People, Enumerable<Person>, Enumerable<Hash>)

    People to search against the server.

  • options (Hash) (defaults to: {})

    the options.

  • silent (Boolean) (defaults to: true)

    false if low level search messages should be shown.

Returns:



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/eco/api/microcases/people_search.rb', line 13

def people_search(data, options: {}, silent: true) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  log(:info) { "Going to api get #{data.length} entries..." }

  silent &&= data.count <= 500

  start = Time.now
  people = session.batch.search(data, silent: silent).then do |status|
    secs = (Time.now - start).round(3)

    Eco::API::Organization::People.new(status.people).tap do |people| # rubocop:disable Lint/ShadowingOuterLocalVariable
      cnt     = people.count
      per_sec = (cnt.to_f / secs).round(2)

      msg     = "... could get #{cnt} people "
      msg    << "(out of #{data.length} entries) in #{secs} seconds (#{per_sec} people/sec)"

      log(:info) { msg }
    end
  end

  # get the supervisors of found people (current supervisors)
  supers = people_search_prepare_supers_request(people)
  if supers.length.positive?
    log(:info) {
      "  Going to api get #{supers.length} current supervisors..."
    }

    start = Time.now
    people = session.batch.search(supers, silent: silent).then do |status|
      secs    = (Time.now - start).round(3)
      found   = status.people
      cnt     = found.count
      per_sec = (cnt.to_f / secs).round(2)

      msg     = "... could find #{cnt} current supers "
      msg    << "(out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
      log(:info) { msg }

      people.merge(found, strict: micro.strict_search?(options))
    end
  end

  # get the supervisors referred in the input data (future supervisors)
  supers = people_search_prepare_supers_request(data, people)
  if supers.length.positive?
    log(:info) {
      "  Going to api get #{supers.length} supervisors as per input entries..."
    }

    start = Time.now
    people = session.batch.search(supers, silent: silent).then do |status|
      secs    = (Time.now - start).round(3)
      found   = status.people
      cnt     = found.count
      per_sec = (cnt.to_f / secs).round(2)

      msg     = "... could find #{cnt} input supers "
      msg    << "(out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
      log(:info) { msg }

      people.merge(found, strict: micro.strict_search?(options))
    end
  end

  log(:info) {
    "Finally got #{people.length} people (out of #{data.length} entries)"
  }

  people
end

#person_update!(person, context: "Session", reason: "") ⇒ Boolean

Note:

if it succeeds the update, it calls person.consolidate!

It updates an idividual person.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • context (String) (defaults to: "Session")

    main part of the message.

  • reason (String) (defaults to: "")

    why are we updating now.

Returns:

  • (Boolean)

    true if it succeded to update, and false otherwise



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/eco/api/microcases/person_update.rb', line 10

def person_update!(person, context: "Session", reason: "")
  log(:debug) {
    "#{context}, going to \"#{reason}\".\nPerson: #{person_ref(person)}"
  }

  if (response = api.people.update(person))
    if response.success?
      person.consolidate!
      true
    else
      msg  = "#{context} Error #{response.status}: #{response.body}\n"
      msg += " -- Failed to \"#{reason}\".\n"
      msg += "  • Person: #{person_ref(person)}"
      log(:error) { msg }
      false
    end
  else
    msg  = "#{context} Error (connection error)\n"
    msg += " -- Failed to \"#{reason}\".\n"
    msg += "  • Person: #{person_ref(person)}"

    log(:error) { msg }
    false
  end
end

#preserve_default_tag(person, _options) ⇒ String

Note:
  1. It only works if the original value of default_tag was not empty

Helper to preserve the original default_tag.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.

Returns:

  • (String)

    the final value of default_tag.



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/eco/api/microcases/preserve_default_tag.rb', line 10

def preserve_default_tag(person, _options)
  return unless ( = person.)

  .default_tag.tap do
    next unless .as_update.key?("default_tag")
    next unless (original = person.original_doc.dig("account", "default_tag"))

    person..default_tag = original
    return original
  end
end

#preserve_filter_tags(person, _options, keep_new: false) ⇒ Array<String>

Note:
  1. It only works if the original value of filter_tags was not empty

Helper to preserve the original filter tags.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.

  • keep_new (Boolean) (defaults to: false)

    tells if it should keep the new tags or get rid of them.

Returns:

  • (Array<String>)

    the final value of filter_tags.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/eco/api/microcases/preserve_filter_tags.rb', line 11

def preserve_filter_tags(person, _options, keep_new: false)
  person.filter_tags.tap do
    next unless person.as_update.key?('filter_tags')
    next unless (original = person.original_doc['filter_tags'])
    next if original.empty?

    if keep_new
      person.filter_tags += original
    else
      person.filter_tags  = original
    end

    return person.filter_tags
  end
end

#preserve_policy_groups(person, _options, keep_new: false) ⇒ String

Note:
  1. It only works if the original value of policy_group_ids was not empty

Helper to preserve the original policy_group_ids.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.

  • keep_new (Boolean) (defaults to: false)

    tells if it should keep the new policy groups or get rid of them.

Returns:

  • (String)

    the final value of policy_group_ids.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/eco/api/microcases/preserve_policy_groups.rb', line 11

def preserve_policy_groups(person, _options, keep_new: false)
  return unless ( = person.)

  .policy_group_ids.tap do
    next unless .as_update.key?("policy_group_ids")
    next unless (original = person.original_doc.dig("account", "policy_group_ids"))
    next if original.empty?

    if keep_new
      person..policy_group_ids += original
    else
      person..policy_group_ids  = original
    end

    return .policy_group_ids
  end
end

#refresh_default_tag(entry, person, options) ⇒ Object

Note:

it assumes default_tag has been already set to person.account

When the input data, or entry, does not provide the default_tag, it sets the default_tag of the user following some criteria

Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/eco/api/microcases/refresh_default_tag.rb', line 10

def refresh_default_tag(entry, person, options)
  return unless person.
  return if options.dig(:exclude, :account)
  return if options.dig(:exclude, :filter_tags)
  return if options.dig(:exclude, :default_tag)
  return if entry&.default_tag?

  if session.tagtree
    person..default_tag = session.tagtree.default_tag(*person.filter_tags)
  else
    tags = person.filter_tags || []
    person..default_tag = tags.first unless tags.length > 1
  end
end

#s3upload_targetsArray<String>

Helper to upload target files to S3.

Returns:

  • (Array<String>)

    the paths in S3 of the uploaded files.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/eco/api/microcases/s3upload_targets.rb', line 6

def s3upload_targets # rubocop:disable Metrics/AbcSize
  [].tap do |paths|
    session.config.s3storage.target_files.each_with_object(paths) do |file, arr|
      arr.push(session.s3upload(file: file))
    end

    session.config.s3storage.target_directories.each_with_object(paths) do |folder, arr|
      arr.concat(session.s3upload(directory: folder))
    end

    session.config.s3storage.target_file_patterns.each_with_object(paths) do |pattern, arr|
      filenames = []
      case pattern
      when Regexp
        Dir.entries(".").sort.each do |file|
          next unless File.file?(file) # Skip directories
          filenames.push(file) if file =~ pattern
        end
      when String
        Dir.glob(pattern).sort.each do |file|
          next unless File.file?(file) # Skip directories
          filenames.push(file)
        end
      else
        # missconfiguration
      end
      filenames.each do |file|
        arr.push(session.s3upload(file: file))
      end
    end
  end
end

#set_account(entry, person, options) ⇒ Object

Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options.



7
8
9
10
11
12
13
14
15
# File 'lib/eco/api/microcases/set_account.rb', line 7

def (entry, person, options)
  return if options.dig(:exclude, :account)

  entry.(person, exclude: micro.(person, options))

  person..send_invites = options[:send_invites] if options.key?(:send_invites)
  micro.refresh_default_tag(entry, person, options)
  micro.fix_default_group(entry, person, options)
end

#set_core(entry, person, options) ⇒ Object

Note:

supervisor_id requires a special treatment, and therefore is always excluded.

Sets all the core details, but the supervisor.

Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • options (Hash)

    the options



9
10
11
12
13
14
# File 'lib/eco/api/microcases/set_core.rb', line 9

def set_core(entry, person, options)
  return if options.dig(:exclude, :core) && !person.new?

  entry.set_core(person, exclude: micro.core_excluded(person, options))
  micro.fix_filter_tags(person, options)
end

#set_core_with_supervisor(entry, person, people, supers_job, options) ⇒ Object

Note:

supervisor_id requires a special treatment, and therefore is always excluded.

Sets all the core details, but the supervisor.

Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • people (Eco::API::Organization::People)

    target existing People of the current update.

  • supers_job (Eco::API::Session::Batch::Job)

    the job that will run the supers .

  • options (Hash)

    the options.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/eco/api/microcases/set_core_with_supervisor.rb', line 11

def set_core_with_supervisor(entry, person, people, supers_job, options)
  return if options.dig(:exclude, :core) && !person.new?

  micro.set_core(entry, person, options)

  return unless entry.supervisor_id?

  micro.set_supervisor(
    person,
    entry.supervisor_id,
    people,
    options
  ) do |unknown_id|
    # delay setting supervisor if does not exit
    supers_job.add(person) do |pers|
      micro.set_supervisor(pers, unknown_id, people, options)
    end
  end
end

#set_supervisor(person, sup_id, people, options) {|supervisor_id| ... } ⇒ Object

Note:
  • It prevents the basic cyclic supervisor case (supervisor to be supervisor of themselves)

Unique access point to set the supervisor_id value on a person.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • sup_id (nil, String)

    the supervisor id we should set on the person.

  • people (Eco::API::Organization::People)

    People involved in the current update.

  • options (Hash)

    the options.

Yields:

  • (supervisor_id)

    callback when the supervisor_id is unknown (not nil nor any one's in people).

Yield Parameters:

  • supervisor_id (String)

    the unknown supervisor_id.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/eco/api/microcases/set_supervisor.rb', line 13

def set_supervisor(person, sup_id, people, options)
  return false if options.dig(:exclude, :core) || options.dig(:exclude, :supervisor)
  return false if sup_id && ((person.id == sup_id) || (person.external_id == sup_id))

  cur_id    = person.supervisor_id
  cur_super = cur_id && with_supervisor(cur_id, people)

  micro.with_supervisor(sup_id, people) do |new_super|
    if !sup_id
      person.supervisor_id = nil
      descrease_subordinates(cur_super)
    elsif new_super && (id = new_super.id)
      set_supervisor(new_super, nil, people, options) if new_super_direct_cyclic?(person, new_super)
      person.supervisor_id = id
      descrease_subordinates(cur_super)
      increase_subordinates(new_super)
    elsif !block_given?
      descrease_subordinates(cur_super)
      person.supervisor_id = sup_id
    elsif block_given?
      yield(sup_id)
    end
  end
end

#strict_search?(options) ⇒ Boolean

Note:
  • strict searches ignore the email when the source entry has an external_id specified.
  • see related command line options -search-strict and -search-soft

When trying to find an person with given a source entry, it states if such a search should be strict or soft.

Parameters:

  • options (Hash)

    the options.

Returns:

  • (Boolean)

    true if the search should be strict only, and false otherwise.



10
11
12
13
14
15
# File 'lib/eco/api/microcases/strict_search.rb', line 10

def strict_search?(options)
  strict_config  = session.config.people.strict_search?
  strict_option  = options.dig(:search, :strict)
  soft_option    = options.dig(:search, :soft) && !strict_option
  (strict_config || strict_option) && !soft_option
end

#take_email_from_account(person, dest_email:, target_email: nil, options: {}, context: "Session") ⇒ Object

Note:
  • It does not do the final update to the server to the target_email. You will need to do this part yourself.
  • You would call this function only when you got an error of email already taken.
  • If the target_email is associated to a user in the same org, this will fail.

Frees up target_email from an account not present in this org. Allows to force target_email on the current user's account.

  • If the person does not have account, this case will not do anything.
  • If original_doc["account"] is nil (no account on server side), this case will not do anything.
  • If the target_email and the current_email are the same or empty, this case will not do anything.

Parameters:

  • person (Ecoportal::API::V1::Person)

    the person we want to update, carrying the changes to be done.

  • dest_email (String, Proc)

    the email that we will move the other account to, when we free up target_email.

  • target_email (String) (defaults to: nil)

    the email that we want to free up from another account and bring to ours. If it's empty, the person.email will be used instead.

  • options (Hash) (defaults to: {})

    the options.

  • current_email (String)

    the email that the person's account is currently linked. As the current email should be associated with this person's account on server side, we use original_doc["email"].

  • context (String) (defaults to: "Session")

    main core part of logs. Provides context to the logs.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/eco/api/microcases/take_email_from_account.rb', line 26

def (person, dest_email:, target_email: nil, options: {}, context: "Session")
  return false if options.dig(:exclude, :account)
  return false unless (     = person.)
  return false unless ( = person.original_doc["account"]) # rubocop:disable Lint/UselessAssignment

  target_email  ||= person.email
     = person.original_doc["email"]

  return false unless target_email != 
  return false if .to_s.strip.empty?
  return false if target_email.to_s.strip.empty?

  if dest_email.is_a?(String)
    return false unless target_email != dest_email
    return false unless dest_email   != 
    return false if dest_email.to_s.strip.empty?
  end

   = ()
  person.email = 

  if (success = _take_email_remove_account!(person, context: context))
    if (success = _take_email_acquire_account!(person, target_email, account: {}, context: context))
      if (success = _take_email_email_free_up!(person, dest_email: dest_email, context: context))
        if (success = _take_email_remove_account!(person, context: context))
          # Bring back the original account
          if (success = _take_email_acquire_account!(person, , account: , context: context)) # rubocop:disable Style/SoleNestedConditional
            success      = true
            person.email = target_email
          end
        end
      else # free up target email
        # restore
        reverted = false
        if reverted ||= _take_email_remove_account!(person, context: context)
          reverted ||= _take_email_acquire_account!(person, , account: , context: context)
        end

        unless reverted
          msg = "Could not revert back to the original account #{person.identify}"
          log(:debug) { msg }
          puts msg
        end

        success = false
      end
    else # aquire other account
      # restore
      unless _take_email_acquire_account!(person, , account: , context: context)
        msg = "Could not bring back the original account that "
        msg << "we want to update the email to '#{target_email}' #{person.identify}"
        log(:debug) { msg }
        puts msg
      end

      success = false
    end
  end

  success
end

#with_each(entries, people, options, append_created: true) {|entry, person| ... } ⇒ Eco::API::Organization::People

Note:
  • it also links to person.entry the input data entry.

Finds each entry of entries in people and runs a block.

Parameters:

Yields:

  • (entry, person)

    gives each entry, and the paired person thereof (new or existing).

Yield Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the found person that matches entry, or a new person otherwise.

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/eco/api/microcases/with_each.rb', line 15

def with_each(entries, people, options, append_created: true)
  @_skip_all_multiple_results = false
  people_copy = people.newFrom(people.to_a)

  entries.each_with_object([]) do |entry, scoped|
    begin
      person   = people_copy.find(entry, strict: micro.strict_search?(options))
      person ||= session.new_person.tap do |pers|
        people << pers if append_created
      end
    rescue Eco::API::Organization::People::MultipleSearchResults => e
      unless @_skip_all_multiple_results
        msg    = "\n * When searching this Entry: #{entry.to_s(:identify)}"
        person = _with_each_prompt_to_select_user(e.append_message(msg), entry: entry)
      end
    end

    next unless person

    person.entry = entry
    yield(entry, person) if block_given?

    scoped << person
  end.then do |all_people|
    people.newFrom all_people.uniq
  end
end

#with_each_leaver(entries, people, options) {|person| ... } ⇒ Eco::API::Organization::People

Note:
  • To be used only when the input file is the full DB
  • The Entries#find method. If the people manager entry does not have external_id, but has a matching email wiht some input entry (row), it won't be identified as a leaver.

Detects who has left the organization and yield s them one by one to the given block

Parameters:

Yields:

  • (person)

    gives each person of people that is not present in entries.

Yield Parameters:

  • person (Ecoportal::API::V1::Person)

    the person that leaves the org.

Returns:



15
16
17
18
19
20
21
22
23
24
# File 'lib/eco/api/microcases/with_each_leaver.rb', line 15

def with_each_leaver(entries, people, options)
  leavers = people.map do |person|
    unless entries.find(person, strict: micro.strict_search?(options))
      yield(person) if block_given?
      person
    end
  end.compact

  people.newFrom leavers
end

#with_each_present(entries, people, options, log_starter: false) {|entry, person| ... } ⇒ Eco::API::Organization::People

Note:
  • it also links to person.entry the input data entry.

Finds those in entries that already exist in the organization (people) and yield s them one by one to the given block.

Parameters:

Yields:

  • (entry, person)

    gives each found person of entries that is not present in people.

Yield Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the found person.

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/eco/api/microcases/with_each_present.rb', line 15

def with_each_present(entries, people, options, log_starter: false)
  found = []
  micro.with_each(entries, people, options) do |entry, person|
    if person.new?
      if log_starter
        log(:error) {
          "This person does not exist: #{entry.to_s(:identify)}"
        }
      end

      next
    end

    found << person
    yield(entry, person) if block_given?
  end

  people.newFrom found
end

#with_each_starter(entries, people, options, log_present: false, append_created: true) {|entry, person| ... } ⇒ Eco::API::Organization::People

Note:
  • it also links to person.entry the input data entry.

Detects who in the entries is new in the organization and yield s them one by one to the given block.

Parameters:

  • entries (Eco::API::Common::People::Entries)

    the input entries with the data.

  • people (Eco::API::Organization::People)

    target existing People of the current update.

  • options (Hash)

    the options.

  • log_present (Boolean) (defaults to: false)

    log error message if an entry has match in people.

  • append_created (Boolean) (defaults to: true)

    whether or not a new person will be added to the people object.

Yields:

  • (entry, person)

    gives each new person of entries that is not present in people.

Yield Parameters:

  • entry (PersonEntry)

    the input entry with the data we should set on person.

  • person (Ecoportal::API::V1::Person)

    the new person.

Returns:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/eco/api/microcases/with_each_starter.rb', line 16

def with_each_starter(entries, people, options, log_present: false, append_created: true)
  starters = []
  micro.with_each(entries, people, options, append_created: append_created) do |entry, person|
    unless person.new?
      if log_present
        log(:error) {
          "This person (id: '#{person.id}') already exists: #{entry.to_s(:identify)}"
        }
      end

      next
    end

    starters << person
    yield(entry, person) if block_given?
  end

  people.newFrom starters
end

#with_each_subordinate(supervisor, people) {|subordinate| ... } ⇒ Eco::API::Organization::People

Note:

if supervisor is nil, it will return all people with no supervisor.

Finds all the subordinates of supervisor.

Parameters:

  • supervisor (String, Ecoportal::API::V1::Person, Hash)

    the supervisor or the id / external_id thereof.

  • people (Eco::API::Organization::People)

    target existing People of the current update.

Yields:

  • (subordinate)

    block that does some stuff with subordinate.

Yield Parameters:

  • subordinate (Ecoportal::API::V1::Person)

    each one of the suborinates of supervisor.

Returns:



11
12
13
14
15
16
17
# File 'lib/eco/api/microcases/with_each_subordinate.rb', line 11

def with_each_subordinate(supervisor, people)
  people.supervisor_id(_person_id(supervisor, people)).tap do |subordinates|
    subordinates.each do |subordinate|
      yield(subordinate) if block_given?
    end
  end
end

#with_supervisor(value, people, strict: false) {|supervisor| ... } ⇒ nil, Ecoportal::API::V1::Person

Finds the supervisor among people by using the supervisor_id of value.

Parameters:

  • value (String, Ecoportal::API::V1::Person, Hash)

    the subordinate person, or the unique identifier of the supervisor to be found (preferably the external_id).

  • people (Eco::API::Organization::People)

    target existing People of the current update.

  • strict (Boolean) (defaults to: false)

    specifies if the search should be strict (see Organization::People#person).

Yields:

  • (supervisor)

    block that does some stuff with supevisor.

Yield Parameters:

  • supervisor (Ecoportal::API::V1::Person)

    the person object of the supervisor, or nil if not found.

Returns:

  • (nil, Ecoportal::API::V1::Person)

    found supervisor of value.



12
13
14
15
16
17
18
# File 'lib/eco/api/microcases/with_supervisor.rb', line 12

def with_supervisor(value, people, strict: false)
  if sup_id = with_supervisor_supervisor_id(value)
    people.person(id: sup_id, external_id: sup_id, email: sup_id, strict: strict)
  end.tap do |supervisor|
    yield(supervisor) if block_given?
  end
end