eco-helpers 3.2.1 → 3.2.3

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +36 -1
  4. data/eco-helpers.gemspec +3 -3
  5. data/lib/eco/api/common/loaders/config/workflow/mailer.rb +1 -0
  6. data/lib/eco/api/common/people/person_entry.rb +6 -1
  7. data/lib/eco/api/common/people/person_parser.rb +1 -0
  8. data/lib/eco/api/microcases/people/manage/cache.rb +21 -16
  9. data/lib/eco/api/microcases/people/manage/filename.rb +29 -0
  10. data/lib/eco/api/microcases/people/manage/load.rb +6 -48
  11. data/lib/eco/api/microcases/people/manage/load_cache.rb +29 -0
  12. data/lib/eco/api/microcases/people/manage/refresh.rb +5 -3
  13. data/lib/eco/api/microcases/people/manage.rb +4 -0
  14. data/lib/eco/api/organization/tag_tree.rb +11 -4
  15. data/lib/eco/api/session/batch/searcher.rb +3 -3
  16. data/lib/eco/api/session/config/people.rb +23 -20
  17. data/lib/eco/api/usecases/default/locations/tagtree_upload_case.rb +20 -2
  18. data/lib/eco/api/usecases/graphql/helpers/location/base/tree_tracking.rb +14 -7
  19. data/lib/eco/api/usecases/graphql/helpers/location/base.rb +1 -1
  20. data/lib/eco/api/usecases/graphql/helpers/location/command/diff/as_update.rb +0 -1
  21. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_archive.rb +0 -1
  22. data/lib/eco/api/usecases/graphql/helpers/location/command/end_points/optimizations.rb +64 -0
  23. data/lib/eco/api/usecases/graphql/helpers/location/command/end_points.rb +96 -0
  24. data/lib/eco/api/usecases/graphql/helpers/location/command/input_unit_response.rb +69 -0
  25. data/lib/eco/api/usecases/graphql/helpers/location/command/result.rb +11 -10
  26. data/lib/eco/api/usecases/graphql/helpers/location/command/results.rb +120 -63
  27. data/lib/eco/api/usecases/graphql/helpers/location/command.rb +26 -26
  28. data/lib/eco/api/usecases/graphql/samples/location/command/dsl.rb +195 -37
  29. data/lib/eco/api/usecases/graphql/samples/location/command/results.rb +45 -13
  30. data/lib/eco/api/usecases/graphql/samples/location/command/service/tree_update.rb +0 -51
  31. data/lib/eco/api/usecases/graphql/samples/location/command/track_changed_ids.rb +6 -14
  32. data/lib/eco/api/usecases/graphql/samples/location/command.rb +1 -1
  33. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/inputable.rb +4 -1
  34. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff.rb +6 -0
  35. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/input.rb +1 -0
  36. data/lib/eco/api/usecases/lib/error_handling.rb +1 -1
  37. data/lib/eco/api/usecases/ooze_samples/helpers/creatable.rb +1 -0
  38. data/lib/eco/api/usecases/ooze_samples/helpers/rescuable.rb +1 -0
  39. data/lib/eco/api/usecases/samples/drivers/cli/sftp_cli.rb +1 -1
  40. data/lib/eco/api/usecases/samples/drivers/sftp_sample.rb +4 -1
  41. data/lib/eco/api/usecases/samples/drivers/url_pull_sample.rb +12 -9
  42. data/lib/eco/api/usecases/samples/people/filters/cli/require_id_cli.rb +5 -0
  43. data/lib/eco/api/usecases/samples/people/filters/cli/require_min_entries_cli.rb +5 -0
  44. data/lib/eco/api/usecases/samples/people/filters/require_id_sample.rb +61 -0
  45. data/lib/eco/api/usecases/samples/people/filters/require_min_entries_sample.rb +20 -0
  46. data/lib/eco/api/usecases/samples/people/filters.rb +7 -0
  47. data/lib/eco/api/usecases/samples/people.rb +12 -0
  48. data/lib/eco/api/usecases/samples.rb +1 -0
  49. data/lib/eco/cli_default/options.rb +5 -0
  50. data/lib/eco/data/hashes/array_diff.rb +14 -4
  51. data/lib/eco/data/locations/node_base/csv_convert.rb +9 -1
  52. data/lib/eco/data/locations/node_base/tag_validations.rb +2 -2
  53. data/lib/eco/data/locations/node_diff/nodes_diff/diffs_tree.rb +10 -3
  54. data/lib/eco/data/locations/node_diff/nodes_diff.rb +6 -0
  55. data/lib/eco/version.rb +1 -1
  56. metadata +23 -13
  57. data/lib/eco/api/usecases/graphql/helpers/location/command/optimizations.rb +0 -84
@@ -0,0 +1,61 @@
1
+ class Eco::API::UseCases::Samples::People::Filters::RequireId < Eco::API::Custom::UseCase
2
+ require_relative 'cli/require_id_cli'
3
+
4
+ name 'require-id'
5
+ type :import
6
+
7
+ GENERATE_FILE = true
8
+ OUT_FOLDER = 'sftp'.freeze
9
+ OUT_TIME_FORMAT = '%Y%m%dT%H%M%S'.freeze
10
+ OUT_FILENAME = 'no_id'.freeze
11
+
12
+ def main(*_args)
13
+ output = input
14
+
15
+ # Filter out the ones that we could not build ids for
16
+ no_id = input.newFrom(input.reject {|e| id?(e)})
17
+
18
+ unless no_id.empty?
19
+ log(:warn) {
20
+ "Excluding #{no_id.length} entries with no external_id."
21
+ }
22
+
23
+ no_id.export(output_filename) if generate_file?
24
+
25
+ output = input.newFrom(input.select {|e| id?(e)})
26
+ end
27
+
28
+ output.tap do
29
+ next unless output.empty?
30
+
31
+ msg = 'Empty entries after excluding entries with no external_id. '
32
+ msg << 'Aborting...'
33
+ abort msg
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def id?(entry)
40
+ return true unless entry.id.to_s.strip.empty?
41
+ return true unless entry.external_id.to_s.strip.empty?
42
+
43
+ false
44
+ end
45
+
46
+ def generate_file?
47
+ self.class::GENERATE_FILE
48
+ end
49
+
50
+ def output_filename(name = self.class::OUT_FILENAME)
51
+ File.join(output_folder, "#{timestamp}_#{config.active_enviro}_#{name}.csv")
52
+ end
53
+
54
+ def output_folder
55
+ File.join(config.active_enviro, self.class::OUT_FOLDER)
56
+ end
57
+
58
+ def timestamp(date = Time.now)
59
+ date.strftime(self.class::OUT_TIME_FORMAT)
60
+ end
61
+ end
@@ -0,0 +1,20 @@
1
+ class Eco::API::UseCases::Samples::People::Filters::RequireMinEntries < Eco::API::Custom::UseCase
2
+ require_relative 'cli/require_min_entries_cli'
3
+
4
+ name 'require-min-entries'
5
+ type :import
6
+
7
+ MIN_COUNT = 200
8
+
9
+ def main(*_args)
10
+ return input if options.dig(:workflow, :ad_hoc)
11
+
12
+ input.tap do |entries|
13
+ next if entries.count >= self.class::MIN_COUNT
14
+
15
+ msg = "There are only #{entries.count} valid entries in the file "
16
+ msg << "(min required: #{self.class::MIN_COUNT}). Aborting..."
17
+ abort(msg)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module Eco::API::UseCases::Samples::People
2
+ module Filters
3
+ end
4
+ end
5
+
6
+ require_relative 'filters/require_id_sample'
7
+ require_relative 'filters/require_min_entries_sample'
@@ -0,0 +1,12 @@
1
+ module Eco
2
+ module API
3
+ class UseCases
4
+ class Samples
5
+ module People
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative 'people/filters'
@@ -8,3 +8,4 @@ module Eco
8
8
  end
9
9
 
10
10
  require_relative 'samples/drivers'
11
+ require_relative 'samples/people'
@@ -145,6 +145,11 @@ ASSETS.cli.config do |cnf| # rubocop:disable Metrics/BlockLength
145
145
  end
146
146
  end
147
147
 
148
+ desc = 'It allows to skip the filtering of entries during the workflow.'
149
+ options_set.add('-skip-pre-filter', desc) do |options, session|
150
+ options.deep_merge!(workflow: {ad_hoc: true})
151
+ end
152
+
148
153
  # PEOPLE FETCH
149
154
 
150
155
  desc = 'Do not load any people for this run.'
@@ -95,14 +95,24 @@ module Eco
95
95
  when String
96
96
  to_array_of_hashes(Eco::CSV.parse(content))
97
97
  when Enumerable
98
- sample = content.to_a.first
98
+ content_ary = content.to_a
99
+ content_cnt = content_ary.count
100
+ sample = content_ary.first
101
+
99
102
  case sample
100
103
  when Hash, Array, ::CSV::Row
101
104
  Eco::CSV::Table.new(content).to_array_of_hashes
102
105
  else
103
- log(:error) {
104
- "(ArrayDiff) Input content 'Array' of '#{sample.class}' is not supported."
105
- }
106
+ if content_cnt.zero?
107
+ log(:error) {
108
+ "Inpout should not be empty"
109
+ }
110
+ else
111
+ log(:error) {
112
+ "(ArrayDiff) Input content 'Array' of '#{sample.class}' is not supported."
113
+ }
114
+ end
115
+
106
116
  exit(1)
107
117
  end
108
118
  else
@@ -15,6 +15,7 @@ module Eco::Data::Locations::NodeBase
15
15
  def hash_list(value, &block)
16
16
  return hash_list(org_tree(value), &block) if value.is_a?(::CSV::Table)
17
17
  return value.as_nodes_json(&block) if value.is_a?(tree_class)
18
+
18
19
  raise ArgumentError, "Expecting Eco::API::Organization::TagTree or CSV::Table. Given: #{value.class}"
19
20
  end
20
21
 
@@ -28,6 +29,7 @@ module Eco::Data::Locations::NodeBase
28
29
  def hash_tree(value, &block)
29
30
  return hash_tree_from_csv(value, &block) if value.is_a?(::CSV::Table)
30
31
  return value.as_json(&block) if value.is_a?(tree_class)
32
+
31
33
  raise ArgumentError, "Expecting Eco::API::Organization::TagTree or CSV::Table. Given: #{value.class}"
32
34
  end
33
35
 
@@ -40,6 +42,7 @@ module Eco::Data::Locations::NodeBase
40
42
  def org_tree(value, &block)
41
43
  return tree_class.new(hash_tree(value), &block) if value.is_a?(::CSV::Table)
42
44
  return tree_class.new(value.as_json) if value.is_a?(tree_class)
45
+
43
46
  raise ArgumentError, "Expecting Eco::API::Organization::TagTree or CSV::Table. Given: #{value.class}"
44
47
  end
45
48
 
@@ -49,7 +52,12 @@ module Eco::Data::Locations::NodeBase
49
52
  # @yieldreturn [Hash] the serialized Node
50
53
  # @return [CSV::Table] a table with L1 to Ln columns ready for dump to csv
51
54
  def csv_tree(value, encoding: 'utf-8', attrs: [:id], &block) # rubocop:disable Lint/UnusedMethodArgument
52
- Eco::CSV::Table.new(hash_tree_to_tree_csv(hash_tree(value, &block), attrs: attrs))
55
+ Eco::CSV::Table.new(
56
+ hash_tree_to_tree_csv(
57
+ hash_tree(value, &block),
58
+ attrs: attrs
59
+ )
60
+ )
53
61
  end
54
62
 
55
63
  # @note it just converts to an organizational tagtree and uses a helper method.
@@ -2,14 +2,14 @@ module Eco::Data::Locations::NodeBase
2
2
  module TagValidations
3
3
  include Eco::Language::AuxiliarLogger
4
4
 
5
- ALLOWED_CHARACTERS = "A-Za-z0-9 &_'\/.-"
5
+ ALLOWED_CHARACTERS = "A-Za-z0-9 &_'\/.-".freeze
6
6
  VALID_TAG_REGEX = /^[#{ALLOWED_CHARACTERS}]+$/
7
7
  INVALID_TAG_REGEX = /[^#{ALLOWED_CHARACTERS}]+/
8
8
  VALID_TAG_CHARS = /[#{ALLOWED_CHARACTERS}]+/
9
9
  DOUBLE_BLANKS = /\s\s+/
10
10
 
11
11
  def clean_id(str, notify: true, ref: '')
12
- blanks_x2 = has_double_blanks?(str)
12
+ blanks_x2 = has_double_blanks?(str) # dubocop:disable Naming/VariableNumber
13
13
  partial = replace_not_allowed(str)
14
14
  remove_double_blanks(partial).tap do |result|
15
15
  next unless notify
@@ -3,6 +3,7 @@ class Eco::Data::Locations::NodeDiff::NodesDiff
3
3
  class DiffsTree
4
4
  class CyclicHierarchy < StandardError
5
5
  end
6
+
6
7
  class CyclicAncestorsChain < CyclicHierarchy
7
8
  end
8
9
 
@@ -37,12 +38,15 @@ class Eco::Data::Locations::NodeDiff::NodesDiff
37
38
  # supports building partial trees (clusters), where some parents
38
39
  # may not have presence.
39
40
  def parent_id
40
- return nil unless parent
41
+ return unless parent
42
+
41
43
  parent.id
42
44
  end
43
45
 
44
46
  def add_child(child_tree)
45
- raise ArgumentError, "Expecting #{self.class}. Given: #{child_tree.class}" unless child_tree.is_a?(self.class)
47
+ msg = "Expecting #{self.class}. Given: #{child_tree.class}"
48
+ raise ArgumentError, msg unless child_tree.is_a?(self.class)
49
+
46
50
  prevent_cyclic_chain(child_tree)
47
51
  children.push(child_tree)
48
52
  child_tree.link_parent(self)
@@ -69,8 +73,11 @@ class Eco::Data::Locations::NodeDiff::NodesDiff
69
73
  protected
70
74
 
71
75
  def link_parent(parent_node)
72
- raise ArgumentError, "Expecting #{self.class}. Given: #{parent_node.class}" unless parent_node.is_a?(self.class)
76
+ msg = "Expecting #{self.class}. Given: #{parent_node.class}"
77
+ raise ArgumentError, msg unless parent_node.is_a?(self.class)
78
+
73
79
  return (@parent = parent_node) unless parent
80
+
74
81
  msg = "Node '#{id}' already has a parent (#{parent.id}). "
75
82
  msg << "Can't make it child of '#{parent_node.id}' as well."
76
83
  raise CyclicHierarchy, msg
@@ -20,10 +20,16 @@ class Eco::Data::Locations::NodeDiff
20
20
 
21
21
  def initialize(*args, original_tree:, **kargs, &block)
22
22
  super(*args, **kargs, &block)
23
+
23
24
  @original_tree = original_tree
24
25
  mark_implicit_unarchive!
25
26
  end
26
27
 
28
+ def any?
29
+ diffs.any?
30
+ end
31
+ alias_method :any_diff?, :any?
32
+
27
33
  def diffs
28
34
  @diffs ||= super.select do |dff|
29
35
  # discard entries that are to be inserted and archived at the same time
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = '3.2.1'.freeze
2
+ VERSION = '3.2.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eco-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-16 00:00:00.000000000 Z
11
+ date: 2025-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -243,7 +243,7 @@ dependencies:
243
243
  version: '0.10'
244
244
  - - ">="
245
245
  - !ruby/object:Gem::Version
246
- version: 0.10.11
246
+ version: 0.10.14
247
247
  type: :runtime
248
248
  prerelease: false
249
249
  version_requirements: !ruby/object:Gem::Requirement
@@ -253,47 +253,47 @@ dependencies:
253
253
  version: '0.10'
254
254
  - - ">="
255
255
  - !ruby/object:Gem::Version
256
- version: 0.10.11
256
+ version: 0.10.14
257
257
  - !ruby/object:Gem::Dependency
258
258
  name: ecoportal-api-graphql
259
259
  requirement: !ruby/object:Gem::Requirement
260
260
  requirements:
261
261
  - - "~>"
262
262
  - !ruby/object:Gem::Version
263
- version: '1.2'
263
+ version: '1.3'
264
264
  - - ">="
265
265
  - !ruby/object:Gem::Version
266
- version: 1.2.1
266
+ version: 1.3.2
267
267
  type: :runtime
268
268
  prerelease: false
269
269
  version_requirements: !ruby/object:Gem::Requirement
270
270
  requirements:
271
271
  - - "~>"
272
272
  - !ruby/object:Gem::Version
273
- version: '1.2'
273
+ version: '1.3'
274
274
  - - ">="
275
275
  - !ruby/object:Gem::Version
276
- version: 1.2.1
276
+ version: 1.3.2
277
277
  - !ruby/object:Gem::Dependency
278
278
  name: ecoportal-api-v2
279
279
  requirement: !ruby/object:Gem::Requirement
280
280
  requirements:
281
281
  - - "~>"
282
282
  - !ruby/object:Gem::Version
283
- version: '3.2'
283
+ version: '3.3'
284
284
  - - ">="
285
285
  - !ruby/object:Gem::Version
286
- version: 3.2.1
286
+ version: 3.3.1
287
287
  type: :runtime
288
288
  prerelease: false
289
289
  version_requirements: !ruby/object:Gem::Requirement
290
290
  requirements:
291
291
  - - "~>"
292
292
  - !ruby/object:Gem::Version
293
- version: '3.2'
293
+ version: '3.3'
294
294
  - - ">="
295
295
  - !ruby/object:Gem::Version
296
- version: 3.2.1
296
+ version: 3.3.1
297
297
  - !ruby/object:Gem::Dependency
298
298
  name: ed25519
299
299
  requirement: !ruby/object:Gem::Requirement
@@ -667,7 +667,9 @@ files:
667
667
  - lib/eco/api/microcases/people/macro/take_email.rb
668
668
  - lib/eco/api/microcases/people/manage.rb
669
669
  - lib/eco/api/microcases/people/manage/cache.rb
670
+ - lib/eco/api/microcases/people/manage/filename.rb
670
671
  - lib/eco/api/microcases/people/manage/load.rb
672
+ - lib/eco/api/microcases/people/manage/load_cache.rb
671
673
  - lib/eco/api/microcases/people/manage/refresh.rb
672
674
  - lib/eco/api/microcases/people/manage/search.rb
673
675
  - lib/eco/api/microcases/people/preserve.rb
@@ -843,7 +845,9 @@ files:
843
845
  - lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_unarchive.rb
844
846
  - lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable.rb
845
847
  - lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable/relation_safe_sort.rb
846
- - lib/eco/api/usecases/graphql/helpers/location/command/optimizations.rb
848
+ - lib/eco/api/usecases/graphql/helpers/location/command/end_points.rb
849
+ - lib/eco/api/usecases/graphql/helpers/location/command/end_points/optimizations.rb
850
+ - lib/eco/api/usecases/graphql/helpers/location/command/input_unit_response.rb
847
851
  - lib/eco/api/usecases/graphql/helpers/location/command/result.rb
848
852
  - lib/eco/api/usecases/graphql/helpers/location/command/results.rb
849
853
  - lib/eco/api/usecases/graphql/helpers/location/tags_remap.rb
@@ -919,6 +923,12 @@ files:
919
923
  - lib/eco/api/usecases/samples/drivers/cli/url_pull_cli.rb
920
924
  - lib/eco/api/usecases/samples/drivers/sftp_sample.rb
921
925
  - lib/eco/api/usecases/samples/drivers/url_pull_sample.rb
926
+ - lib/eco/api/usecases/samples/people.rb
927
+ - lib/eco/api/usecases/samples/people/filters.rb
928
+ - lib/eco/api/usecases/samples/people/filters/cli/require_id_cli.rb
929
+ - lib/eco/api/usecases/samples/people/filters/cli/require_min_entries_cli.rb
930
+ - lib/eco/api/usecases/samples/people/filters/require_id_sample.rb
931
+ - lib/eco/api/usecases/samples/people/filters/require_min_entries_sample.rb
922
932
  - lib/eco/api/usecases/service.rb
923
933
  - lib/eco/api/usecases/service/sftp.rb
924
934
  - lib/eco/api/usecases/service/sftp/with_target_config.rb
@@ -1,84 +0,0 @@
1
- module Eco::API::UseCases::GraphQL::Helpers::Location
2
- module Command::Optimizations
3
- DEFAULT_COMMANDS_PER_PAGE = 45
4
- DEFAULT_FORCE_CONTINUE = false
5
-
6
- # Available options are:
7
- # - :per_request -> on each request
8
- # - :per_batch -> at the end of each batch / stage (on last page)
9
- # - :once -> only when the script starts to run
10
- def default_tree_tracking_mode
11
- :per_request
12
- end
13
-
14
- # Helper to identify the commands payload block
15
- # @note
16
- # 1. Gives flexibility on at what time the structure should be retrieved
17
- # 2. This increases performacne, as we don't retrieve the full tree on
18
- # each request unless necessary/specified
19
- # 3. `nil` falls the block back to the `ecoportal-api-graphql` gem, which
20
- # has a default block that retrieves the structure
21
- # @return [Proc, NilClass] the payload block
22
- def scope_commands_block(idx, total, track_tree_mode: default_tree_tracking_mode)
23
- case track_tree_mode
24
- when :per_request
25
- nil
26
- when :once
27
- commands_payload_without_structure_block
28
- when :per_batch
29
- return nil if idx == total
30
- commands_payload_without_structure_block
31
- end
32
- end
33
-
34
- # Prevents each request from timing out
35
- def commands_per_page
36
- if self.class.const_defined?(:COMMANDS_PER_PAGE)
37
- self.class::COMMANDS_PER_PAGE
38
- else
39
- DEFAULT_COMMANDS_PER_PAGE
40
- end
41
- end
42
-
43
- # Whether to stop or continue on command fail
44
- def force_continue?
45
- if self.class.const_defined?(:FORCE_CONTINUE)
46
- self.class::FORCE_CONTINUE
47
- else
48
- DEFAULT_FORCE_CONTINUE
49
- end
50
- end
51
-
52
- # Commands payload without querying Structure
53
- # @note this servces the purpose of optimizing/speeding up the requests.
54
- def commands_payload_without_structure_block
55
- proc {
56
- clientMutationId
57
- error { # rubocop:disable Style/BlockDelimiters
58
- message
59
- conflictingIds
60
- validationErrors { # rubocop:disable Style/BlockDelimiters
61
- error
62
- message
63
- }
64
- }
65
- results { # rubocop:disable Style/BlockDelimiters
66
- command { # rubocop:disable Style/BlockDelimiters
67
- id
68
- state
69
- __typename
70
- }
71
- ok
72
- error { # rubocop:disable Style/BlockDelimiters
73
- conflictingIds
74
- message
75
- validationErrors { # rubocop:disable Style/BlockDelimiters
76
- error
77
- message
78
- }
79
- }
80
- }
81
- }
82
- end
83
- end
84
- end