eco-helpers 3.0.20 → 3.0.22

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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/.idea/.gitignore +10 -0
  3. data/CHANGELOG.md +55 -5
  4. data/eco-helpers.gemspec +3 -3
  5. data/lib/eco/api/common/class_hierarchy.rb +6 -9
  6. data/lib/eco/api/common/loaders/case_base.rb +12 -4
  7. data/lib/eco/api/common/loaders/config/cli.rb +9 -0
  8. data/lib/eco/api/common/loaders/config/workflow/cases_extension.rb +53 -0
  9. data/lib/eco/api/common/loaders/config/workflow/mailer.rb +2 -14
  10. data/lib/eco/api/common/loaders/config/workflow.rb +4 -0
  11. data/lib/eco/api/common/loaders/config.rb +1 -0
  12. data/lib/eco/api/common/loaders/error_handler.rb +3 -2
  13. data/lib/eco/api/common/loaders/policy.rb +3 -2
  14. data/lib/eco/api/common/loaders/use_case/cli_identify.rb +28 -0
  15. data/lib/eco/api/common/loaders/use_case/target_model.rb +25 -0
  16. data/lib/eco/api/common/loaders/use_case/type.rb +37 -0
  17. data/lib/eco/api/common/loaders/use_case.rb +16 -43
  18. data/lib/eco/api/common/people/default_parsers/xls_parser.rb +1 -1
  19. data/lib/eco/api/common/session/logger/cache.rb +10 -4
  20. data/lib/eco/api/common/session/logger/channels.rb +41 -0
  21. data/lib/eco/api/common/session/logger.rb +9 -0
  22. data/lib/eco/api/error/handler.rb +6 -4
  23. data/lib/eco/api/error/handlers.rb +12 -5
  24. data/lib/eco/api/microcases/people/apply_changes/set_account/account_excluded.rb +34 -0
  25. data/lib/eco/api/microcases/people/apply_changes/set_account.rb +28 -0
  26. data/lib/eco/api/microcases/people/apply_changes/set_core/core_excluded.rb +28 -0
  27. data/lib/eco/api/microcases/people/apply_changes/set_core.rb +27 -0
  28. data/lib/eco/api/microcases/people/apply_changes/set_core_with_supervisor.rb +38 -0
  29. data/lib/eco/api/microcases/people/apply_changes/set_supervisor.rb +69 -0
  30. data/lib/eco/api/microcases/people/apply_changes.rb +19 -0
  31. data/lib/eco/api/microcases/people/fetch/with_each.rb +109 -0
  32. data/lib/eco/api/microcases/people/fetch/with_each_leaver.rb +33 -0
  33. data/lib/eco/api/microcases/people/fetch/with_each_present.rb +42 -0
  34. data/lib/eco/api/microcases/people/fetch/with_each_starter.rb +43 -0
  35. data/lib/eco/api/microcases/people/fetch/with_each_subordinate.rb +41 -0
  36. data/lib/eco/api/microcases/people/fetch/with_supervisor.rb +46 -0
  37. data/lib/eco/api/microcases/people/fetch.rb +23 -0
  38. data/lib/eco/api/microcases/people/integrity/fix_default_group.rb +39 -0
  39. data/lib/eco/api/microcases/people/integrity/fix_filter_tags.rb +55 -0
  40. data/lib/eco/api/microcases/people/integrity/refresh_default_tag.rb +32 -0
  41. data/lib/eco/api/microcases/people/integrity.rb +17 -0
  42. data/lib/eco/api/microcases/people/macro/take_email.rb +141 -0
  43. data/lib/eco/api/microcases/people/macro.rb +13 -0
  44. data/lib/eco/api/microcases/people/manage/cache.rb +36 -0
  45. data/lib/eco/api/microcases/people/manage/load.rb +90 -0
  46. data/lib/eco/api/microcases/people/manage/refresh.rb +59 -0
  47. data/lib/eco/api/microcases/people/manage/search.rb +118 -0
  48. data/lib/eco/api/microcases/people/manage.rb +19 -0
  49. data/lib/eco/api/microcases/people/preserve/default_tag.rb +29 -0
  50. data/lib/eco/api/microcases/people/preserve/filter_tags.rb +34 -0
  51. data/lib/eco/api/microcases/people/preserve/policy_groups.rb +36 -0
  52. data/lib/eco/api/microcases/people/preserve.rb +17 -0
  53. data/lib/eco/api/microcases/people.rb +21 -0
  54. data/lib/eco/api/microcases/person_update.rb +1 -1
  55. data/lib/eco/api/microcases/s3upload_targets.rb +1 -1
  56. data/lib/eco/api/microcases/with_each_contractor_present.rb +40 -0
  57. data/lib/eco/api/microcases.rb +3 -23
  58. data/lib/eco/api/organization/people/multiple_search_results.rb +48 -0
  59. data/lib/eco/api/organization/{people_similarity.rb → people/similarity.rb} +89 -72
  60. data/lib/eco/api/organization/people.rb +40 -66
  61. data/lib/eco/api/organization.rb +0 -1
  62. data/lib/eco/api/policies/policy.rb +7 -5
  63. data/lib/eco/api/policies.rb +9 -4
  64. data/lib/eco/api/session/batch/feedback/generate.rb +60 -0
  65. data/lib/eco/api/session/batch/feedback/getters.rb +28 -0
  66. data/lib/eco/api/session/batch/feedback/identifiers.rb +20 -0
  67. data/lib/eco/api/session/batch/feedback/job_dependencies.rb +45 -0
  68. data/lib/eco/api/session/batch/feedback/request_stat.rb +27 -0
  69. data/lib/eco/api/session/batch/feedback/request_stats.rb +270 -0
  70. data/lib/eco/api/session/batch/feedback.rb +45 -119
  71. data/lib/eco/api/session/batch/job/sets.rb +23 -0
  72. data/lib/eco/api/session/batch/job/type.rb +22 -0
  73. data/lib/eco/api/session/batch/job.rb +19 -18
  74. data/lib/eco/api/session/batch/jobs.rb +6 -2
  75. data/lib/eco/api/session/batch/launcher/mode_size.rb +1 -1
  76. data/lib/eco/api/session/batch/launcher/retry.rb +4 -4
  77. data/lib/eco/api/session/batch/launcher.rb +2 -2
  78. data/lib/eco/api/session/batch/policies.rb +4 -4
  79. data/lib/eco/api/session/batch/searcher.rb +2 -1
  80. data/lib/eco/api/session/batch.rb +0 -1
  81. data/lib/eco/api/session/config/workflow.rb +19 -9
  82. data/lib/eco/api/usecases/base_case/model.rb +54 -0
  83. data/lib/eco/api/usecases/base_case/type.rb +52 -0
  84. data/lib/eco/api/usecases/base_case.rb +5 -29
  85. data/lib/eco/api/usecases/base_io/chaining.rb +48 -0
  86. data/lib/eco/api/usecases/base_io/validations.rb +114 -0
  87. data/lib/eco/api/usecases/base_io.rb +65 -115
  88. data/lib/eco/api/usecases/cli/dsl.rb +3 -1
  89. data/lib/eco/api/usecases/default/people/treat/analyse_people_case.rb +7 -4
  90. data/lib/eco/api/usecases/default/people/treat/supers_cyclic_identify_case.rb +1 -3
  91. data/lib/eco/api/usecases/default/people/treat/supers_hierarchy_case.rb +1 -5
  92. data/lib/eco/api/usecases/default_cases/entries_to_csv_case.rb +2 -2
  93. data/lib/eco/api/usecases/default_cases/hris_case.rb +0 -2
  94. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +3 -6
  95. data/lib/eco/api/usecases/graphql/base.rb +3 -2
  96. data/lib/eco/api/usecases/graphql/helpers/base/case_env.rb +1 -1
  97. data/lib/eco/api/usecases/graphql/helpers/base/error_handling.rb +3 -3
  98. data/lib/eco/api/usecases/graphql/helpers/contractors/base/load.rb +17 -0
  99. data/lib/eco/api/usecases/graphql/helpers/contractors/base.rb +8 -0
  100. data/lib/eco/api/usecases/graphql/helpers/contractors.rb +6 -0
  101. data/lib/eco/api/usecases/graphql/helpers/location/base.rb +5 -4
  102. data/lib/eco/api/usecases/graphql/helpers/location/command.rb +2 -2
  103. data/lib/eco/api/usecases/graphql/helpers.rb +1 -0
  104. data/lib/eco/api/usecases/graphql/samples/contractors/dsl.rb +5 -0
  105. data/lib/eco/api/usecases/graphql/samples/contractors.rb +17 -0
  106. data/lib/eco/api/usecases/graphql/samples/location/service/base.rb +1 -1
  107. data/lib/eco/api/usecases/graphql/samples/location.rb +1 -1
  108. data/lib/eco/api/usecases/graphql/samples.rb +1 -0
  109. data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +0 -1
  110. data/lib/eco/api/usecases/ooze_samples/ooze_run_base_case.rb +8 -8
  111. data/lib/eco/api/usecases/use_case/chainer.rb +12 -0
  112. data/lib/eco/api/usecases/use_case.rb +32 -23
  113. data/lib/eco/api/usecases/use_case_chain/chaining.rb +88 -0
  114. data/lib/eco/api/usecases/use_case_chain.rb +17 -62
  115. data/lib/eco/api/usecases/use_case_io/chain.rb +24 -0
  116. data/lib/eco/api/usecases/use_case_io.rb +17 -22
  117. data/lib/eco/api/usecases.rb +12 -4
  118. data/lib/eco/assets.rb +1 -1
  119. data/lib/eco/cli/config/filters/people_filters.rb +6 -5
  120. data/lib/eco/cli/config/input.rb +6 -2
  121. data/lib/eco/cli/config/use_cases.rb +4 -2
  122. data/lib/eco/cli_default/input.rb +49 -29
  123. data/lib/eco/cli_default/options.rb +4 -1
  124. data/lib/eco/cli_default/people.rb +102 -47
  125. data/lib/eco/cli_default/people_filters.rb +5 -1
  126. data/lib/eco/cli_default/workflow.rb +149 -138
  127. data/lib/eco/data/mapper.rb +51 -19
  128. data/lib/eco/language/auxiliar_logger.rb +16 -3
  129. data/lib/eco/language/basic_logger.rb +1 -0
  130. data/lib/eco/language/methods/dsl_able.rb +3 -0
  131. data/lib/eco/version.rb +1 -1
  132. metadata +68 -33
  133. data/lib/eco/api/microcases/account_excluded.rb +0 -26
  134. data/lib/eco/api/microcases/core_excluded.rb +0 -20
  135. data/lib/eco/api/microcases/fix_default_group.rb +0 -33
  136. data/lib/eco/api/microcases/fix_filter_tags.rb +0 -49
  137. data/lib/eco/api/microcases/people_cache.rb +0 -30
  138. data/lib/eco/api/microcases/people_load.rb +0 -84
  139. data/lib/eco/api/microcases/people_refresh.rb +0 -53
  140. data/lib/eco/api/microcases/people_search.rb +0 -112
  141. data/lib/eco/api/microcases/preserve_default_tag.rb +0 -23
  142. data/lib/eco/api/microcases/preserve_filter_tags.rb +0 -28
  143. data/lib/eco/api/microcases/preserve_policy_groups.rb +0 -30
  144. data/lib/eco/api/microcases/refresh_default_tag.rb +0 -26
  145. data/lib/eco/api/microcases/set_account.rb +0 -18
  146. data/lib/eco/api/microcases/set_core.rb +0 -17
  147. data/lib/eco/api/microcases/set_core_with_supervisor.rb +0 -32
  148. data/lib/eco/api/microcases/set_supervisor.rb +0 -63
  149. data/lib/eco/api/microcases/take_email_from_account.rb +0 -129
  150. data/lib/eco/api/microcases/with_each.rb +0 -103
  151. data/lib/eco/api/microcases/with_each_leaver.rb +0 -27
  152. data/lib/eco/api/microcases/with_each_present.rb +0 -36
  153. data/lib/eco/api/microcases/with_each_starter.rb +0 -37
  154. data/lib/eco/api/microcases/with_each_subordinate.rb +0 -33
  155. data/lib/eco/api/microcases/with_supervisor.rb +0 -35
  156. data/lib/eco/api/session/batch/request_stats.rb +0 -266
@@ -0,0 +1,55 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Integrity
6
+ module FixFilterTags
7
+ # Helper that makes sure the **custom `tags`** are preserved.
8
+ # @note
9
+ # - this feature is essential to preserve custom `tags` in users that have register tags.
10
+ # - for this to work out, it requires a `tagtree` to be defined.
11
+ # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes already done.
12
+ # @param options [Hash] the options.
13
+ # @option options [Hash<Symbol, Object>] :filter_tags options around `filter_tags`.
14
+ # * `:preserve_custom` (Boolean) [true] indicates if original tags that are not in the tree should be added/preserved.
15
+ # * `:add_custom` (Boolean) [true] indicates if target tags that are not in the tree should be really added.
16
+ def fix_filter_tags(person, options)
17
+ return unless session.tagtree
18
+
19
+ filter_tags_excluded =
20
+ options.dig(:exclude, :core) ||
21
+ options.dig(:exclude, :filter_tags)
22
+
23
+ return if !person.new? && filter_tags_excluded
24
+
25
+ person.filter_tags = session.tagtree.user_tags(
26
+ initial: person.original_doc['filter_tags'] || [],
27
+ final: person.filter_tags,
28
+ preserve_custom: _fix_filter_tags_preserve_custom?(options),
29
+ add_custom: _fix_filter_tags_add_custom?(options)
30
+ )
31
+ end
32
+
33
+ private
34
+
35
+ # default `true`
36
+ def _fix_filter_tags_preserve_custom?(options)
37
+ key_defined = options.key?(:filter_tags) && options[:filter_tags].key?(:preserve_custom)
38
+ return true unless key_defined
39
+
40
+ options.dig(:filter_tags, :preserve_custom)
41
+ end
42
+
43
+ # default `true`
44
+ def _fix_filter_tags_add_custom?(options)
45
+ key_defined = options.key?(:filter_tags) && options[:filter_tags].key?(:add_custom)
46
+ return true unless key_defined
47
+
48
+ options.dig(:filter_tags, :add_custom)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,32 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Integrity
6
+ module RefreshDefaultTag
7
+ # When the input data, or `entry`, does not provide the `default_tag`,
8
+ # it sets the `default_tag` of the user following some criteria
9
+ # @note it assumes `default_tag` has been already set to `person.account`
10
+ # @param entry [PersonEntry] the input entry with the data we should set on person.
11
+ # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
12
+ # @param options [Hash] the options
13
+ def refresh_default_tag(entry, person, options)
14
+ return unless person.account
15
+ return if options.dig(:exclude, :account)
16
+ return if options.dig(:exclude, :filter_tags)
17
+ return if options.dig(:exclude, :default_tag)
18
+ return if entry&.default_tag?
19
+
20
+ if session.tagtree
21
+ person.account.default_tag = session.tagtree.default_tag(*person.filter_tags)
22
+ else
23
+ tags = person.filter_tags || []
24
+ person.account.default_tag = tags.first unless tags.length > 1
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'integrity/refresh_default_tag'
2
+ require_relative 'integrity/fix_filter_tags'
3
+ require_relative 'integrity/fix_default_group'
4
+
5
+ module Eco
6
+ module API
7
+ class MicroCases
8
+ module People
9
+ module Integrity
10
+ include RefreshDefaultTag
11
+ include FixFilterTags
12
+ include FixDefaultGroup
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,141 @@
1
+ # rubocop:disable Metrics/BlockNesting, Layout/LineLength
2
+ module Eco
3
+ module API
4
+ class MicroCases
5
+ module People
6
+ module Macro
7
+ module TakeEmail
8
+ # Frees up `target_email` from an account not present in this org.
9
+ # Allows to force `target_email` on the current user's account.
10
+ # - If the person does not have account, this case will not do anything.
11
+ # - If `original_doc['account']` is `nil` (no account on server side), this case will not do anything.
12
+ # - If the `target_email` and the `current_email` are the same or empty, this case will not do anything.
13
+ # @note
14
+ # - **It does not do the final update to the server to the `target_email`**.
15
+ # You will need to do this part yourself.
16
+ # - You would call this function only when you got an error of `email already taken`.
17
+ # - If the `target_email` is associated to a user in the same org, this will fail.
18
+ # @param person [Ecoportal::API::V1::Person] the person we want to update,
19
+ # carrying the changes to be done.
20
+ # @param dest_email [String, Proc] the email that we will move the other account to,
21
+ # when we free up `target_email`.
22
+ # @param target_email [String] the email that we want to free up from another account and bring to ours.
23
+ # If it's empty, the `person.email` will be used instead.
24
+ # @param options [Hash] the options.
25
+ # @param current_email [String] the email that the person's account is currently linked.
26
+ # As the current email should be associated with this person's account on server side,
27
+ # we use `original_doc['email']`.
28
+ # @param context [String] main core part of logs. Provides context to the logs.
29
+ def take_email_from_account( # rubocop:disable Metrics/AbcSize
30
+ person,
31
+ dest_email:,
32
+ target_email: nil,
33
+ options: {},
34
+ context: 'Session'
35
+ )
36
+ return false if options.dig(:exclude, :account)
37
+ return false unless (account = person.account)
38
+ return false unless (had_account = person.original_doc['account']) # rubocop:disable Lint/UselessAssignment
39
+
40
+ target_email ||= person.email
41
+ account_email = person.original_doc['email']
42
+
43
+ return false unless target_email != account_email
44
+ return false if account_email.to_s.strip.empty?
45
+ return false if target_email.to_s.strip.empty?
46
+
47
+ if dest_email.is_a?(String)
48
+ return false unless target_email != dest_email
49
+ return false unless dest_email != account_email
50
+ return false if dest_email.to_s.strip.empty?
51
+ end
52
+
53
+ account_json = _take_email_account_json(account)
54
+ person.email = account_email
55
+
56
+ if (success = _take_email_remove_account!(person, context: context))
57
+ if (success = _take_email_acquire_account!(person, target_email, account: {}, context: context))
58
+ if (success = _take_email_email_free_up!(person, dest_email: dest_email, context: context))
59
+ if (success = _take_email_remove_account!(person, context: context))
60
+ # Bring back the original account
61
+ if (success = _take_email_acquire_account!(person, account_email, account: account_json, context: context)) # rubocop:disable Style/SoleNestedConditional
62
+ success = true
63
+ person.email = target_email
64
+ end
65
+ end
66
+ else # free up target email
67
+ # restore
68
+ reverted = false
69
+ if reverted ||= _take_email_remove_account!(person, context: context)
70
+ reverted ||= _take_email_acquire_account!(person, account_email, account: account_json, context: context)
71
+ end
72
+
73
+ unless reverted
74
+ msg = "Could not revert back to the original account #{person.identify}"
75
+ log(:debug) { msg }
76
+ puts msg
77
+ end
78
+
79
+ success = false
80
+ end
81
+ else # aquire other account
82
+ # restore
83
+ unless _take_email_acquire_account!(person, account_email, account: account_json, context: context)
84
+ msg = 'Could not bring back the original account that '
85
+ msg << "we want to update the email to '#{target_email}' #{person.identify}"
86
+ log(:debug) { msg }
87
+ puts msg
88
+ end
89
+
90
+ success = false
91
+ end
92
+ end
93
+
94
+ success
95
+ end
96
+
97
+ private
98
+
99
+ def _take_email_account_json(account)
100
+ JSON.parse(account.to_json).tap do |hash|
101
+ hash.delete('user_id')
102
+ hash.delete('permissions_merged')
103
+ hash.delete('permissions_preset')
104
+ hash.delete('prefilter')
105
+
106
+ if (pref = hash['preferences'])
107
+ hash['preferences'] = pref.reject do |attr, _value|
108
+ attr.start_with?('kiosk')
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ # Bring the account of the `target_email` taken, so we can change the email of this account
115
+ def _take_email_acquire_account!(person, target_email, account: {}, context: 'Session')
116
+ person.account = account
117
+ person.account.send_invites = false
118
+ person.email = target_email
119
+ micro.person_update!(person, reason: "bring account with email '#{target_email}'", context: context)
120
+ end
121
+
122
+ # Free up the email (`target_email`) of the account that has it taken to `dest_email`
123
+ def _take_email_email_free_up!(person, dest_email:, target_email: nil, context: 'Session')
124
+ target_email ||= person.email
125
+ person.email = dest_email.is_a?(Proc)? dest_email.call(target_email) : dest_email
126
+ reason = "free up email '#{target_email}', by moving account to '#{person.email}'"
127
+ micro.person_update!(person, reason: reason, context: context)
128
+ end
129
+
130
+ def _take_email_remove_account!(person, context: 'Session')
131
+ person.account = nil
132
+ micro.person_update!(person, reason: 'remove account', context: context)
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ # rubocop:enable Metrics/BlockNesting, Layout/LineLength
@@ -0,0 +1,13 @@
1
+ require_relative 'macro/take_email'
2
+
3
+ module Eco
4
+ module API
5
+ class MicroCases
6
+ module People
7
+ module Macro
8
+ include TakeEmail
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Manage
6
+ module Cache
7
+ # Helper to locally cache the people manager.
8
+ # @param filename [String] the name of the file where the data should be cached.
9
+ # @return [Eco::API::Organization::People] the `People` object with the data.
10
+ def people_cache(filename = enviro.config.people.cache)
11
+ log(:info) { 'Going to get all the people via API' }
12
+
13
+ start = Time.now
14
+ people = session.batch.get_people
15
+ secs = (Time.now - start).round(3)
16
+ cnt = people.count
17
+ per_sec = (cnt.to_f / secs).round(2)
18
+
19
+ log(:info) {
20
+ "Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)"
21
+ }
22
+
23
+ file = file_manager.save_json(people, filename, :timestamp)
24
+
25
+ log(:info) {
26
+ "#{people.length} people loaded and saved locally to #{file}."
27
+ }
28
+
29
+ Eco::API::Organization::People.new(people)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,90 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Manage
6
+ module Load
7
+ # Helper to load `People` that works in different phases:
8
+ # 1. first tries to get the newest cached file that follows `filename` pattern
9
+ # - if not the newest, it tries to find the specific filename
10
+ # 2. if it succeeds to identify a cached file, it loads it
11
+ # - if it fails, it tries to get people from the server
12
+ # @note
13
+ # - `filename` will be relative to the working directory (the one of the session `enviro` set by the user).
14
+ # @param filename [String] the name of the file where the cached data is to be found.
15
+ # @param modifier [Array<Symbol>] modifiers to specify how this function should proceed:
16
+ # - `:newest` if it should try to find the newest file (pattern alike).
17
+ # - `:api` if it should try to get people from the server in case there's no cache.
18
+ # - `:file` if it is supposed to load people from a file.
19
+ # - `:save` if it is supposed to cache/save the data locally once obtained people from the server (`:api`)
20
+ # @return [Eco::API::Organization::People] the `People` object with the data.
21
+ def people_load(filename = enviro.config.people.cache, modifier: %i[newest api]) # rubocop:disable Metrics/AbcSize
22
+ modifier = [modifier].flatten
23
+ load_file = %i[file newest].any? {|flag| modifier.include?(flag)}
24
+
25
+ case
26
+ when filename && load_file
27
+ file = people_load_filename(filename, newest: modifier.include?(:newest))
28
+
29
+ if file
30
+ file_manager.load_json(file).tap do |people|
31
+ next unless people.is_a?(Array)
32
+
33
+ log(:info) {
34
+ "#{people&.length} people loaded from file #{file}"
35
+ }
36
+ end
37
+ else
38
+ log(:error) {
39
+ "could not find the file #{file_manager.dir.file(filename)}"
40
+ }
41
+
42
+ exit unless modifier.include?(:api)
43
+
44
+ people_load(modifier: modifier - %i[newest file])
45
+ end
46
+ when modifier.include?(:api)
47
+ log(:info) { 'Going to get all the people via API (load)' }
48
+
49
+ start = Time.now
50
+ session.batch.get_people.tap do |people|
51
+ secs = (Time.now - start).round(3)
52
+ cnt = people.count
53
+ per_sec = (cnt.to_f / secs).round(2)
54
+
55
+ log(:info) {
56
+ "Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)"
57
+ }
58
+
59
+ if modifier.include?(:save) && people && people.length.positive?
60
+ file = file_manager.save_json(people, filename, :timestamp)
61
+ log(:info) { "#{people.length} people saved to file #{file}." }
62
+ end
63
+ end
64
+ end.then do |people|
65
+ Eco::API::Organization::People.new(people)
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ def people_load_filename(filename, newest: false)
72
+ if newest
73
+ # search input file based on pattern (in case the name has a timestamp)
74
+ file_manager.dir.newest_file(file: filename).tap do |file|
75
+ next unless file
76
+
77
+ log(:info) {
78
+ "previous file found: #{file}"
79
+ }
80
+ end
81
+ else
82
+ file_manager.dir.file(filename, should_exist: true)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,59 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Manage
6
+ module Refresh
7
+ # Helper to obtain all the elements of `people` anew from the _People Manager_.
8
+ # @note
9
+ # 1. This helper is normally used to run consecutive usecases, where data needs refresh.
10
+ # 2. It only includes new people if they are not dirty (they do not have pending updates)
11
+ # - This contingency wouldn't be necessary if the server worked perfectly.
12
+ # @param people [Eco::API::Organization::People] the people that needs refresh.
13
+ # @param include_created [Boolean] include people created during this session? (will check `:create` batch jobs).
14
+ # @return [Eco::API::Organization::People] the `People` object with the data.
15
+ def people_refresh(people:, include_created: true) # rubocop:disable Metrics/AbcSize
16
+ people = people.newFrom people.select do |person|
17
+ !person.new? || !person.dirty?
18
+ end
19
+
20
+ ini = people.length
21
+
22
+ if include_created
23
+ session.job_groups.find_jobs(type: :create).map do |job|
24
+ to_add = job.people.reject(&:dirty?)
25
+ people = people.merge(to_add)
26
+ end
27
+ end
28
+
29
+ created = people.length - ini
30
+ msg = "Going to refresh #{people.length} people with server data"
31
+ msg << " (including #{created} that were created)" if created.positive?
32
+ log(:info) { msg }
33
+
34
+ start = Time.now
35
+ entries = session.batch.get_people(people, silent: true)
36
+ secs = (Time.now - start).round(3)
37
+ cnt = entries.count
38
+ per_sec = (cnt.to_f / secs).round(2)
39
+
40
+ log(:info) {
41
+ "Re-loaded #{cnt} people (out of #{people.length}) in #{secs} seconds (#{per_sec} people/sec)"
42
+ }
43
+
44
+ missing = people.length - entries.length
45
+
46
+ if missing.positive?
47
+ log(:error) {
48
+ "Missed to obtain #{missing} people during the refresh"
49
+ }
50
+ end
51
+
52
+ Eco::API::Organization::People.new(entries)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,118 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Manage
6
+ module Search
7
+ # Helper to search/obtain people from `data` against the server (_People Manager_).
8
+ # @note
9
+ # - this helper is normally used to **get partial** part of the people manager.
10
+ # - therefore, normally used with _**delta** input files_ (files with only the differences).
11
+ # @param data [Eco::API::Organization::People, Enumerable<Person>, Enumerable<Hash>]
12
+ # `People` to search against the server.
13
+ # @param options [Hash] the options.
14
+ # @param silent [Boolean] `false` if low level search messages should be shown.
15
+ # @return [Eco::API::Organization::People] the `People` object with the found persons.
16
+ def people_search(data, options: {}, silent: false) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
17
+ log(:info) { "Going to api get #{data.length} entries..." }
18
+
19
+ silent &&= data.count <= 500
20
+
21
+ start = Time.now
22
+ people = session.batch.search(data, silent: silent).then do |status|
23
+ secs = (Time.now - start).round(3)
24
+
25
+ Eco::API::Organization::People.new(status.people).tap do |people| # rubocop:disable Lint/ShadowingOuterLocalVariable
26
+ cnt = people.count
27
+ per_sec = (cnt.to_f / secs).round(2)
28
+
29
+ msg = "... could get #{cnt} people "
30
+ msg << "(out of #{data.length} entries) in #{secs} seconds (#{per_sec} people/sec)"
31
+
32
+ log(:info) { msg }
33
+ end
34
+ end
35
+
36
+ # get the supervisors of found people (current supervisors)
37
+ supers = people_search_prepare_supers_request(people)
38
+ if supers.length.positive?
39
+ log(:info) {
40
+ " Going to api get #{supers.length} current supervisors..."
41
+ }
42
+
43
+ start = Time.now
44
+ people = session.batch.search(supers, silent: silent).then do |status|
45
+ secs = (Time.now - start).round(3)
46
+ found = status.people
47
+ cnt = found.count
48
+ per_sec = (cnt.to_f / secs).round(2)
49
+
50
+ msg = "... could find #{cnt} current supers "
51
+ msg << "(out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
52
+ log(:info) { msg }
53
+
54
+ people.merge(found, strict: micro.strict_search?(options))
55
+ end
56
+ end
57
+
58
+ # get the supervisors referred in the input data (future supervisors)
59
+ supers = people_search_prepare_supers_request(data, people)
60
+ if supers.length.positive?
61
+ log(:info) {
62
+ " Going to api get #{supers.length} supervisors as per input entries..."
63
+ }
64
+
65
+ start = Time.now
66
+ people = session.batch.search(supers, silent: silent).then do |status|
67
+ secs = (Time.now - start).round(3)
68
+ found = status.people
69
+ cnt = found.count
70
+ per_sec = (cnt.to_f / secs).round(2)
71
+
72
+ msg = "... could find #{cnt} input supers "
73
+ msg << "(out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
74
+ log(:info) { msg }
75
+
76
+ people.merge(found, strict: micro.strict_search?(options))
77
+ end
78
+ end
79
+
80
+ log(:info) {
81
+ "Finally got #{people.length} people (out of #{data.length} entries)"
82
+ }
83
+
84
+ people
85
+ end
86
+
87
+ private
88
+
89
+ # Prepares a unique request with only the supervisor ids missing in `people`
90
+ def people_search_prepare_supers_request(data, people = data)
91
+ data.each_with_object([]) do |entry, request|
92
+ spr = {'id' => (sup_id = people_search_super_id(entry))}
93
+ next if !sup_id || request.include?(spr)
94
+
95
+ micro.with_supervisor(sup_id, people) do |supervisor|
96
+ request.push(spr) unless supervisor
97
+ end
98
+ end
99
+ end
100
+
101
+ # Gets the `supervisor_id` from `value`
102
+ def people_search_super_id(value)
103
+ sup_id =
104
+ if value.respond_to?(:supervisor_id)
105
+ value.supervisor_id
106
+ elsif value.is_a?(Hash) && value.key('supervisor_id')
107
+ value['supervisor_id']
108
+ end
109
+
110
+ sup_id = nil if sup_id.to_s.strip.empty?
111
+ sup_id
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'manage/cache'
2
+ require_relative 'manage/load'
3
+ require_relative 'manage/search'
4
+ require_relative 'manage/refresh'
5
+
6
+ module Eco
7
+ module API
8
+ class MicroCases
9
+ module People
10
+ module Manage
11
+ include Cache
12
+ include Load
13
+ include Search
14
+ include Refresh
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Preserve
6
+ module DefaultTag
7
+ # Helper to preserve the original `default_tag`.
8
+ # @note
9
+ # 1. It only works if the original value of `default_tag` was **not** empty
10
+ # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
11
+ # @param options [Hash] the options.
12
+ # @return [String] the final value of `default_tag`.
13
+ def preserve_default_tag(person, _options)
14
+ return unless (account = person.account)
15
+
16
+ account.default_tag.tap do
17
+ next unless account.as_update.key?('default_tag')
18
+ next unless (original = person.original_doc.dig('account', 'default_tag'))
19
+
20
+ person.account.default_tag = original
21
+ return original
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ module Eco
2
+ module API
3
+ class MicroCases
4
+ module People
5
+ module Preserve
6
+ module FilterTags
7
+ # Helper to preserve the original filter tags.
8
+ # @note
9
+ # 1. It only works if the original value of `filter_tags` was **not** empty
10
+ # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
11
+ # @param options [Hash] the options.
12
+ # @param keep_new [Boolean] tells if it should keep the new tags or get rid of them.
13
+ # @return [Array<String>] the final value of `filter_tags`.
14
+ def preserve_filter_tags(person, _options, keep_new: false)
15
+ person.filter_tags.tap do
16
+ next unless person.as_update.key?('filter_tags')
17
+ next unless (original = person.original_doc['filter_tags'])
18
+ next if original.empty?
19
+
20
+ if keep_new
21
+ person.filter_tags += original
22
+ else
23
+ person.filter_tags = original
24
+ end
25
+
26
+ return person.filter_tags
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end