eco-helpers 2.0.22 → 2.0.27

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +95 -5
  3. data/lib/eco/api/common.rb +0 -1
  4. data/lib/eco/api/common/loaders.rb +2 -0
  5. data/lib/eco/api/common/loaders/base.rb +58 -0
  6. data/lib/eco/api/common/loaders/case_base.rb +33 -0
  7. data/lib/eco/api/common/loaders/error_handler.rb +2 -2
  8. data/lib/eco/api/common/loaders/parser.rb +30 -5
  9. data/lib/eco/api/common/loaders/policy.rb +1 -1
  10. data/lib/eco/api/common/loaders/use_case.rb +1 -1
  11. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +129 -1
  12. data/lib/eco/api/common/people/entries.rb +83 -14
  13. data/lib/eco/api/common/people/entry_factory.rb +11 -10
  14. data/lib/eco/api/common/people/person_attribute_parser.rb +8 -0
  15. data/lib/eco/api/common/people/person_entry.rb +7 -6
  16. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +55 -16
  17. data/lib/eco/api/common/people/person_factory.rb +4 -2
  18. data/lib/eco/api/common/people/person_parser.rb +7 -1
  19. data/lib/eco/api/common/people/supervisor_helpers.rb +1 -1
  20. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +0 -8
  21. data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +0 -8
  22. data/lib/eco/api/microcases/set_core_with_supervisor.rb +4 -2
  23. data/lib/eco/api/microcases/set_supervisor.rb +29 -8
  24. data/lib/eco/api/microcases/with_each.rb +7 -3
  25. data/lib/eco/api/microcases/with_each_starter.rb +3 -2
  26. data/lib/eco/api/organization/people.rb +7 -1
  27. data/lib/eco/api/session.rb +7 -2
  28. data/lib/eco/api/session/batch.rb +1 -1
  29. data/lib/eco/api/session/batch/job.rb +42 -9
  30. data/lib/eco/api/usecases/default_cases/create_case.rb +10 -1
  31. data/lib/eco/api/usecases/default_cases/create_details_case.rb +10 -1
  32. data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +10 -1
  33. data/lib/eco/api/usecases/default_cases/hris_case.rb +25 -1
  34. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +1 -37
  35. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +42 -0
  36. data/lib/eco/api/usecases/default_cases/upsert_case.rb +10 -1
  37. data/lib/eco/cli/config/default/input.rb +2 -2
  38. data/lib/eco/cli/config/default/options.rb +44 -7
  39. data/lib/eco/cli/config/default/usecases.rb +16 -0
  40. data/lib/eco/cli/config/default/workflow.rb +7 -4
  41. data/lib/eco/cli/config/filters.rb +6 -2
  42. data/lib/eco/cli/config/filters/input_filters.rb +3 -2
  43. data/lib/eco/cli/config/filters/people_filters.rb +3 -2
  44. data/lib/eco/cli/config/help.rb +1 -1
  45. data/lib/eco/cli/config/options_set.rb +6 -4
  46. data/lib/eco/cli/config/use_cases.rb +6 -3
  47. data/lib/eco/csv.rb +2 -0
  48. data/lib/eco/language/models/collection.rb +5 -2
  49. data/lib/eco/version.rb +1 -1
  50. metadata +3 -2
  51. data/lib/eco/api/common/base_loader.rb +0 -72
@@ -7,16 +7,20 @@ module Eco
7
7
  # @param entries [Eco::API::Common::People::Entries] the input entries with the data.
8
8
  # @param people [Eco::API::Organization::People] target existing _People_ of the current update.
9
9
  # @param options [Hash] the options.
10
+ # @param append_created [Boolean] whether or not a new person will be added to the `people` object.
10
11
  # @yield [entry, person] gives each entry, and the paired person thereof (new or existing).
11
12
  # @yieldparam entry [PersonEntry] the input entry with the data we should set on person.
12
13
  # @yieldparam person [Ecoportal::API::V1::Person] the found person that matches `entry`, or a new person otherwise.
13
14
  # @return [Eco::API::Organization::People] all the people, including new and existing ones.
14
- def with_each(entries, people, options)
15
+ def with_each(entries, people, options, append_created: true)
15
16
  @_skip_all_multiple_results = false
17
+ people_copy = people.newFrom(people.to_a)
16
18
  entries.each_with_object([]) do |entry, scoped|
17
19
  begin
18
- unless person = people.find(entry, strict: micro.strict_search?(options))
19
- person = session.new_person
20
+ unless person = people_copy.find(entry, strict: micro.strict_search?(options))
21
+ person = session.new_person.tap do |person|
22
+ people << person if append_created
23
+ end
20
24
  end
21
25
  rescue Eco::API::Organization::People::MultipleSearchResults => e
22
26
  unless @_skip_all_multiple_results
@@ -8,13 +8,14 @@ module Eco
8
8
  # @param people [Eco::API::Organization::People] target existing _People_ of the current update.
9
9
  # @param options [Hash] the options.
10
10
  # @param log_present [Boolean] log error message if an `entry` has match in `people`.
11
+ # @param append_created [Boolean] whether or not a new person will be added to the `people` object.
11
12
  # @yield [entry, person] gives each **new** `person` of `entries` that is not present in `people`.
12
13
  # @yieldparam entry [PersonEntry] the input entry with the data we should set on person.
13
14
  # @yieldparam person [Ecoportal::API::V1::Person] the **new** person.
14
15
  # @return [Eco::API::Organization::People] the starters.
15
- def with_each_starter(entries, people, options, log_present: false)
16
+ def with_each_starter(entries, people, options, log_present: false, append_created: true)
16
17
  starters = []
17
- micro.with_each(entries, people, options) do |entry, person|
18
+ micro.with_each(entries, people, options, append_created: append_created) do |entry, person|
18
19
  if !person.new?
19
20
  if log_present
20
21
  session.logger.error("This person (id: '#{person.id}') already exists: #{entry.to_s(:identify)}")
@@ -210,6 +210,12 @@ module Eco
210
210
  to_h(:supervisor_id)
211
211
  end
212
212
 
213
+ def group_by_schema
214
+ to_h do |person|
215
+ person.details && person.details.schema_id
216
+ end
217
+ end
218
+
213
219
  def to_h(attr = "id")
214
220
  super(attr || "id")
215
221
  end
@@ -252,7 +258,7 @@ module Eco
252
258
 
253
259
  def init_caches
254
260
  return if @caches_init
255
- @by_id = to_h
261
+ @by_id = no_nil_key(to_h)
256
262
  @by_external_id = no_nil_key(to_h('external_id'))
257
263
  @by_users_email = no_nil_key(existing_users.to_h('email'))
258
264
  @by_non_users_email = no_nil_key(non_users.to_h('email'))
@@ -153,9 +153,14 @@ module Eco
153
153
  # Generates an entries collection from a csv input file.
154
154
  # @see Eco::API::Common::People::EntryFactory#entries
155
155
  # @param file [String] file to generate the entries from.
156
+ # @param (see Eco::API::Session#entries)
156
157
  # @return [Eco::API::Common::People::Entries] collection of entries.
157
- def csv_entries(file)
158
- return entries(file: file, format: :csv)
158
+ def csv_entries(file, **kargs)
159
+ kargs.merge!({
160
+ file: file,
161
+ format: :csv
162
+ })
163
+ return entries(**kargs)
159
164
  end
160
165
 
161
166
  # Generates the collection of entries that should be discarded from an update.
@@ -137,7 +137,7 @@ module Eco
137
137
  rescue error_type => e
138
138
  raise unless retries_left > 0
139
139
  explanation = "Batch TimeOut. You have #{retries_left} retries left."
140
- prompt_user("Do you want to retry (y/N)?", explanation, default: "Y", timeout: 10) do |response|
140
+ prompt_user(" Do you want to retry (y/N)?", default: "Y", explanation: explanation, timeout: 10) do |response|
141
141
  if response.upcase.start_with?("Y")
142
142
  offer_retry_on(error_type, retries_left - 1, &block)
143
143
  else
@@ -164,12 +164,17 @@ module Eco
164
164
  # @return [Eco::API::Session::Batch::Status]
165
165
  def launch(simulate: false)
166
166
  pqueue = processed_queue
167
- @requests = pqueue.map {|e| as_update(e)}
167
+ @requests = as_update(pqueue)
168
168
  pre_checks(requests, simulate: simulate)
169
169
 
170
- unless simulate
170
+ if simulate
171
+ if options.dig(:requests, :backup)
172
+ req_backup = as_update(pqueue, add_feedback: false)
173
+ backup_update(req_backup, simulate: simulate)
174
+ end
175
+ else
171
176
  if pqueue.length > 0
172
- req_backup = pqueue.map {|e| as_update(e, add_feedback: false)}
177
+ req_backup = as_update(pqueue, add_feedback: false)
173
178
  backup_update(req_backup)
174
179
  session.batch.launch(pqueue, method: type).tap do |job_status|
175
180
  @status = job_status
@@ -220,13 +225,26 @@ module Eco
220
225
  end.join("\n")
221
226
  end
222
227
 
223
- def as_update(*args)
224
- feedback.as_update(*args)
228
+ def as_update(data, *args)
229
+ if data.is_a?(Array)
230
+ data.map do |e|
231
+ feedback.as_update(e, *args)
232
+ end.compact.select {|e| e && !e.empty?}
233
+ else
234
+ feedback.as_update(data, *args)
235
+ end
225
236
  end
226
237
 
227
238
  def processed_queue
228
239
  @queue.each {|e| @callbacks[e].call(e) if @callbacks.key?(e) }
229
- apply_policies(api_included(@queue)).select {|e| !as_update(e).empty?}
240
+ apply_policies(api_included(@queue)).select do |e|
241
+ !as_update(e).empty?
242
+ end.select do |e|
243
+ next true unless e.is_a?(Ecoportal::API::V1::Person)
244
+ next true unless e.new?
245
+ # new people should either have account or details
246
+ e.account || e.details
247
+ end
230
248
  end
231
249
 
232
250
  # if there is a config definition to exclude entries
@@ -235,7 +253,13 @@ module Eco
235
253
  def api_included(full_queue)
236
254
  return full_queue if type == :create
237
255
  return full_queue unless excluded = session.config.people.api_excluded
238
- full_queue.select {|entry| !excluded.call(entry, session, options, self)}
256
+ if options.dig(:include, :excluded, :only)
257
+ full_queue.select {|entry| excluded.call(entry, session, options, self)}
258
+ elsif options.dig(:include, :excluded)
259
+ full_queue
260
+ else
261
+ full_queue.select {|entry| !excluded.call(entry, session, options, self)}
262
+ end
239
263
  end
240
264
 
241
265
  # Applies the changes introduced by api policies
@@ -280,6 +304,9 @@ module Eco
280
304
  if !simulate && status
281
305
  status.queue.map do |entry|
282
306
  if status.success?(entry)
307
+ if type == :create && entry.respond_to?(:id=)
308
+ entry.id = status[entry].body["id"]
309
+ end
283
310
  entry.consolidate! if entry.respond_to?(:consolidate!)
284
311
  #else # do not entry.reset! (keep track on changes still)
285
312
  end
@@ -300,16 +327,22 @@ module Eco
300
327
  end
301
328
  end
302
329
  elsif simulate
330
+ fake_id = 111111111111111111111111
303
331
  queue.map do |entry|
332
+ if type == :create && entry.respond_to?(:id=)
333
+ entry.id = fake_id.to_s
334
+ fake_id += 1
335
+ end
304
336
  entry.consolidate! if entry.respond_to?(:consolidate!)
305
337
  end
306
338
  end
307
339
  end
308
340
 
309
341
  # Keep a copy of the requests for future reference
310
- def backup_update(requests)
342
+ def backup_update(requests, simulate: false)
343
+ dry_run = simulate ? "_dry_run" : ""
311
344
  dir = config.people.requests_folder
312
- file = File.join(dir, "#{type}_data.json")
345
+ file = File.join(dir, "#{type}_data#{dry_run}.json")
313
346
  file_manager.save_json(requests, file, :timestamp)
314
347
  end
315
348
 
@@ -2,12 +2,15 @@ class Eco::API::UseCases::DefaultCases::CreateCase < Eco::API::Common::Loaders::
2
2
  name "create"
3
3
  type :sync
4
4
 
5
+ attr_reader :options
6
+
5
7
  def main(entries, people, session, options, usecase)
8
+ options = @options
6
9
  micro = session.micro
7
10
  creation = session.new_job("main", "create", :create, usecase)
8
11
  supers = session.new_job("post", "supers", :update, usecase, :core)
9
12
 
10
- micro.with_each_starter(entries, people, options, log_present: true) do |entry, person|
13
+ micro.with_each_starter(entries, people, options, log_present: true, append_created: append_created) do |entry, person|
11
14
  creation.add(person)
12
15
  micro.set_core_with_supervisor(entry, person, people, supers, options)
13
16
  entry.set_details(person) unless options.dig(:exclude, :details)
@@ -15,4 +18,10 @@ class Eco::API::UseCases::DefaultCases::CreateCase < Eco::API::Common::Loaders::
15
18
  end
16
19
  end
17
20
 
21
+ private
22
+
23
+ def append_created
24
+ options.dig(:people, :append_created)
25
+ end
26
+
18
27
  end
@@ -2,15 +2,24 @@ class Eco::API::UseCases::DefaultCases::CreateDetailsCase < Eco::API::Common::Lo
2
2
  name "create-details"
3
3
  type :sync
4
4
 
5
+ attr_reader :options
6
+
5
7
  def main(entries, people, session, options, usecase)
8
+ @options = options
6
9
  micro = session.micro
7
10
  creation = session.new_job("main", "create", :create, usecase)
8
11
 
9
- micro.with_each_starter(entries, people, options, log_present: true) do |entry, person|
12
+ micro.with_each_starter(entries, people, options, log_present: true, append_created: append_created) do |entry, person|
10
13
  creation.add(person)
11
14
  micro.set_core(entry, person, options)
12
15
  entry.set_details(person) unless options.dig(:exclude, :details)
13
16
  end
14
17
  end
15
18
 
19
+ private
20
+
21
+ def append_created
22
+ options.dig(:people, :append_created)
23
+ end
24
+
16
25
  end
@@ -2,16 +2,25 @@ class Eco::API::UseCases::DefaultCases::CreateDetailsWithSupervisorCase < Eco::A
2
2
  name "create-details-with-supervisor"
3
3
  type :sync
4
4
 
5
+ attr_reader :options
6
+
5
7
  def main(entries, people, session, options, usecase)
8
+ @options = options
6
9
  micro = session.micro
7
10
  creation = session.new_job("main", "create", :create, usecase)
8
11
  supers = session.new_job("post", "supers", :update, usecase, :core)
9
12
 
10
- micro.with_each_starter(entries, people, options, log_present: true) do |entry, person|
13
+ micro.with_each_starter(entries, people, options, log_present: true, append_created: append_created) do |entry, person|
11
14
  creation.add(person)
12
15
  micro.set_core_with_supervisor(entry, person, people, supers, options)
13
16
  entry.set_details(person) unless options.dig(:exclude, :details)
14
17
  end
15
18
  end
16
19
 
20
+ private
21
+
22
+ def append_created
23
+ options.dig(:people, :append_created)
24
+ end
25
+
17
26
  end
@@ -3,8 +3,11 @@ class Eco::API::UseCases::DefaultCases::HrisCase < Eco::API::Common::Loaders::Us
3
3
  type :sync
4
4
 
5
5
  attr_reader :creation, :update, :supers, :leavers
6
+ attr_reader :people, :session, :options
6
7
 
7
8
  def main(entries, people, session, options, usecase)
9
+ @session = session; @options = options; @people = people
10
+ require_only_one_schema!
8
11
  micro = session.micro
9
12
  @creation = session.new_job("main", "create", :create, usecase)
10
13
  @update = session.new_job("main", "update", :update, usecase)
@@ -15,7 +18,7 @@ class Eco::API::UseCases::DefaultCases::HrisCase < Eco::API::Common::Loaders::Us
15
18
  leavers.add(person, &method(:leavers_callback))
16
19
  end
17
20
 
18
- micro.with_each(entries, people, options) do |entry, person|
21
+ micro.with_each(entries, people, options, append_created: append_created) do |entry, person|
19
22
  person.new? ? creation.add(person) : update.add(person)
20
23
  micro.set_core_with_supervisor(entry, person, people, supers, options)
21
24
  entry.set_details(person) unless options.dig(:exclude, :details)
@@ -25,9 +28,30 @@ class Eco::API::UseCases::DefaultCases::HrisCase < Eco::API::Common::Loaders::Us
25
28
 
26
29
  private
27
30
 
31
+ def append_created
32
+ options.dig(:people, :append_created)
33
+ end
34
+
28
35
  def leavers_callback(person)
29
36
  person.supervisor_id = nil
30
37
  person.account = nil if person.account
31
38
  end
32
39
 
40
+ def require_only_one_schema!
41
+ unless schema_id = options.dig(:people, :filter, :details, :schema_id)
42
+ active_schema = session.schema
43
+ other_schemas = session.schemas.map(&:id) - [active_schema.id]
44
+ other_people = people.group_by_schema.values_at(*other_schemas).map(&:to_a).flatten
45
+ if other_people.length > 3
46
+ msg = "There are #{other_people.length} people in schemas other than #{active_schema.name}."
47
+ msg << " Please, use the filter option '-schema_id SchemaName' for the 'hris' case to only include those of that schema"
48
+ msg << " in the current update. The HRIS case identifies people that are not in the file as leavers"
49
+ msg << " (as it will remove the account of all the people of other schemas if they are not in the input file)."
50
+ msg << "\n For example: -schema-id '#{active_schema.name.downcase}'"
51
+ logger.error(msg)
52
+ raise msg
53
+ end
54
+ end
55
+ end
56
+
33
57
  end
@@ -125,43 +125,7 @@ class Eco::API::UseCases::DefaultCases::ToCsvCase < Eco::API::Common::Loaders::U
125
125
  "id" => "ecoPortal ID",
126
126
  "external_id" => "Reference ID (ext_id)",
127
127
  "login_provider_ids" => "Login Methods",
128
- "landing_page_id" => "Landing Page ID",
129
- "show_sidebar" => "(pref) Sidebar Open?",
130
- "show_shortcuts" => "(pref) Link to Registers?",
131
- "show_coming_soon" => "(pref) Coming Soon List?",
132
- "show_recently_visited_forms" => "(pref) Recently Visited Forms List?",
133
- "show_tasks" => "(pref) Tasks List?",
134
- "show_task_bubbles" => "(pref) Task Count Bubbles",
135
- "kiosk_enabled" => "Kiosk User?",
136
- "freemium" => "Freemium User?",
137
- "files" => "(able) on Files",
138
- "reports" => "(able) on Report Structures",
139
- "data" => "(able) on Data (hours, datasets)",
140
- "organization" => "(able) on Organization Config",
141
- "pages" => "(able) on Page/Entries",
142
- "page_editor" => "(able) page Editor Level",
143
- "registers" => "(able) on Registers",
144
- "tasks" => "(able) on Tasks",
145
- "person_core" => "(able) on People",
146
- "person_core_create" => "(able) Create People?",
147
- "person_core_edit" => "(able) Edit People?",
148
- "person_details" => "(able) on People Schema Details",
149
- "person_account" => "(able) on Users",
150
- "person_abilities" => "(able) on Users' Abilities",
151
- "custom_files" => "(min) on Files",
152
- "custom_reports" => "(min) on Report Structures",
153
- "custom_data" => "(min) on Data (hours, datasets)",
154
- "custom_organization" => "(min) on Organization Config",
155
- "custom_pages" => "(min) on Page/Entries",
156
- "custom_page_editor" => "(min) page Editor Level",
157
- "custom_registers" => "(min) on Registers",
158
- "custom_tasks" => "(min) on Tasks",
159
- "custom_person_core" => "(min) on People",
160
- "custom_person_core_create" => "(min) Create People?",
161
- "custom_person_core_edit" => "(min) Edit People?",
162
- "custom_person_details" => "(min) on People Schema Details",
163
- "custom_person_account" => "(min) on Users",
164
- "custom_person_abilities" => "(min) on Users' Abilities"
128
+ "landing_page_id" => "Landing Page ID"
165
129
  }
166
130
  end
167
131
 
@@ -75,4 +75,46 @@ class Eco::API::UseCases::DefaultCases::ToCsvDetailedCase < Eco::API::UseCases::
75
75
  ]
76
76
  end
77
77
 
78
+ def nice_header_maps
79
+ @nice_header_maps ||= super.merge({
80
+ "landing_page_id" => "Landing Page ID",
81
+ "show_sidebar" => "(pref) Sidebar Open?",
82
+ "show_shortcuts" => "(pref) Link to Registers?",
83
+ "show_coming_soon" => "(pref) Coming Soon List?",
84
+ "show_recently_visited_forms" => "(pref) Recently Visited Forms List?",
85
+ "show_tasks" => "(pref) Tasks List?",
86
+ "show_task_bubbles" => "(pref) Task Count Bubbles",
87
+ "kiosk_enabled" => "Kiosk User?",
88
+ "freemium" => "Freemium User?",
89
+ "files" => "(able) on Files",
90
+ "reports" => "(able) on Report Structures",
91
+ "data" => "(able) on Data (hours, datasets)",
92
+ "organization" => "(able) on Organization Config",
93
+ "pages" => "(able) on Page/Entries",
94
+ "page_editor" => "(able) page Editor Level",
95
+ "registers" => "(able) on Registers",
96
+ "tasks" => "(able) on Tasks",
97
+ "person_core" => "(able) on People",
98
+ "person_core_create" => "(able) Create People?",
99
+ "person_core_edit" => "(able) Edit People?",
100
+ "person_details" => "(able) on People Schema Details",
101
+ "person_account" => "(able) on Users",
102
+ "person_abilities" => "(able) on Users' Abilities",
103
+ "custom_files" => "(min) on Files",
104
+ "custom_reports" => "(min) on Report Structures",
105
+ "custom_data" => "(min) on Data (hours, datasets)",
106
+ "custom_organization" => "(min) on Organization Config",
107
+ "custom_pages" => "(min) on Page/Entries",
108
+ "custom_page_editor" => "(min) page Editor Level",
109
+ "custom_registers" => "(min) on Registers",
110
+ "custom_tasks" => "(min) on Tasks",
111
+ "custom_person_core" => "(min) on People",
112
+ "custom_person_core_create" => "(min) Create People?",
113
+ "custom_person_core_edit" => "(min) Edit People?",
114
+ "custom_person_details" => "(min) on People Schema Details",
115
+ "custom_person_account" => "(min) on Users",
116
+ "custom_person_abilities" => "(min) on Users' Abilities"
117
+ })
118
+ end
119
+
78
120
  end
@@ -2,13 +2,16 @@ class Eco::API::UseCases::DefaultCases::UpsertCase < Eco::API::Common::Loaders::
2
2
  name "upsert"
3
3
  type :sync
4
4
 
5
+ attr_reader :options
6
+
5
7
  def main(entries, people, session, options, usecase)
8
+ @options = options
6
9
  micro = session.micro
7
10
  creation = session.new_job("main", "create", :create, usecase)
8
11
  update = session.new_job("main", "update", :update, usecase)
9
12
  supers = session.new_job("post", "supers", :update, usecase, :core)
10
13
 
11
- micro.with_each(entries, people, options) do |entry, person|
14
+ micro.with_each(entries, people, options, append_created: append_created) do |entry, person|
12
15
  person.new? ? creation.add(person) : update.add(person)
13
16
  micro.set_core_with_supervisor(entry, person, people, supers, options)
14
17
  entry.set_details(person) unless options.dig(:exclude, :details)
@@ -16,4 +19,10 @@ class Eco::API::UseCases::DefaultCases::UpsertCase < Eco::API::Common::Loaders::
16
19
  end
17
20
  end
18
21
 
22
+ private
23
+
24
+ def append_created
25
+ options.dig(:people, :append_created)
26
+ end
27
+
19
28
  end