eco-helpers 2.0.15 → 2.0.21

Sign up to get free protection for your applications and to get access to all the features.
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