eco-helpers 2.0.21 → 2.0.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -4
  3. data/eco-helpers.gemspec +0 -1
  4. data/lib/eco/api/common.rb +0 -1
  5. data/lib/eco/api/common/loaders.rb +2 -0
  6. data/lib/eco/api/common/loaders/base.rb +58 -0
  7. data/lib/eco/api/common/loaders/case_base.rb +33 -0
  8. data/lib/eco/api/common/loaders/error_handler.rb +2 -2
  9. data/lib/eco/api/common/loaders/parser.rb +30 -5
  10. data/lib/eco/api/common/loaders/policy.rb +1 -1
  11. data/lib/eco/api/common/loaders/use_case.rb +1 -1
  12. data/lib/eco/api/common/people/default_parsers.rb +1 -0
  13. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +93 -1
  14. data/lib/eco/api/common/people/default_parsers/xls_parser.rb +53 -0
  15. data/lib/eco/api/common/people/entries.rb +83 -14
  16. data/lib/eco/api/common/people/entry_factory.rb +36 -21
  17. data/lib/eco/api/common/people/person_attribute_parser.rb +8 -0
  18. data/lib/eco/api/common/people/person_factory.rb +4 -2
  19. data/lib/eco/api/common/people/person_parser.rb +8 -2
  20. data/lib/eco/api/common/people/supervisor_helpers.rb +1 -1
  21. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +0 -8
  22. data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +0 -8
  23. data/lib/eco/api/microcases/set_core_with_supervisor.rb +4 -2
  24. data/lib/eco/api/microcases/set_supervisor.rb +29 -8
  25. data/lib/eco/api/microcases/with_each.rb +7 -3
  26. data/lib/eco/api/microcases/with_each_starter.rb +3 -2
  27. data/lib/eco/api/organization/people.rb +7 -1
  28. data/lib/eco/api/session.rb +18 -7
  29. data/lib/eco/api/session/batch.rb +1 -1
  30. data/lib/eco/api/session/batch/job.rb +42 -9
  31. data/lib/eco/api/usecases.rb +2 -2
  32. data/lib/eco/api/usecases/base_case.rb +2 -2
  33. data/lib/eco/api/usecases/base_io.rb +17 -4
  34. data/lib/eco/api/usecases/default_cases/create_case.rb +10 -1
  35. data/lib/eco/api/usecases/default_cases/create_details_case.rb +10 -1
  36. data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +10 -1
  37. data/lib/eco/api/usecases/default_cases/hris_case.rb +25 -1
  38. data/lib/eco/api/usecases/default_cases/upsert_case.rb +10 -1
  39. data/lib/eco/cli/config/default/input.rb +63 -10
  40. data/lib/eco/cli/config/default/options.rb +40 -8
  41. data/lib/eco/cli/config/default/usecases.rb +16 -0
  42. data/lib/eco/cli/config/default/workflow.rb +7 -4
  43. data/lib/eco/cli/config/filters.rb +6 -2
  44. data/lib/eco/cli/config/filters/input_filters.rb +3 -2
  45. data/lib/eco/cli/config/filters/people_filters.rb +3 -2
  46. data/lib/eco/cli/config/help.rb +1 -1
  47. data/lib/eco/cli/config/options_set.rb +6 -4
  48. data/lib/eco/cli/config/use_cases.rb +6 -3
  49. data/lib/eco/cli/scripting/args_helpers.rb +2 -2
  50. data/lib/eco/csv.rb +2 -0
  51. data/lib/eco/language/models/collection.rb +5 -2
  52. data/lib/eco/version.rb +1 -1
  53. metadata +4 -22
  54. data/lib/eco/api/common/base_loader.rb +0 -68
@@ -1,19 +1,72 @@
1
1
  ASSETS.cli.config do |cnf|
2
+ formats = {
3
+ csv: {
4
+ option: ["-csv"],
5
+ extname: [".csv", ".txt"]
6
+ },
7
+ xml: {
8
+ option: ["-xml"],
9
+ extname: [".xml"]
10
+ },
11
+ xls: {
12
+ option: ["-xls", "-xlsx", "-excel"],
13
+ extname: [".xls", ".xlsx", ".xlsm"]
14
+ },
15
+ json: {
16
+ option: ["-json"],
17
+ extname: [".json"]
18
+ }
19
+ }
20
+
2
21
  cnf.input(default_option: "-entries-from") do |session, str_opt, options|
3
22
  input = []
4
23
  if SCR.get_arg(str_opt)
5
24
  file = SCR.get_file(str_opt, required: true)
6
- options.deep_merge!(input: {file: {name: file}})
7
- if SCR.get_arg("-xml")
8
- options.deep_merge!(input: {file: {format: :xml}})
9
- session.config.files.validate(:xml, file)
10
- input = session.entries(file: file, format: :xml)
11
- elsif SCR.get_arg("-json")
12
- options.deep_merge!(input: {file: {format: :json}})
13
- input = Eco::API::Organization::People.new(JSON.parse(File.read(file)))
25
+
26
+ # Command line check
27
+ format = formats.reduce(nil) do |matched, (format, selectors)|
28
+ used = selectors[:option].reduce(false) {|used, option| SCR.get_arg(option) || used}
29
+ next matched if matched
30
+ next format if used
31
+ end
32
+
33
+ # File/Folder check
34
+ file = File.expand_path(file)
35
+ if File.directory?(file)
36
+ folder = file
37
+ file = Dir.glob("#{file}/*").reject {|f| File.directory?(f)}
38
+ ext = (format && formats[format][:extname]) || [File.extname(file.first)]
39
+ file = file.select {|f| ext.any? {|e| File.extname(f) == e}}.tap do |files|
40
+ if files.empty?
41
+ session.logger.error("Could not find any file with extension: #{ext} in folder '#{folder}'")
42
+ exit(1)
43
+ end
44
+ end
14
45
  else
15
- options.deep_merge!(input: {file: {format: :csv}})
16
- input = session.csv_entries(file)
46
+ ext = File.extname(file)
47
+ end
48
+
49
+ format ||= formats.reduce(nil) do |matched, (format, selectors)|
50
+ next matched if matched
51
+ next format if selectors[:extname].any? {|e| ext == e}
52
+ end
53
+ format ||= :csv
54
+
55
+ options.deep_merge!(input: {file: {name: file}})
56
+ options.deep_merge!(input: {file: {format: format}})
57
+
58
+ case format
59
+ when :xml
60
+ [file].flatten.each {|f| session.config.files.validate(:xml, f)}
61
+ input = session.entries(file: file, format: format)
62
+ when :xls
63
+ input = session.entries(file: file, format: format)
64
+ when :json
65
+ input = [file].flatten.reduce(Eco::API::Organization::People.new([])) do |people, file|
66
+ people.merge(JSON.parse(File.read(file)))
67
+ end
68
+ else # :csv
69
+ input = session.csv_entries(file, check_headers: true)
17
70
  end
18
71
  end
19
72
  input
@@ -1,19 +1,30 @@
1
1
  ASSETS.cli.config do |cnf|
2
2
  cnf.options_set do |options_set, options|
3
3
  options_set.add("--help", "Offers a HELP") do |options, sesssion|
4
- conf = ASSETS.cli.config
5
- puts conf.people_filters.help if hpf = SCR.get_arg("-filters")
6
- puts conf.input_filters.help if hif = SCR.get_arg("-input-filters")
7
- puts conf.options_set.help if ho = SCR.get_arg("-options")
8
- puts conf.usecases.help if huc = SCR.get_arg("-usecases")
4
+ conf = ASSETS.cli.config
5
+ active = Proc.new {|opt| SCR.get_arg(opt) && SCR.get_arg(opt, with_param: true)}
6
+
7
+ if hpf = active.call("-filters")
8
+ puts conf.people_filters.help(refine: hpf)
9
+ end
10
+ if hif = active.call("-input-filters")
11
+ puts conf.input_filters.help(refine: hif)
12
+ end
13
+ if ho = active.call("-options")
14
+ puts conf.options_set.help(refine: ho)
15
+ end
16
+ if huc = active.call("-usecases")
17
+ puts conf.usecases.help(refine: huc)
18
+ end
9
19
  puts [
10
20
  "Please specify one of the below:",
11
21
  " -filters to display available filters on people",
12
22
  " -input-filters to display available filters on input data",
13
23
  " -options to dislpay available options",
14
24
  " -usecases to display available usecases",
15
- "",
16
- "You may specify the usecase to know its specific options by: -usecase_name --help -options"
25
+ "TIPS:",
26
+ " * You may specify the usecase to know its specific options by: -usecase_name --help -options",
27
+ " * You may specify a refinement to show specific information only: --help -usecases tags"
17
28
  ].join("\n") unless hpf || hif || ho || huc
18
29
  exit
19
30
  end
@@ -41,7 +52,7 @@ ASSETS.cli.config do |cnf|
41
52
  session.schema = sch_id
42
53
  end
43
54
 
44
- desc = "Used to be used to specify the input file when using -get-partial. "
55
+ desc = "Used to be used to specify the input file or folder when using -get-partial."
45
56
  desc += "It can also be useful to obtain `-get-partial` of people base on `:export` use cases (i.e. -people-to-csv)"
46
57
  options_set.add("-entries-from", desc) do |options, session|
47
58
  options.deep_merge!(input: {entries_from: true})
@@ -66,6 +77,11 @@ ASSETS.cli.config do |cnf|
66
77
  })
67
78
  end
68
79
 
80
+ desc = "Saves the requests's body even though running in dry-run (-simulate)"
81
+ options_set.add("-save-requests", desc) do |options, session|
82
+ options.deep_merge!(requests: {backup: true})
83
+ end
84
+
69
85
  desc = "Used to specify the cache file of people to be used. "
70
86
  desc += "It is useful to use as people reference those stored in cached file diffrent to the last one."
71
87
  options_set.add("-people-from-backup", desc) do |options, session|
@@ -82,6 +98,22 @@ ASSETS.cli.config do |cnf|
82
98
  session.config.dry_run!
83
99
  end
84
100
 
101
+ desc = "Runs runs post_launch cases even if in dry-run"
102
+ options_set.add("-run-postlaunch", desc) do |options, session|
103
+ options.deep_merge!(post_launch: {run: true})
104
+ end
105
+
106
+ desc = "(careful with this option) This will include everybody as part of the update (including those that are api excluded). "
107
+ desc += "Only launch with this option when only api excluded people are included in your update."
108
+ options_set.add("-include-excluded", desc) do |options|
109
+ options.deep_merge!(include: {excluded: true})
110
+ end
111
+
112
+ desc = "Includes in API updates ONLY people that evaluate true as people excluded from periodic upates."
113
+ options_set.add("-include-only-excluded", desc) do |options|
114
+ options.deep_merge!(include: {excluded: {only: true}})
115
+ end
116
+
85
117
  desc = "Ignores threshold limitations on requests for this session (skip batch belt)"
86
118
  options_set.add("-skip-batch-policy", desc) do |options|
87
119
  options.deep_merge!(skip: {batch_policy: true})
@@ -190,9 +190,18 @@ ASSETS.cli.config do |cnf|
190
190
  cases.add("-set-default-tag", :transform, desc, case_name: "set-default-tag")
191
191
 
192
192
  desc = "Creates people with with details and account"
193
+ as1 = "During the run, if new people is created, they are included in the People object of the current session."
194
+ as1 << " This makes them available to find them (i.e. via 'external-id') before they exist"
193
195
  cases.add("-create-from", :sync, desc, case_name: "create")
196
+ .add_option("-append-starters", as1) do |options|
197
+ options.deep_merge!(people: {append_created: true})
198
+ end
199
+
194
200
  desc = "Creates people with only details"
195
201
  cases.add("-create-details-from", :sync, desc, case_name: "create-details")
202
+ .add_option("-append-starters", as1) do |options|
203
+ options.deep_merge!(people: {append_created: true})
204
+ end
196
205
 
197
206
  desc = "It just adds everybody to an update job without doing any change. If the org has policies, it will refresh"
198
207
  cases.add("-refresh", :transform, desc, case_name: "refresh")
@@ -213,7 +222,14 @@ ASSETS.cli.config do |cnf|
213
222
 
214
223
  desc = "Tries to find the input entries and update them. It creates them if not found"
215
224
  cases.add("-upsert-from", :sync, desc, case_name: "upsert")
225
+ .add_option("-append-starters", as1) do |options|
226
+ options.deep_merge!(people: {append_created: true})
227
+ end
228
+
216
229
  desc = "It does like -upsert-from and additionally removes account and supervisor of those in people that are not in the entries (leavers)"
217
230
  cases.add("-hris-from", :sync, desc, case_name: "hris")
231
+ .add_option("-append-starters", as1) do |options|
232
+ options.deep_merge!(people: {append_created: true})
233
+ end
218
234
  end
219
235
  end
@@ -100,10 +100,13 @@ ASSETS.cli.config do |config|
100
100
  else
101
101
  get_people = io.options.dig(:people, :get)
102
102
  partial_update = get_people && get_people.dig(:type) == :partial
103
- if !io.options[:dry_run] && partial_update
104
- # get target people afresh
105
- people = io.session.micro.people_refresh(people: io.people, include_created: true)
106
- io = io.new(people: people)
103
+ run_it = !io.options[:dry_run] || io.options.dig(:post_launch, :run)
104
+ if run_it && partial_update
105
+ unless io.options[:dry_run]
106
+ # get target people afresh
107
+ people = io.session.micro.people_refresh(people: io.people, include_created: true)
108
+ io = io.base.new(people: people)
109
+ end
107
110
  else
108
111
  wf_post.skip!
109
112
  msg = "Although there are post_launch cases, they will NOT be RUN"
@@ -12,10 +12,14 @@ module Eco
12
12
  end
13
13
 
14
14
  # @return [String] summary of the filters.
15
- def help(msg = "The following are the available filters:")
15
+ def help(msg = nil, refine: nil)
16
+ refinement = refine.is_a?(String)? " (containing: '#{refine}')" : ""
17
+ msg ||= "The following are the available filters#{refinement}:"
16
18
  [msg].yield_self do |lines|
17
19
  max_len = keys_max_len(@filters.keys)
18
- @filters.keys.sort.each do |key|
20
+ @filters.keys.sort.select do |key|
21
+ refine.is_a?(String) && key.include?(refine)
22
+ end.each do |key|
19
23
  lines << help_line(key, @description[key], max_len)
20
24
  end
21
25
  lines
@@ -4,8 +4,9 @@ module Eco
4
4
  class Filters
5
5
  class InputFilters < Eco::CLI::Config::Filters
6
6
 
7
- def help
8
- super("The following are the available filters on the input entries:")
7
+ def help(refine: nil)
8
+ refinement = refine.is_a?(String)? " (containing: '#{refine}')" : ""
9
+ super("The following are the available filters on the input entries#{refinement}:", refine: refine)
9
10
  end
10
11
 
11
12
  def process(io:)
@@ -4,8 +4,9 @@ module Eco
4
4
  class Filters
5
5
  class PeopleFilters < Eco::CLI::Config::Filters
6
6
 
7
- def help
8
- super("The following are the available filters on people:")
7
+ def help(refine: nil)
8
+ refinement = refine.is_a?(String)? " (containing: '#{refine}')" : ""
9
+ super("The following are the available filters on people#{refinement}:", refine: refine)
9
10
  end
10
11
 
11
12
  def process(io:)
@@ -3,7 +3,7 @@ module Eco
3
3
  class Config
4
4
  module Help
5
5
 
6
- def help
6
+ def help(*args)
7
7
  raise "this needs to be reimplemented in the child class and return a string"
8
8
  end
9
9
 
@@ -14,17 +14,19 @@ module Eco
14
14
  end
15
15
 
16
16
  # @return [String] summary of the options.
17
- def help
17
+ def help(refine: nil)
18
18
  indent = 2
19
19
  spaces = any_non_general_space_active? ? active_namespaces : namespaces
20
-
21
- ["The following are the available options:"].yield_self do |lines|
20
+ refinement = refine.is_a?(String)? " (containing: '#{refine}')" : ""
21
+ ["The following are the available options#{refinement}:"].yield_self do |lines|
22
22
  max_len = keys_max_len(options_args(spaces)) + indent
23
23
  spaces.each do |namespace|
24
24
  is_general = (namespace == :general)
25
25
  str_indent = is_general ? "" : " " * indent
26
26
  lines << help_line(namespace, "", max_len) unless is_general
27
- options_set(namespace).each do |arg, option|
27
+ options_set(namespace).select do |arg, option|
28
+ refine.is_a?(String) && option.name.include?(refine)
29
+ end.each do |arg, option|
28
30
  lines << help_line(" " * indent + "#{option.name}", option.description, max_len)
29
31
  end
30
32
  end
@@ -29,10 +29,13 @@ module Eco
29
29
  end
30
30
 
31
31
  # @return [String] summary of the use cases.
32
- def help
33
- ["The following are the available use cases:"].yield_self do |lines|
32
+ def help(refine: nil)
33
+ refinement = refine.is_a?(String)? " (containing: '#{refine}')" : ""
34
+ ["The following are the available use cases#{refinement}:"].yield_self do |lines|
34
35
  max_len = keys_max_len(@linked_cases.keys)
35
- @linked_cases.keys.sort.each do |option_case|
36
+ @linked_cases.keys.sort.select do |key|
37
+ refine.is_a?(String) && key.include?(refine)
38
+ end.each do |option_case|
36
39
  lines << help_line(option_case, @linked_cases[option_case].description, max_len)
37
40
  end
38
41
  lines
@@ -75,10 +75,10 @@ module Eco
75
75
  def get_file(key, required: false, should_exist: true)
76
76
  filename = get_arg(key, with_param: true)
77
77
  if !filename && required
78
- puts "You need to specify a file '#{key} file'"
78
+ puts "You need to specify a file or folder '#{key} file_or_folder'"
79
79
  exit(1)
80
80
  elsif !file_exists?(filename) && should_exist && required
81
- puts "This file doesn't exist '#{filename}'"
81
+ puts "This file/folder doesn't exist '#{filename}'"
82
82
  exit(1)
83
83
  end
84
84
 
data/lib/eco/csv.rb CHANGED
@@ -5,6 +5,7 @@ module Eco
5
5
 
6
6
  class << self
7
7
 
8
+ # @return [Eco::CSV::Table]
8
9
  def parse(data, **kargs, &block)
9
10
  kargs = {headers: true, skip_blanks: true}.merge(kargs)
10
11
  out = super(data, **kargs, &block).reject do |row|
@@ -14,6 +15,7 @@ module Eco
14
15
  Eco::CSV::Table.new(out)
15
16
  end
16
17
 
18
+ # @return [Eco::CSV::Table]
17
19
  def read(file, **kargs)
18
20
  kargs = {headers: true, skip_blanks: true}.merge(kargs)
19
21
 
@@ -134,8 +134,11 @@ module Eco
134
134
  to_a.group_by(&block) if block
135
135
  end
136
136
 
137
- def to_h(attr)
138
- return {} if !attr
137
+ # By a specific `attr` or a block
138
+ # @note either one or the other should be present
139
+ def to_h(attr, &block)
140
+ return to_a.group_by(&block) if block
141
+ raise "And attr or a block are required. Given attr: #{attr}" unless attr
139
142
  to_a.group_by { |object| object.method(attr).call }
140
143
  end
141
144
  # @!endgroup
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = "2.0.21"
2
+ VERSION = "2.0.26"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eco-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.21
4
+ version: 2.0.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
@@ -350,26 +350,6 @@ dependencies:
350
350
  - - "<"
351
351
  - !ruby/object:Gem::Version
352
352
  version: '1.3'
353
- - !ruby/object:Gem::Dependency
354
- name: creek
355
- requirement: !ruby/object:Gem::Requirement
356
- requirements:
357
- - - ">="
358
- - !ruby/object:Gem::Version
359
- version: 2.5.2
360
- - - "<"
361
- - !ruby/object:Gem::Version
362
- version: '2.6'
363
- type: :runtime
364
- prerelease: false
365
- version_requirements: !ruby/object:Gem::Requirement
366
- requirements:
367
- - - ">="
368
- - !ruby/object:Gem::Version
369
- version: 2.5.2
370
- - - "<"
371
- - !ruby/object:Gem::Version
372
- version: '2.6'
373
353
  description:
374
354
  email:
375
355
  - oscar@ecoportal.co.nz
@@ -389,12 +369,13 @@ files:
389
369
  - lib/eco-helpers.rb
390
370
  - lib/eco/api.rb
391
371
  - lib/eco/api/common.rb
392
- - lib/eco/api/common/base_loader.rb
393
372
  - lib/eco/api/common/class_auto_loader.rb
394
373
  - lib/eco/api/common/class_helpers.rb
395
374
  - lib/eco/api/common/class_hierarchy.rb
396
375
  - lib/eco/api/common/class_meta_basics.rb
397
376
  - lib/eco/api/common/loaders.rb
377
+ - lib/eco/api/common/loaders/base.rb
378
+ - lib/eco/api/common/loaders/case_base.rb
398
379
  - lib/eco/api/common/loaders/error_handler.rb
399
380
  - lib/eco/api/common/loaders/parser.rb
400
381
  - lib/eco/api/common/loaders/policy.rb
@@ -412,6 +393,7 @@ files:
412
393
  - lib/eco/api/common/people/default_parsers/policy_groups_parser.rb
413
394
  - lib/eco/api/common/people/default_parsers/select_parser.rb
414
395
  - lib/eco/api/common/people/default_parsers/send_invites_parser.rb
396
+ - lib/eco/api/common/people/default_parsers/xls_parser.rb
415
397
  - lib/eco/api/common/people/entries.rb
416
398
  - lib/eco/api/common/people/entry_factory.rb
417
399
  - lib/eco/api/common/people/person_attribute_parser.rb
@@ -1,68 +0,0 @@
1
- module Eco
2
- module API
3
- module Common
4
- class BaseLoader
5
- extend Eco::API::Common::ClassHelpers
6
-
7
- class << self
8
- attr_writer :name, :type
9
-
10
- # The name that this case, policy or error handler will have.
11
- def name(value = nil)
12
- name_only_once! if value
13
- set_created_at!
14
- return @name ||= self.to_s unless value
15
- @name = value
16
- end
17
-
18
- # Sort order
19
- def <=>(other)
20
- created_at <=> other.created_at
21
- end
22
-
23
- # If still not set, it sets the `created_at` class timestamp.
24
- def set_created_at!
25
- @created_at = Time.now unless @created_at
26
- end
27
-
28
- # Class creation timestamp, to be able to load them in the order they were declared.
29
- def created_at
30
- @created_at ||= Time.now
31
- end
32
-
33
- # Prevent the same class to be re-opened/re-named
34
- def name_only_once!
35
- raise "You have already declared #{self} or you are trying to give it a name twice" if @name
36
- end
37
-
38
- end
39
-
40
- # This method will be called when the BaseLoader is created
41
- # @note
42
- # - this method should implement the loading logics for the given `Children` class.
43
- def initialize
44
- raise "You should implement this method"
45
- end
46
-
47
- def name
48
- self.class.name
49
- end
50
-
51
- private
52
-
53
- def session
54
- @session ||= ASSETS.session
55
- end
56
-
57
- def micro
58
- session.micro
59
- end
60
-
61
- def config
62
- @config ||= ASSETS.config
63
- end
64
-
65
- end
66
- end
67
- end
68
- end