eco-helpers 2.0.15 → 2.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +109 -3
  3. data/eco-helpers.gemspec +11 -5
  4. data/lib/eco-helpers.rb +2 -0
  5. data/lib/eco/api/common/base_loader.rb +14 -0
  6. data/lib/eco/api/common/loaders/parser.rb +1 -0
  7. data/lib/eco/api/common/people/default_parsers/date_parser.rb +11 -1
  8. data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +1 -1
  9. data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +11 -11
  10. data/lib/eco/api/common/people/entries.rb +1 -0
  11. data/lib/eco/api/common/people/entry_factory.rb +74 -23
  12. data/lib/eco/api/common/people/person_entry.rb +5 -2
  13. data/lib/eco/api/common/people/supervisor_helpers.rb +27 -0
  14. data/lib/eco/api/common/session.rb +1 -0
  15. data/lib/eco/api/common/session/base_session.rb +2 -0
  16. data/lib/eco/api/common/session/file_manager.rb +2 -2
  17. data/lib/eco/api/common/session/helpers.rb +30 -0
  18. data/lib/eco/api/common/session/helpers/prompt_user.rb +34 -0
  19. data/lib/eco/api/common/session/mailer.rb +0 -1
  20. data/lib/eco/api/common/session/s3_uploader.rb +0 -1
  21. data/lib/eco/api/common/session/sftp.rb +0 -1
  22. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +1 -1
  23. data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +7 -4
  24. data/lib/eco/api/common/version_patches/exception.rb +11 -4
  25. data/lib/eco/api/microcases.rb +3 -1
  26. data/lib/eco/api/microcases/append_usergroups.rb +0 -1
  27. data/lib/eco/api/microcases/people_cache.rb +2 -2
  28. data/lib/eco/api/microcases/people_load.rb +2 -2
  29. data/lib/eco/api/microcases/people_refresh.rb +2 -2
  30. data/lib/eco/api/microcases/people_search.rb +6 -6
  31. data/lib/eco/api/microcases/preserve_default_tag.rb +23 -0
  32. data/lib/eco/api/microcases/preserve_filter_tags.rb +28 -0
  33. data/lib/eco/api/microcases/preserve_policy_groups.rb +30 -0
  34. data/lib/eco/api/microcases/set_account.rb +0 -1
  35. data/lib/eco/api/microcases/with_each.rb +67 -6
  36. data/lib/eco/api/microcases/with_each_present.rb +4 -2
  37. data/lib/eco/api/microcases/with_each_starter.rb +4 -2
  38. data/lib/eco/api/organization.rb +1 -0
  39. data/lib/eco/api/organization/people.rb +98 -22
  40. data/lib/eco/api/organization/people_similarity.rb +272 -0
  41. data/lib/eco/api/organization/person_schemas.rb +5 -1
  42. data/lib/eco/api/organization/policy_groups.rb +5 -1
  43. data/lib/eco/api/organization/presets_factory.rb +40 -80
  44. data/lib/eco/api/organization/presets_integrity.json +6 -0
  45. data/lib/eco/api/organization/presets_values.json +5 -4
  46. data/lib/eco/api/organization/tag_tree.rb +33 -0
  47. data/lib/eco/api/policies/default_policies/99_user_access_policy.rb +0 -30
  48. data/lib/eco/api/session.rb +10 -24
  49. data/lib/eco/api/session/batch.rb +25 -7
  50. data/lib/eco/api/session/config.rb +16 -15
  51. data/lib/eco/api/session/config/api.rb +4 -0
  52. data/lib/eco/api/session/config/apis.rb +80 -0
  53. data/lib/eco/api/session/config/files.rb +7 -0
  54. data/lib/eco/api/session/config/people.rb +3 -19
  55. data/lib/eco/api/usecases/default_cases.rb +4 -1
  56. data/lib/eco/api/usecases/default_cases/abstract_policygroup_abilities_case.rb +161 -0
  57. data/lib/eco/api/usecases/default_cases/analyse_people_case.rb +223 -0
  58. data/lib/eco/api/usecases/default_cases/clean_unknown_tags_case.rb +37 -0
  59. data/lib/eco/api/usecases/default_cases/codes_to_tags_case.rb +2 -3
  60. data/lib/eco/api/usecases/default_cases/reset_landing_page_case.rb +11 -1
  61. data/lib/eco/api/usecases/default_cases/restore_db_case.rb +1 -2
  62. data/lib/eco/api/usecases/default_cases/supers_cyclic_identify_case.rb +72 -0
  63. data/lib/eco/api/usecases/default_cases/supers_hierarchy_case.rb +1 -1
  64. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +132 -29
  65. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +61 -36
  66. data/lib/eco/api/usecases/ooze_samples/ooze_update_case.rb +3 -2
  67. data/lib/eco/cli.rb +0 -10
  68. data/lib/eco/cli/config/default/options.rb +48 -17
  69. data/lib/eco/cli/config/default/people.rb +18 -24
  70. data/lib/eco/cli/config/default/people_filters.rb +3 -3
  71. data/lib/eco/cli/config/default/usecases.rb +105 -28
  72. data/lib/eco/cli/config/default/workflow.rb +21 -12
  73. data/lib/eco/cli/config/help.rb +1 -0
  74. data/lib/eco/cli/config/options_set.rb +106 -13
  75. data/lib/eco/cli/config/use_cases.rb +33 -33
  76. data/lib/eco/cli/scripting/args_helpers.rb +30 -3
  77. data/lib/eco/csv.rb +4 -2
  78. data/lib/eco/csv/table.rb +121 -21
  79. data/lib/eco/data.rb +1 -0
  80. data/lib/eco/data/crypto/encryption.rb +3 -3
  81. data/lib/eco/data/files/directory.rb +28 -20
  82. data/lib/eco/data/files/helpers.rb +6 -4
  83. data/lib/eco/data/fuzzy_match.rb +201 -0
  84. data/lib/eco/data/fuzzy_match/array_helpers.rb +75 -0
  85. data/lib/eco/data/fuzzy_match/chars_position_score.rb +38 -0
  86. data/lib/eco/data/fuzzy_match/ngrams_score.rb +82 -0
  87. data/lib/eco/data/fuzzy_match/pairing.rb +95 -0
  88. data/lib/eco/data/fuzzy_match/result.rb +87 -0
  89. data/lib/eco/data/fuzzy_match/results.rb +77 -0
  90. data/lib/eco/data/fuzzy_match/score.rb +49 -0
  91. data/lib/eco/data/fuzzy_match/stop_words.rb +35 -0
  92. data/lib/eco/data/fuzzy_match/string_helpers.rb +82 -0
  93. data/lib/eco/version.rb +1 -1
  94. metadata +168 -11
  95. data/lib/eco/api/microcases/refresh_abilities.rb +0 -19
  96. data/lib/eco/api/organization/presets_reference.json +0 -59
  97. data/lib/eco/api/usecases/default_cases/refresh_abilities_case.rb +0 -30
@@ -210,13 +210,13 @@ module Eco
210
210
  # @param exclude [String, Array<String>] account properties that should not be set/changed to the person.
211
211
  def set_account(person, exclude: nil)
212
212
  person.account = {} if !person.account
213
- person.account.permissions_preset = nil unless person.account.permissions_preset = "custom"
214
213
  scoped_attrs = @emap.account_attrs - into_a(exclude)
215
214
  @final_entry.slice(*scoped_attrs).each do |attr, value|
216
215
  set_part(person.account, attr, value)
217
216
  end
218
217
  end
219
218
 
219
+ # TO DO: use person.details.schema_id to switch @emap and @person_parser (or just crash if they don't match?)
220
220
  # Setter to fill in all the schema `details` fields of the `Person` that are present in the `Entry`.
221
221
  # @note it only sets those details properties defined in the entry.
222
222
  # Meaning that if an details property is not present in the entry, this will not be set on the target person.
@@ -290,7 +290,10 @@ module Eco
290
290
  # @param internal_entry [Hash] entry with **internal** names and values, but **external** types.
291
291
  # @return [Hash] entry with **internal** names and **external** values and types.
292
292
  def _mapped_serializing(internal_entry)
293
- internal_entry.merge(_serialize_values(internal_entry, :internal))
293
+ mapped_hash = internal_entry.merge(_serialize_values(internal_entry, :internal))
294
+ model_attrs = @person_parser.all_model_attrs - ["send_invites"]
295
+ aux_hash = mapped_hash.slice(*model_attrs)
296
+ merge_missing_attrs(aux_hash, mapped_hash)
294
297
  end
295
298
 
296
299
  # Parsing helper that just **parses the values** that have a parser/serializer defined.
@@ -15,6 +15,7 @@ module Eco
15
15
  # Reorders as follows:
16
16
  # 1. supervisors, people with no supervisor or where their supervisor not present
17
17
  # 2. subordinates
18
+ # @return [Array<Entry>] `values` sorted by supervisors/subordinates
18
19
  def sort_by_supervisors(values, supervisors_first: true)
19
20
  raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
20
21
  return [] unless values && values.is_a?(Enumerable)
@@ -32,6 +33,32 @@ module Eco
32
33
  roam.call(supervisors_tree(values))
33
34
  end
34
35
 
36
+ # Identifies all the cyclic supervisor chains
37
+ # @note as `supervisors_tree` will have any entry involved in a cycle at the top, it just checks all the top entries against their offspring
38
+ # @return [Array<Array>] the sets of entries that are cyclic
39
+ def identify_cyclic_chains(values)
40
+ raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
41
+ return [] unless values && values.is_a?(Enumerable)
42
+
43
+ identify = Proc.new do |top_sup, offspring, chain = [top_sup]|
44
+ next [] if offspring.empty?
45
+ offspring.each_with_object([]) do |(sup, subordinates), set|
46
+ break set unless set.empty?
47
+ if top_sup.supervisor_id == sup.id
48
+ set.concat(chain, [sup])
49
+ else
50
+ set = identify.call(top_sup, subordinates, chain | [sup])
51
+ end
52
+ end
53
+ end
54
+
55
+ supervisors_tree(values).each_with_object([]) do |(top_sup, offspring), sets|
56
+ if (set = identify.call(top_sup, offspring)) && !set.empty?
57
+ sets.push(set)
58
+ end
59
+ end
60
+ end
61
+
35
62
  def tree_to_str(tree, lev: 0)
36
63
  raise "Required Hash tree structure. Given: #{tree.class}" unless tree.is_a?(Hash)
37
64
  "".tap do |str|
@@ -13,4 +13,5 @@ require_relative 'session/sftp'
13
13
  require_relative 'session/s3_uploader'
14
14
  require_relative 'session/file_manager'
15
15
  require_relative 'session/environment'
16
+ require_relative 'session/helpers'
16
17
  require_relative 'session/base_session'
@@ -11,6 +11,8 @@ module Eco
11
11
  attr_reader :api, :file_manager, :logger
12
12
  alias_method :fm, :file_manager
13
13
 
14
+ include Session::Helpers
15
+
14
16
  def initialize(e)
15
17
  raise "Expected object Eco::API::Common::Session::Environment. Given: #{e.class}" unless e.is_a?(Environment)
16
18
  self.environment = e
@@ -20,8 +20,8 @@ module Eco
20
20
  begin
21
21
  @dir = Eco::Data::Files::Directory.new(value)
22
22
  @dir_path = @dir.create
23
- rescue
24
- logger.error("could not create or make any sense of directory '#{value}'")
23
+ rescue Exception => e
24
+ logger.error("could not create or make any sense of directory '#{value}': #{e.to_s}")
25
25
  end
26
26
  end
27
27
 
@@ -0,0 +1,30 @@
1
+ require_relative 'helpers/prompt_user'
2
+
3
+ module Eco
4
+ module API
5
+ module Common
6
+ module Session
7
+ module Helpers
8
+
9
+ class << self
10
+ def included(base)
11
+ base.send(:include, InstanceMethods)
12
+ base.extend(ClassMethods)
13
+ end
14
+ end
15
+
16
+
17
+ module ClassMethods
18
+
19
+ end
20
+
21
+ module InstanceMethods
22
+ include Helpers::PromptUser
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require 'timeout'
2
+ module Eco
3
+ module API
4
+ module Common
5
+ module Session
6
+ module Helpers
7
+ module PromptUser
8
+
9
+ def prompt_user(question, default:, explanation: "", timeout: nil)
10
+ response = if config.run_mode_remote?
11
+ default
12
+ else
13
+ puts explanation
14
+ print "#{question} "
15
+ if timeout
16
+ begin
17
+ Timeout::timeout(timeout) { STDIN.gets.chop }
18
+ rescue Timeout::Error
19
+ default
20
+ end
21
+ else
22
+ STDIN.gets.chop
23
+ end
24
+ end
25
+ return response unless block_given?
26
+ yield(response)
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,5 +1,4 @@
1
1
  require 'aws-sdk-ses'
2
- require 'dotenv/load'
3
2
 
4
3
  module Eco
5
4
  module API
@@ -1,5 +1,4 @@
1
1
  require 'aws-sdk-s3'
2
- require 'dotenv/load'
3
2
 
4
3
  module Eco
5
4
  module API
@@ -1,5 +1,4 @@
1
1
  require "net/sftp"
2
- require 'dotenv/load'
3
2
 
4
3
  module Eco
5
4
  module API
@@ -18,7 +18,7 @@ module Ecoportal
18
18
  entry.to_s(:identify)
19
19
  else
20
20
  str_id = id ? "id: '#{id}'; " : ""
21
- "#{name}' (#{str_id}ext_id: '#{external_id}'; email: '#{email}')"
21
+ "'#{name}' (#{str_id}ext_id: '#{external_id}'; email: '#{email}')"
22
22
  end
23
23
  end
24
24
 
@@ -11,12 +11,15 @@ module Ecoportal
11
11
  original_doc["account"] = JSON.parse(doc["account"])
12
12
  end
13
13
 
14
- def new?
15
- !initial_doc["details"] && !initial_doc["account"]
14
+ def new?(doc = :initial)
15
+ ref_doc = (doc == :original) ? original_doc : initial_doc
16
+ !ref_doc["details"] && !ref_doc["account"]
16
17
  end
17
18
 
18
- def account_added?
19
- account && !initial_doc["account"]
19
+ # @return [Boolean] if the account has been added, compared to `doc`
20
+ def account_added?(doc = :initial)
21
+ ref_doc = (doc == :original) ? original_doc : initial_doc
22
+ account && !ref_doc["account"]
20
23
  end
21
24
 
22
25
  end
@@ -1,9 +1,16 @@
1
1
  class ::Exception
2
2
  def patch_full_message
3
- msg = []
4
- msg << "\n#{backtrace.first} \n#{message} (#{self.class.to_s})"
5
- backtrace[1..-1].each_with_index {|bt, i| msg << "#{" "*8}#{i+1}: from #{bt}"}
6
- msg.join("\n")
3
+ begin
4
+ msg = []
5
+ tracing = backtrace ? backtrace : []
6
+ tracing = (self.class == SystemStackError) ? tracing[1..30] : tracing[1..-1]
7
+ tracing ||= []
8
+ msg << "\n#{tracing.first} \n#{message} (#{self.class.to_s})"
9
+ tracing.each_with_index {|bt, i| msg << "#{" "*8}#{i+1}: from #{bt}"}
10
+ msg.join("\n")
11
+ rescue Exception => e
12
+ puts "Something is wrong with 'patch_full_message': #{e}"
13
+ end
7
14
  end
8
15
  end
9
16
 
@@ -19,7 +19,9 @@ require_relative 'microcases/people_cache'
19
19
  require_relative 'microcases/people_load'
20
20
  require_relative 'microcases/people_refresh'
21
21
  require_relative 'microcases/people_search'
22
- require_relative 'microcases/refresh_abilities'
22
+ require_relative 'microcases/preserve_filter_tags'
23
+ require_relative 'microcases/preserve_default_tag'
24
+ require_relative 'microcases/preserve_policy_groups'
23
25
  require_relative 'microcases/set_account'
24
26
  require_relative 'microcases/set_core_with_supervisor'
25
27
  require_relative 'microcases/set_core'
@@ -9,7 +9,6 @@ module Eco
9
9
  unless options.dig(:exclude, :account)
10
10
  if person.account
11
11
  person.account.policy_group_ids |= entry.policy_group_ids
12
- micro.refresh_abilities(person, options)
13
12
  end
14
13
  end
15
14
  end
@@ -9,9 +9,9 @@ module Eco
9
9
 
10
10
  start = Time.now
11
11
  people = session.batch.get_people
12
- secs = Time.now - start
12
+ secs = (Time.now - start).round(3)
13
13
  cnt = people.count
14
- per_sec = (cnt.to_f / secs).floor
14
+ per_sec = (cnt.to_f / secs).round(2)
15
15
  logger.info("Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)")
16
16
 
17
17
  file = file_manager.save_json(people, filename, :timestamp)
@@ -34,9 +34,9 @@ module Eco
34
34
 
35
35
  start = Time.now
36
36
  session.batch.get_people.tap do |people|
37
- secs = Time.now - start
37
+ secs = (Time.now - start).round(3)
38
38
  cnt = people.count
39
- per_sec = (cnt.to_f / secs).floor
39
+ per_sec = (cnt.to_f / secs).round(2)
40
40
  logger.info("Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)")
41
41
 
42
42
  if modifier.include?(:save) && people && people.length > 0
@@ -21,9 +21,9 @@ module Eco
21
21
 
22
22
  start = Time.now
23
23
  entries = session.batch.get_people(people, silent: true)
24
- secs = Time.now - start
24
+ secs = (Time.now - start).round(3)
25
25
  cnt = entries.count
26
- per_sec = (cnt.to_f / secs).floor
26
+ per_sec = (cnt.to_f / secs).round(2)
27
27
  logger.info("Re-loaded #{cnt} people (out of #{people.length}) in #{secs} seconds (#{per_sec} people/sec)")
28
28
 
29
29
  missing = people.length - entries.length
@@ -14,10 +14,10 @@ module Eco
14
14
 
15
15
  start = Time.now
16
16
  people = session.batch.search(data, silent: silent).yield_self do |status|
17
- secs = Time.now - start
17
+ secs = (Time.now - start).round(3)
18
18
  Eco::API::Organization::People.new(status.people).tap do |people|
19
19
  cnt = people.count
20
- per_sec = (cnt.to_f / secs).floor
20
+ per_sec = (cnt.to_f / secs).round(2)
21
21
  msg = "... could get #{cnt} people (out of #{data.length} entries) in #{secs} seconds (#{per_sec} people/sec)"
22
22
  session.logger.info(msg)
23
23
  end
@@ -29,10 +29,10 @@ module Eco
29
29
  session.logger.info(" Going to api get #{supers.length} current supervisors...")
30
30
  start = Time.now
31
31
  people = session.batch.search(supers, silent: silent).yield_self do |status|
32
- secs = Time.now - start
32
+ secs = (Time.now - start).round(3)
33
33
  found = status.people
34
34
  cnt = found.count
35
- per_sec = (cnt.to_f / secs).floor
35
+ per_sec = (cnt.to_f / secs).round(2)
36
36
  msg = "... could find #{cnt} current supers (out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
37
37
  session.logger.info(msg)
38
38
  people.merge(found, strict: micro.strict_search?(options))
@@ -46,10 +46,10 @@ module Eco
46
46
  start = Time.now
47
47
 
48
48
  people = session.batch.search(supers, silent: silent).yield_self do |status|
49
- secs = Time.now - start
49
+ secs = (Time.now - start).round(3)
50
50
  found = status.people
51
51
  cnt = found.count
52
- per_sec = (cnt.to_f / secs).floor
52
+ per_sec = (cnt.to_f / secs).round(2)
53
53
  msg = "... could find #{cnt} input supers (out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
54
54
  session.logger.info(msg)
55
55
  people.merge(found, strict: micro.strict_search?(options))
@@ -0,0 +1,23 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ # Helper to preserve the original `default_tag`.
5
+ # @note
6
+ # 1. It only works if the original value of `default_tag` was **not** empty
7
+ # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
8
+ # @param options [Hash] the options.
9
+ # @return [String] the final value of `default_tag`.
10
+ def preserve_default_tag(person, options)
11
+ if account = person.account
12
+ if account.as_update.key?("default_tag")
13
+ if original = person.original_doc.dig("account", "default_tag")
14
+ person.account.default_tag = original
15
+ end
16
+ end
17
+ end
18
+ person.account&.default_tag
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ # Helper to preserve the original filter tags.
5
+ # @note
6
+ # 1. It only works if the original value of `filter_tags` was **not** empty
7
+ # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
8
+ # @param options [Hash] the options.
9
+ # @param keep_new [Boolean] tells if it should keep the new tags or get rid of them.
10
+ # @return [Array<String>] the final value of `filter_tags`.
11
+ def preserve_filter_tags(person, options, keep_new: false)
12
+ if person.as_update.key?("filter_tags")
13
+ if original = person.original_doc["filter_tags"]
14
+ unless original.empty?
15
+ if keep_new
16
+ person.filter_tags += original
17
+ else
18
+ person.filter_tags = original
19
+ end
20
+ end
21
+ end
22
+ end
23
+ person.filter_tags
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ # Helper to preserve the original `policy_group_ids`.
5
+ # @note
6
+ # 1. It only works if the original value of `policy_group_ids` was **not** empty
7
+ # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
8
+ # @param options [Hash] the options.
9
+ # @param keep_new [Boolean] tells if it should keep the new policy groups or get rid of them.
10
+ # @return [String] the final value of `policy_group_ids`.
11
+ def preserve_policy_groups(person, options, keep_new: false)
12
+ if account = person.account
13
+ if account.as_update.key?("policy_group_ids")
14
+ if original = person.original_doc.dig("account", "policy_group_ids")
15
+ unless original.empty?
16
+ if keep_new
17
+ person.account.policy_group_ids += original
18
+ else
19
+ person.account.policy_group_ids = original
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ person.account&.policy_group_ids
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -11,7 +11,6 @@ module Eco
11
11
  person.account.send_invites = options[:send_invites] if options.key?(:send_invites)
12
12
  micro.refresh_default_tag(entry, person, options)
13
13
  micro.fix_default_group(entry, person, options)
14
- micro.refresh_abilities(person, options)
15
14
  end
16
15
  end
17
16
 
@@ -12,16 +12,77 @@ module Eco
12
12
  # @yieldparam person [Ecoportal::API::V1::Person] the found person that matches `entry`, or a new person otherwise.
13
13
  # @return [Eco::API::Organization::People] all the people, including new and existing ones.
14
14
  def with_each(entries, people, options)
15
- entries.map do |entry|
16
- unless person = people.find(entry, strict: micro.strict_search?(options))
17
- person = session.new_person
15
+ @_skip_all_multiple_results = false
16
+ entries.each_with_object([]) do |entry, scoped|
17
+ begin
18
+ unless person = people.find(entry, strict: micro.strict_search?(options))
19
+ person = session.new_person
20
+ end
21
+ rescue Eco::API::Organization::People::MultipleSearchResults => e
22
+ unless @_skip_all_multiple_results
23
+ msg = "\n * When searching this Entry: #{entry.to_s(:identify)}"
24
+ person = _with_each_prompt_to_select_user(e.append_message(msg), entry: entry)
25
+ end
26
+ end
27
+
28
+ if person
29
+ person.entry = entry
30
+ yield(entry, person) if block_given?
31
+ scoped << person
18
32
  end
19
- person.entry = entry
20
- yield(entry, person) if block_given?
21
- person
22
33
  end.yield_self {|all_people| people.newFrom all_people.uniq}
23
34
  end
24
35
 
36
+ private
37
+
38
+ def _with_each_prompt_to_select_user(error, entry: nil, increase_count: true)
39
+ unless error.is_a?(Eco::API::Organization::People::MultipleSearchResults)
40
+ raise "Expecting Eco::API::Organization::People::MultipleSearchResults. Given: #{error.class}"
41
+ end
42
+ @_with_each_prompts = 0 unless instance_variable_defined?(:@_with_each_prompts)
43
+ @_with_each_prompts += 1 if increase_count
44
+
45
+ lines = []
46
+ lines << "\n(#{@_with_each_prompts}) " + error.to_s + "\n"
47
+ lines << " #index - Select the correct person by its number index among the list above."
48
+ lines << " (I) - Just Skip/Ignore this one. I will deal with that input entry in another launch."
49
+ lines << " (A) - Ignore all the rest of input entries with this problem."
50
+ lines << " (C) - Create a new person."
51
+ lines << " (B) - Just break this script. I need to change the input file :/"
52
+
53
+ prompt_user("Type one option (#number/I/A/C/B):", explanation: lines.join("\n"), default: "I") do |res|
54
+ res = res.upcase
55
+ case
56
+ when res.start_with?("I")
57
+ logger.info "Ignoring entry... #{entry.to_s(:identify) if entry}"
58
+ nil
59
+ when res.start_with?("A")
60
+ logger.info "All input entries with this same issue will be ignored for this launch"
61
+ @_skip_all_multiple_results = true
62
+ nil
63
+ when res.start_with?("C")
64
+ logger.info "Creating new person...#{"for entry #{entry.to_s(:identify)}" if entry}"
65
+ session.new_person
66
+ when res.start_with?("B")
67
+ raise error
68
+ when res && !res.empty? && (pos = res.to_i rescue nil) && (pos < error.candidates.length)
69
+ error.candidate(pos).tap do |person|
70
+ logger.info "Thanks!! You selected #{person.identify}"
71
+ sleep(1.5)
72
+ end
73
+ else
74
+ if pos.is_a?(Numeric) && (pos >= error.candidates.length)
75
+ print "#{pos} is not a number in the range. "
76
+ else
77
+ print "#{res} is not an option. "
78
+ end
79
+ puts "Please select one of the offered options..."
80
+ sleep(1)
81
+ _with_each_prompt_to_select_user(error, increase_count: false, entry: entry)
82
+ end
83
+ end
84
+ end
85
+
25
86
  end
26
87
  end
27
88
  end