eco-helpers 2.0.9 → 2.0.14

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75a468069bd29d7dc25347e6da7d4d9faebc52043eba8b4ea1e91f6d383a8690
4
- data.tar.gz: dee338f8e23d4608f0d359bd44712377d15723c70730e823c11766f179f4877e
3
+ metadata.gz: 697d71754e809691a39f62a86d5fc46e2988578c19c965945e1c06ea73b290b6
4
+ data.tar.gz: 01ef5ca1a9bcf941d44b5f7088f54dd9c2cba950cc562ed0516400811df60f12
5
5
  SHA512:
6
- metadata.gz: 36c25c8a37c8fe894c57309e07126251e658846881698d4eec1660bf2a1a6cdc2e09f6b3f94c28434e47e7ea1f70cbf69196d2965d0a45609492867b2b356478
7
- data.tar.gz: 98bdbf74599ab4a3ab98ac6c76d068bbcf7871774e3f7315f992dbcb9cc31066ac7d2293b8cbee1bc3019bf94e1b9f78c7fdf02b8751cafb403451be12c8c159
6
+ metadata.gz: b24db6ddf741e3f0dcc3f080dba19132d7926c85cf211ae0f98c090c7a3cd93f513b6e977ac21ca24d5c2092d524cc1e7ef3d04250bb29ae672400623c823964
7
+ data.tar.gz: 9585e95676aab71322af2f174d06aed7d6226502bed1e2560cfd0915643e682c02fb857c33310f7c5f1b6d083b83267d14194f0f1e315c940048ef1c3c43faff
data/CHANGELOG.md CHANGED
@@ -1,32 +1,71 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- ## [2.0.9] - 2021-03-xx
4
+ ## [2.0.14] - 2021-03-xx
5
5
 
6
6
  ### Added
7
+ - `Eco::API::UseCases::DefaultCases::ToCsvCase` added option `-internal-names` to avoid overriding data on export
8
+ - `Eco::API::Common::People::PersonEntry#mapped_entry` exposed method for raw `csv` generation
9
+ - `Eco::API::Organization::PresetsFactory` added integrity validation for `person_*` abilities
10
+ - `Eco::API::Session::Batch::Job` more debug info on erron handlers
11
+
7
12
  ### Changed
8
- - `Eco::API::Session::Batch:Errors#person_ref` moved to the public method
13
+ ### Fixed
14
+ - `Eco::API::Error.get_type` was almost always matching `Eco::API::Error::Unclassified` -> fixed
15
+
16
+ ## [2.0.13] - 2021-03-31
17
+
18
+ ### Added
19
+ - Stats on the `Eco::API::Session::Batch`
20
+ - Allow to inherit and re-use the `Eco::API::UseCases::DefaultCase::HrisCase`
9
21
 
10
22
  ### Fixed
23
+ - Ensure auto-loading for `Eco::API::UseCases`
11
24
 
12
- ## [2.0.8] - 2021-03-09
25
+ ## [2.0.12] - 2021-03-29
26
+
27
+ ### Changed
28
+ - `Eco::CLI#run` it does include any defined states on the workflow
29
+
30
+
31
+ ## [2.0.11] - 2021-03-29
32
+
33
+ ### Fixed
34
+ - `Eco::API::Session::Batch:Errors#errors` changed `Array#filter` call to `Array#select` call
35
+
36
+ ## [2.0.10] - 2021-03-26
13
37
 
14
38
  ### Added
39
+ - `Eco::API::Common::People::PersonParser`
40
+ - `#defined_attrs`: list of all attribute defined parsers (regardless they belong to the model)
41
+ - `Eco::API::Organization::TagTree` methods
42
+ - `#total_depth` to know the total depth of a tree
43
+ - `#flat?` to know if the tagtree has only 1 level
44
+
15
45
  ### Changed
46
+ - `Eco::API::Common::People::PersonParser`
47
+ - Renamed `#all_attrs` to `#all_model_attrs`
48
+ - Ranamed `#defined_attrs` to `#defined_model_attrs`
49
+ - Ranamed `#undefined_attrs` to `#undefined_model_attrs`
50
+
51
+ ## [2.0.9] - 2021-03-19
52
+
53
+ ### Changed
54
+ - `Eco::API::Session::Batch:Errors#person_ref` moved to the public method
55
+
56
+ ## [2.0.8] - 2021-03-09
57
+
16
58
  ### Fixed
17
59
  - `Ecoportal::API::V1::Person#identity` adjust behavior
18
60
 
19
61
  ## [2.0.7] - 2021-03-09
20
62
 
21
- ### Added
22
- ### Changed
23
63
  ### Fixed
24
64
  - `Eco::API::Session::Batch::JobsGroups` and `Eco::API::Session::Batch::Jobs`: when new `Batch::Job`s are creating during launch, they remained unlaunched
25
65
  - this fix makes `#launch` method to iterate until there are no pending
26
66
 
27
67
  ## [2.0.6] - 2021-03-08
28
68
 
29
- ### Added
30
69
  ### Changed
31
70
  - `Eco::API::Session::Batch:Errors` moved some methods to be private
32
71
  ### Fixed
@@ -34,46 +73,33 @@ All notable changes to this project will be documented in this file.
34
73
 
35
74
  ## [2.0.5] - 2021-02-24
36
75
 
37
- ### Added
38
- ### Changed
39
76
  ### Fixed
40
77
  - `Eco::API::Common::People::PersonParser#symbol_keys` to use `Array#select`
41
78
  - as `Array#filter` was introduced in ruby `2.5.5`
42
79
 
43
80
  ## [2.0.4] - 2021-02-23
44
81
 
45
- ### Added
46
82
  ### Changed
47
83
  - `Eco::API::Common::People::PersonParser#defined_attrs` to include virtual attributes
48
84
 
49
- ### Fixed
50
-
51
85
  ## [2.0.3] - 2021-02-23
52
86
 
53
87
  ### Added
54
88
  - `Eco::API::UseCases::OozeSamples::OozeUpdateCase`: added integration to update page instances (non-templates)
55
89
 
56
- ### Changed
57
90
  ### Fixed
58
91
  - `Eco::API::Policies::DefaultPolicies::UserAccess` complete default policy code.
59
92
 
60
93
  ## [2.0.2] - 2021-02-22
61
94
 
62
- ### Added
63
95
  ### Changed
64
96
  - upgraded dependencies with `ecoportal-api`
65
97
 
66
- ### Fixed
67
-
68
-
69
98
  ## [2.0.1] - 2021-02-22
70
99
 
71
- ### Added
72
100
  ### Changed
73
101
  - upgraded dependencies with `ecoportal-api-oozes` to `ecoportal-api-v2`
74
102
 
75
- ### Fixed
76
-
77
103
  ## [1.5.15] - 2021-02-17
78
104
 
79
105
  ### Added
@@ -87,7 +113,6 @@ All notable changes to this project will be documented in this file.
87
113
  - `Eco::API::MicroCases#people_search`
88
114
  - `Eco::API::MicroCases#refresh`
89
115
 
90
- ### Changed
91
116
  ### Fixed
92
117
  - `Eco::API::Policies::DefaultPolicies::UserAccess` typos in default api policy
93
118
 
@@ -109,11 +134,8 @@ All notable changes to this project will be documented in this file.
109
134
  - `Eco::API::Common::People::PersonEntry` add error log when wrong email error is detected
110
135
  - previously it would have crashed
111
136
 
112
- ### Fixed
113
-
114
137
  ## [1.5.13] - 2021-02-01
115
138
 
116
- ### Added
117
139
  ### Changed
118
140
  - upgraded dependency with `ecoportal-api-oozes`
119
141
 
@@ -129,23 +151,16 @@ All notable changes to this project will be documented in this file.
129
151
  ### Changed
130
152
  - upgraded `ecoportal-api` dependency
131
153
 
132
- ### Fixed
133
-
134
-
135
154
  ## [1.5.11] - 2021-01-25
136
155
 
137
156
  ### Added
138
157
  - `Eco::API::Organization::TagTree#subtag?` to check if the tag is in any subtree.
139
158
 
140
- ### Changed
141
-
142
159
  ### Fixed
143
160
  - `Eco::API::MicroCases#set_supervisor` shouldn't set it if the entry does not have it.
144
161
 
145
162
  ## [1.5.10] - 2021-01-19
146
163
 
147
- ### Added
148
- ### Changed
149
164
  ### Fixed
150
165
  - `Eco::API::Session::Batch::Errors#print` show the row number of the input data.
151
166
 
@@ -154,14 +169,8 @@ All notable changes to this project will be documented in this file.
154
169
  ### Added
155
170
  - `Eco::API::Organization::TagTree#subtags` to get all the tags but those of the highest level.
156
171
 
157
- ### Changed
158
- ### Fixed
159
-
160
-
161
172
  ## [1.5.8] - 2021-01-05
162
173
 
163
- ### Added
164
- ### Changed
165
174
  ### Fixed
166
175
  - `Eco::API::Session::Batch::Jobs#job` shouldn't be calling the post-launch callback function on creation.
167
176
  - `Eco::API::Session#new_job` should include a `&block` parameter.
@@ -169,15 +178,11 @@ All notable changes to this project will be documented in this file.
169
178
 
170
179
  ## [1.5.7] - 2020-12-17
171
180
 
172
- ### Added
173
- ### Changed
174
181
  ### Fixed
175
182
  - `Eco::API::Sesssion#parse_attribute` was not using phase argument
176
183
 
177
184
  ## [1.5.6] - 2020-12-04
178
185
 
179
- ### Added
180
- ### Changed
181
186
  ### Fixed
182
187
  - `Eco::API::UseCases::DefaultCases::RestoreDBCase` fixed typo and slightly improved
183
188
  - fixed some back-end errors when chaining usecases
@@ -185,8 +190,6 @@ All notable changes to this project will be documented in this file.
185
190
 
186
191
  ## [1.5.5] - 2020-12-03
187
192
 
188
- ### Added
189
- ### Changed
190
193
  ### Fixed
191
194
  - rubies previous to `2.5` do not have `yield_self`
192
195
 
@@ -194,14 +197,11 @@ All notable changes to this project will be documented in this file.
194
197
 
195
198
  ### Added
196
199
  - update `ecoportal-api` dependency
197
- ### Changed
198
200
  ### Fixed
199
201
  - `Eco::API::MicroCases#people_refresh` typo
200
202
 
201
203
  ## [1.5.3] - 2020-11-30
202
204
 
203
- ### Added
204
- ### Changed
205
205
  ### Fixed
206
206
  - `Eco::API::Session::Batch::RequestStats#blanked_value?` better blank detection
207
207
  - `Eco::API::MicroCases#with_each_starter` rectified typo
@@ -342,14 +342,11 @@ All notable changes to this project will be documented in this file.
342
342
 
343
343
  ## [1.4.2] - 2020-07-23
344
344
 
345
- ### Added
346
- ### Changed
347
345
  ### Fixed
348
346
  - preserve backtrace on logging
349
347
 
350
348
  ## [1.4.0] - 2020-07-14
351
349
 
352
- ### Added
353
350
  ### Changed
354
351
  - change abilities to align with ecoPortal release `1.5.0`
355
352
  - remove some patches on `ecoportal-api`
@@ -359,22 +356,17 @@ All notable changes to this project will be documented in this file.
359
356
 
360
357
  ## [1.3.19] - 2020-07-23
361
358
 
362
- ### Added
363
- ### Changed
364
359
  ### Fixed
365
360
  - preserve backtrace on logging
366
361
 
367
362
  ## [1.3.18] - 2020-07-08
368
363
 
369
- ### Added
370
- ### Changed
371
364
  ### Fixed
372
365
  - the `update` case was missing the code to use the `default_usergroup`
373
366
 
374
367
 
375
368
  ## [1.3.17] - 2020-07-06
376
369
 
377
- ### Added
378
370
  ### Changed
379
371
  - the `hris` case should not only include as `leavers` those that have account, but anyone that leaves
380
372
  * as we could have active people with no account
@@ -397,7 +389,6 @@ All notable changes to this project will be documented in this file.
397
389
  ### Added
398
390
  - default usecase to export to `csv` (`-detailed`) now includes `"Supervisor Name"` column
399
391
  ### Changed
400
- ### Fixed
401
392
 
402
393
  ## [1.3.14] - 2020-06-10
403
394
 
@@ -405,33 +396,24 @@ All notable changes to this project will be documented in this file.
405
396
  - `Eco::API::Common::People::SupervisorHelpers` now has its methods as class methods
406
397
  ### Changed
407
398
  - upgraded `ecoportal-api` gem dependency to minimum version `0.5.6`
408
- ### Fixed
409
399
 
410
400
 
411
401
  ## [1.3.13] - 2020-05-29
412
402
 
413
- ### Added
414
- ### Changed
415
403
  ### Fixed
416
404
  - `Eco::API::Organization::TagTree#tag?` to accept `nil` by returning `false`
417
405
  - `Eco::API::Common::People::DefaultParsers::DateParser` will parse to `Date` class
418
406
  * it was parsing to `Time` class, while the native gem `ecoportal-api` parses as `Date` ([reference](https://gitlab.com/ecoPortal/ecoportal-api/-/blob/master/lib/ecoportal/api/v1/schema_field.rb))
419
407
  ## [1.3.12] - 2020-05-19
420
408
 
421
- ### Added
422
409
  ### Changed
423
410
  - stop using `email` as `external_id` on `People#person` & `People#find`
424
411
  * this should result in more accurate searches when using `:strict` options
425
- ### Fixed
426
-
427
412
 
428
413
  ## [1.3.11] - 2020-05-12
429
414
 
430
- ### Added
431
415
  ### Changed
432
416
  - remove popping up comments on `Eco::API::Organization::PolicyGroups#`
433
- ### Fixed
434
-
435
417
 
436
418
  ## [1.3.10] - 2020-05-12
437
419
 
@@ -440,14 +422,11 @@ All notable changes to this project will be documented in this file.
440
422
  - `config.people.default_usergroup`, when defined, will have effect on usecases: `update` (this case was missing the change)
441
423
  * on account creation, if the input file did not specify `policy_group_ids`
442
424
 
443
- ### Changed
444
425
  ### Fixed
445
426
  - `upsert`, `hris` and `create` usecases: fixed condition for use of default_usergroup
446
427
 
447
428
  ## [1.3.9] - 2020-05-12
448
429
 
449
- ### Added
450
- ### Changed
451
430
  ### Fixed
452
431
 
453
432
  - `usecase` callback was not receiving `usecase` paramater
@@ -8,7 +8,7 @@ module Eco
8
8
  # @return [Symbol] the `type` of usecase (i.e. `:sync`, `:transform`, `:import`, `:other`)
9
9
  def type(value = nil)
10
10
  unless value
11
- return @type || raise("You should specify a type of case [:sync, :transform, :import, :other] for #{self.class}")
11
+ return @type || raise("You should specify a type of case [:sync, :transform, :import, :other] for #{self}")
12
12
  end
13
13
  @type = value
14
14
  end
@@ -57,6 +57,11 @@ module Eco
57
57
  @internal_entry
58
58
  end
59
59
 
60
+ # @return [Hash] entry `Hash` with **internal** attribute names, but **external** types and values.
61
+ def mapped_entry
62
+ @mapped_entry
63
+ end
64
+
60
65
  # @note values ready to be set to a person.
61
66
  # @return [Hash] entry `Hash` with **internal** attribute names, values and types.
62
67
  def final_entry
@@ -256,7 +261,7 @@ module Eco
256
261
  # @param mapped_entry [Hash] that with **internal** names but **external** values and types.
257
262
  # @return [Hash] with **external** names, values and types.
258
263
  def _external_serializing(mapped_entry)
259
- target_attrs = @emap.all_attrs | @emap.aliased_attrs
264
+ target_attrs = @emap.all_model_attrs | @emap.aliased_attrs
260
265
  rest_keys = mapped_entry.keys - target_attrs
261
266
  target_attrs -= ["send_invites"]
262
267
  external_entry = target_attrs.each_with_object({}) do |attr, hash|
@@ -6,14 +6,14 @@ module Eco
6
6
  # @attr_reader core_attrs [Array<String>] core attributes that are present in the person entry.
7
7
  # @attr_reader details_attrs [Array<String>] schema details attributes that are present in the person entry.
8
8
  # @attr_reader account_attrs [Array<String>] account attributes that are present in the person entry.
9
- # @attr_reader all_attrs [Array<String>] all the attrs that are present in the person entry.
9
+ # @attr_reader all_model_attrs [Array<String>] all the attrs that are present in the person entry.
10
10
  # @attr_reader internal_attrs [Array<String>] all the internally named attributes that the person entry has.
11
11
  # @attr_reader aliased_attrs [Array<String>] only those internal attributes present in the person entry that have an internal/external name mapping.
12
12
  # @attr_reader direct_attrs [Array<String>] only those internal attributes present in the person entry that do **not** have an internal/external name mapping.
13
13
  class PersonEntryAttributeMapper
14
14
  @@cached_warnings = {}
15
15
 
16
- attr_reader :core_attrs, :details_attrs, :account_attrs, :all_attrs
16
+ attr_reader :core_attrs, :details_attrs, :account_attrs, :all_model_attrs
17
17
  attr_reader :internal_attrs, :aliased_attrs, :direct_attrs
18
18
 
19
19
  # Helper class tied to `PersonEntry` that allows to track which attributes of a person entry are present
@@ -41,14 +41,14 @@ module Eco
41
41
  init_attr_trackers
42
42
  else # SERIALIZING
43
43
  @person = data
44
- @internal_attrs = @person_parser.all_attrs
44
+ @internal_attrs = @person_parser.all_model_attrs
45
45
  @aliased_attrs = @attr_map.list(:internal)
46
46
  end
47
47
 
48
48
  @core_attrs = @person_parser.target_attrs_core(@internal_attrs)
49
49
  @details_attrs = @person_parser.target_attrs_details(@internal_attrs)
50
50
  @account_attrs = @person_parser.target_attrs_account(@internal_attrs)
51
- @all_attrs = @core_attrs | @account_attrs | @details_attrs
51
+ @all_model_attrs = @core_attrs | @account_attrs | @details_attrs
52
52
  end
53
53
 
54
54
  # To know if currently the object is in parse or serialize mode.
@@ -98,7 +98,7 @@ module Eco
98
98
  end
99
99
  end
100
100
 
101
- return nil unless @person_parser.all_attrs.include?(attr)
101
+ return nil unless @person_parser.all_model_attrs.include?(attr)
102
102
  end
103
103
 
104
104
  # Serializing helper also used to do a reverse mapping when parsing:
@@ -146,9 +146,9 @@ module Eco
146
146
  # when parsing:
147
147
  def init_attr_trackers
148
148
  # (def) all internal attributes we can expect
149
- def_all_attrs = @person_parser.all_attrs
149
+ def_all_attrs = @person_parser.all_model_attrs
150
150
  # (def) internal attrs with no aliasing nor parser definition (expected to be direct)
151
- def_unlinked = @person_parser.undefined_attrs.select { |attr| !to_external(attr) }
151
+ def_unlinked = @person_parser.undefined_model_attrs.select { |attr| !to_external(attr) }
152
152
  # (def) those with parser or alias:
153
153
  def_linked = def_all_attrs - def_unlinked
154
154
 
@@ -168,7 +168,7 @@ module Eco
168
168
  # (data) virtual internal attrs (the internal names of those virtual attrs)
169
169
  data_vi_int_aliased = data_vi_ext_alias.map do |attr|
170
170
  # to_internal(attr) can't be used here, becauase virtual fields would get filtered out,
171
- # as they are not recognized by @parser.all_attrs.include?(attr)
171
+ # as they are not recognized by @parser.all_model_attrs.include?(attr)
172
172
  @attr_map.to_internal(attr)
173
173
  end.compact
174
174
 
@@ -7,7 +7,7 @@ module Eco
7
7
  #
8
8
  # @attr_reader schema [Ecoportal::API::V1::PersonSchema, nil] schema of person details that this parser will be based upon.
9
9
  # @attr_reader details_attrs [Array<String>] internal names of schema details attributes.
10
- # @attr_reader all_attrs [Array<String>] all the internal name attributes, including _core_, _account_ and _details_.
10
+ # @attr_reader all_model_attrs [Array<String>] all the internal name attributes, including _core_, _account_ and _details_.
11
11
  class PersonParser
12
12
  extend Eco::API::Common::ClassAutoLoader
13
13
  autoloads_children_of "Eco::API::Common::Loaders::Parser"
@@ -19,8 +19,7 @@ module Eco
19
19
  FORMAT = [:csv, :xml, :json]
20
20
 
21
21
  attr_reader :schema
22
- attr_reader :details_attrs, :all_attrs
23
- attr_reader :defined_attrs
22
+ attr_reader :details_attrs, :all_model_attrs
24
23
  attr_reader :patch_version
25
24
 
26
25
  # @example Example of usage:
@@ -46,7 +45,7 @@ module Eco
46
45
  @details_attrs = @schema&.fields.map { |fld| fld.alt_id }
47
46
  end
48
47
 
49
- @all_attrs = CORE_ATTRS + ACCOUNT_ATTRS + @details_attrs
48
+ @all_model_attrs = CORE_ATTRS + ACCOUNT_ATTRS + @details_attrs
50
49
  self.class.autoload_children(self)
51
50
  end
52
51
 
@@ -60,6 +59,11 @@ module Eco
60
59
 
61
60
  # @!group Scopping attributes (identifying, presence & active)
62
61
 
62
+ # All the internal name attributes, including _core_, _account_ and _details_.
63
+ def all_attrs(include_defined_parsers: false)
64
+ all_model_attrs | defined_model_attrs
65
+ end
66
+
63
67
  # Scopes `source_attrs` using the _**core** attributes_.
64
68
  # @note use this helper to know which among your attributes are **core** ones.
65
69
  # @param source_attrs [Array<String>]
@@ -93,14 +97,21 @@ module Eco
93
97
  @parsers.keys
94
98
  end
95
99
 
100
+ # Returns a list of all the internal attributes that have a parser defined.
101
+ # @note These attributes do not necessarily belong to the model. They could be virtual attributes
102
+ # @return [Array<String>] list of all attribute defined parsers.
103
+ def defined_attrs
104
+ defined_list - symbol_keys
105
+ end
106
+
96
107
  # Returns a list of all the internal attributes of the model that have a parser defined.
97
108
  # @note
98
109
  # - it excludes any parser that is not in the model, such as type parsers (i.e. `:boolean`, `:multiple`)
99
110
  # - the list is sorted according `CORE_ATTRS` + `ACCOUNT_ATTRS` + schema attrs
100
- # @return [Array<String>] list of all attribute defined parsers.
101
- def defined_attrs
111
+ # @return [Array<String>] list of all attribute defined parsers in the model.
112
+ def defined_model_attrs
102
113
  defined = @parsers.keys
103
- defined = (all_attrs | defined) & defined
114
+ defined = (all_model_attrs | defined) & defined
104
115
  defined - symbol_keys
105
116
  end
106
117
 
@@ -118,7 +129,7 @@ module Eco
118
129
  # @param process [Symbol] either `:parse` or `:serialize`, depending if we want to parse or serialize the `attr`.
119
130
  # @return [Array<String>] list of all attribute defined parsers that should be active for the given `source_data`.
120
131
  def active_attrs(source_data, phase = :any, process: :parse)
121
- defined_attrs.select do |attr|
132
+ defined_model_attrs.select do |attr|
122
133
  if process == :serialize
123
134
  @parsers[attr].serializer_active?(phase)
124
135
  else
@@ -130,8 +141,8 @@ module Eco
130
141
  # Returns a list of all the internal attributes of the model that do **not** have a parser defined.
131
142
  # @note it excludes any parser that is **not** in the model, such as type parsers (i.e. :boolean, :multiple)
132
143
  # @return [Array<String>] list of all attributes without a defined parser.
133
- def undefined_attrs
134
- all_attrs - defined_attrs
144
+ def undefined_model_attrs
145
+ all_model_attrs - defined_model_attrs
135
146
  end
136
147
 
137
148
  # @param attr [String] internal name of an attribute.
@@ -238,7 +249,7 @@ module Eco
238
249
  end
239
250
 
240
251
  def valid_attr?(attr)
241
- attr.is_a?(String) && (!@schema || @all_attrs.include?(attr))
252
+ attr.is_a?(String) && (!@schema || @all_model_attrs.include?(attr))
242
253
  end
243
254
 
244
255
  def valid_type?(attr)
data/lib/eco/api/error.rb CHANGED
@@ -80,6 +80,7 @@ module Eco
80
80
  next 1 if k1 < k2
81
81
  0
82
82
  end.tap do |siblings|
83
+ siblings.delete(Unclassified)
83
84
  if direct
84
85
  siblings.reject! do |si|
85
86
  siblings.any? {|s| si < s}
@@ -96,17 +97,18 @@ module Eco
96
97
  err_msg =~ @match
97
98
  end
98
99
 
99
- def get_type(err_msg)
100
+ def get_type(err_msg, first: true)
100
101
  type = nil
101
102
  descendants(direct: true).reverse.each do |klass|
102
103
  if klass.err_match?(err_msg)
103
104
  type = klass
104
105
  if klass.descendants?(direct: true)
105
- type = klass.get_type(err_msg) || type
106
+ type = klass.get_type(err_msg, first: false) || type
106
107
  end
107
108
  end
108
109
  end
109
- type
110
+ return type unless first
111
+ type || Unclassified
110
112
  end
111
113
 
112
114
  def known_err_class?(klass)
@@ -4,38 +4,27 @@ module Eco
4
4
 
5
5
  class PresetsFactory
6
6
  ABILITIES = File.join(__dir__, 'presets_values.json')
7
+ INTEGRITY = File.join(__dir__, 'presets_integrity.json')
7
8
  DEFAULT_CUSTOM = 'presets_custom.json'
8
9
  DEFAULT_MAP = 'presets_map.json'
9
10
 
10
11
  def initialize(presets_custom: DEFAULT_CUSTOM, presets_map: DEFAULT_MAP, enviro: nil, policy_groups: nil)
11
- @abilities = JSON.load(File.open(ABILITIES))
12
- @habilities = @abilities.map do |key, values|
13
- h_values = values.map { |v| [v, true] }.to_h
14
- [key, h_values]
15
- end.to_h
16
-
17
12
  fatal("Expecting Environment object. Given: #{enviro}") if enviro && !enviro.is_a?(Eco::API::Common::Session::Environment)
18
- @enviro = enviro
19
-
20
- policy_groups = policy_groups || @enviro&.api&.policy_groups.to_a
21
- if policy_groups.is_a?(Eco::API::Organization::PolicyGroups)
22
- @policy_groups = policy_groups
23
- else
24
- @policy_groups = Eco::API::Organization::PolicyGroups.new(policy_groups)
25
- end
13
+ @enviro = enviro
26
14
 
27
- init_custom(presets_custom)
28
- init_map(presets_map)
15
+ @policy_groups = policy_groups
16
+ @presets_custom_file = presets_custom || DEFAULT_CUSTOM
17
+ @presets_map_file = presets_map || DEFAULT_MAP
29
18
  end
30
19
 
31
20
  def new(*policy_group_ids_or_names)
32
21
 
33
22
  names = policy_group_ids_or_names.map do |id_name|
34
- @policy_groups.to_name(id_name)&.downcase
23
+ policy_groups.to_name(id_name)&.downcase
35
24
  end.compact
36
25
 
37
- if @presets_map
38
- preset_names = names.map { |name| @presets_map.fetch(name, nil) }
26
+ if presets_map
27
+ preset_names = names.map { |name| presets_map.fetch(name, nil) }
39
28
  else # option to do not use preset mapping (so just the policy group name)
40
29
  preset_names = names
41
30
  end
@@ -44,69 +33,11 @@ module Eco
44
33
 
45
34
  # @return [Array<String>] all the abilities
46
35
  def keys
47
- @abilities.keys
36
+ abilities_model.keys
48
37
  end
49
38
 
50
39
  private
51
40
 
52
- def init_custom(file = DEFAULT_CUSTOM)
53
- @presets_custom = nil
54
-
55
- return if !file
56
- file = File.expand_path(file)
57
-
58
- if File.exists?(file)
59
- @presets_custom = JSON.load(File.open(file))
60
-
61
- errors = @presets_custom.map do |key, preset|
62
- (err = preset_errors(preset)) ? "{ '#{key}' preset -> #{err}}": nil
63
- end.compact
64
-
65
- fatal("File '#{file}' contains invalid presets:\n #{errors.join("\n ")}") if errors.length > 0
66
- end
67
-
68
- end
69
-
70
- def init_map(file = DEFAULT_MAP)
71
- @presets_map = nil
72
-
73
- return if !file
74
- file = File.expand_path(file)
75
-
76
- if File.exists?(file)
77
- fatal("Maps file specified without custom presets file. Aborting!") if !@presets_custom
78
- @presets_map = JSON.load(File.open(file))
79
-
80
- errors = []
81
- if @policy_groups.length > 0
82
- errors = @policy_groups.map do |pg|
83
- exists = @presets_map[pg.name.downcase] || @presets_custom[pg.name.downcase]
84
- exists ? nil : "'#{pg.name}'"
85
- end.compact
86
-
87
- warn("No maps or no preset for policy group(s): #{errors.join(", ")}") if errors.length > 0
88
- end
89
-
90
- errors = @presets_map.map do |source, dest|
91
- @presets_custom[dest] ? nil : "'#{dest}'"
92
- end.compact
93
-
94
- warn("Unexisting mapped preset(s): #{errors.uniq.join(", ")}") if errors.length > 0
95
- end
96
-
97
- end
98
-
99
- def fatal(msg)
100
- raise msg if !@enviro
101
- @enviro.logger.fatal(msg)
102
- raise msg
103
- end
104
-
105
- def warn(msg)
106
- raise msg if !@enviro
107
- @enviro.logger.warn(msg)
108
- end
109
-
110
41
  def compile(*preset_names)
111
42
  fatal("You need to specify an existing file for the custom presets.") if !@presets_custom
112
43
  @presets_custom.values_at(*preset_names).compact.reduce({}) do |p1, p2|
@@ -117,7 +48,7 @@ module Eco
117
48
  def merge(preset1, preset2)
118
49
  keys = preset1.keys | preset2.keys
119
50
 
120
- @abilities.each_with_object({}) do |(key, values), result|
51
+ abilities_model.each_with_object({}) do |(key, values), result|
121
52
  next unless keys.include?(key)
122
53
  idx = [
123
54
  values.index(preset1[key]),
@@ -129,17 +60,149 @@ module Eco
129
60
 
130
61
  # unsused: only play with the given abilities
131
62
  def empty_model
132
- JSON.parse(@abilities.to_json).transform_values {|v| nil }
63
+ JSON.parse(abilities_model.to_json).transform_values {|v| nil }
133
64
  end
134
65
 
135
66
  def preset_errors(preset)
136
67
  return "No preset given" if !preset
137
68
  errors = preset.map do |k, v|
138
- @habilities.dig(k, v) ? nil : "#{k}:#{v}"
69
+ value_exists?(k, v) ? nil : "#{k}:#{v}"
139
70
  end.compact
140
- return " unknown: {#{errors.join(", ")}}" if errors.length > 0
71
+ return " Unknown: {#{errors.join(", ")}}" if errors.length > 0
141
72
  nil
142
73
  end
74
+
75
+ def preset_integrity(preset)
76
+ preset.each_with_object([]) do |(ability, value), errors|
77
+ next unless checks = integrity_model[ability]
78
+
79
+ suberrors = []
80
+
81
+ checks.each do |check|
82
+ next unless check["value"] == value
83
+ check["conditions"].each do |cond, targets|
84
+ case cond
85
+ when "at_least"
86
+ targets.each do |other, minimum|
87
+ unless (ability_value_idx(other, minimum) <= ability_value_idx(other, preset[other]))
88
+ suberrors << "'#{other}' should be at least '#{minimum}'"
89
+ end
90
+ end
91
+ when "one_of"
92
+ unless targets.any? {|other, expected| preset[other] == expected}
93
+ suberrors << targets.each_with_object([]) do |(other, expected), out|
94
+ out << "'#{other}': '#{expected}'"
95
+ end.join(", ").yield_self do |msg|
96
+ "there should be at least one of: {#{msg}}"
97
+ end
98
+ end
99
+ else
100
+ warn("Unsuported integrity condition statement '#{cond}' in '#{ability}' with level '#{value}'")
101
+ end
102
+ end
103
+ end
104
+
105
+ if suberrors.length > 0
106
+ errors << "Incorrect value '#{value}' for '#{ability}' - reasons: {#{suberrors.join(", ")}}"
107
+ end
108
+ end.yield_self do |errors|
109
+ " Integrity errors: { #{errors.join(", ")} }" if errors.length > 0
110
+ end
111
+ end
112
+
113
+ def integrity_model
114
+ @integrity_model ||= JSON.load(File.open(INTEGRITY))
115
+ end
116
+
117
+ def value_exists?(ability, value)
118
+ abilities_model_inverted.dig(ability, value)
119
+ end
120
+
121
+ def abilities_model_inverted
122
+ @abilities_model_inverted ||= abilities_model.each_with_object({}) do |(key, values), out|
123
+ out[key] = values.each_with_object({}) {|v, h| h[v] = true }
124
+ end
125
+ end
126
+
127
+ def ability_value_idx(ability, value)
128
+ abilities_model[ability].index(value)
129
+ end
130
+
131
+ def abilities_model
132
+ @abilities_model ||= JSON.load(File.open(ABILITIES))
133
+ end
134
+
135
+ def policy_groups
136
+ return @policy_groups if @policy_groups.is_a?(Eco::API::Organization::PolicyGroups)
137
+ @policy_groups ||= @enviro&.api&.policy_groups.to_a
138
+
139
+ unless @policy_groups.is_a?(Eco::API::Organization::PolicyGroups)
140
+ @policy_groups = Eco::API::Organization::PolicyGroups.new(@policy_groups)
141
+ end
142
+ @policy_groups
143
+ end
144
+
145
+ def presets_custom
146
+ return @presets_custom if instance_variable_defined?(:@presets_custom)
147
+ @presets_custom = nil
148
+ if @presets_custom_file
149
+ if (file = File.expand_path(@presets_custom_file)) && File.exists?(file)
150
+ @presets_custom = JSON.load(File.open(file)).tap do |custom_presets|
151
+ errors = custom_presets.each_with_object([]) do |(key, preset), errors|
152
+ if err = preset_errors(preset)
153
+ errors << "{ '#{key}' preset -> #{err}}"
154
+ end
155
+ if err = preset_integrity(preset)
156
+ errors << "{ '#{key}' preset -> #{err}}"
157
+ end
158
+ end
159
+
160
+ fatal("File '#{file}' contains invalid presets:\n #{errors.join("\n ")}") if errors.length > 0
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ def presets_map
167
+ return @presets_map if instance_variable_defined?(:@presets_map)
168
+ @presets_map = nil
169
+ if @presets_map_file
170
+ if (file = File.expand_path(@presets_map_file)) && File.exists?(file)
171
+ fatal("Maps file specified without 'presets_custom.json' file. Aborting!") if !presets_custom
172
+ @presets_map = JSON.load(File.open(file)).tap do |map_presets|
173
+
174
+ errors = []
175
+ if policy_groups.length > 0
176
+ errors = policy_groups.map do |pg|
177
+ exists = map_presets[pg.name.downcase] || presets_custom[pg.name.downcase]
178
+ exists ? nil : "'#{pg.name}'"
179
+ end.compact
180
+
181
+ warn("No maps or no preset for policy group(s): #{errors.join(", ")}") if errors.length > 0
182
+ end
183
+
184
+ errors = map_presets.map do |source, dest|
185
+ presets_custom[dest] ? nil : "'#{dest}'"
186
+ end.compact
187
+
188
+ warn("Unexisting mapped preset(s): #{errors.uniq.join(", ")}") if errors.length > 0
189
+
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ def fatal(msg)
196
+ raise msg if !@enviro
197
+ @enviro.logger.fatal(msg)
198
+ raise msg
199
+ end
200
+
201
+ def warn(msg)
202
+ raise msg if !@enviro
203
+ @enviro.logger.warn(msg)
204
+ end
205
+
143
206
  end
144
207
 
145
208
  end
@@ -0,0 +1,52 @@
1
+ {
2
+ "person_core_create": [
3
+ { "value": "create", "conditions": {
4
+ "at_least": {"person_core": "view_people_manager"}
5
+ }
6
+ }
7
+ ],
8
+ "person_core_edit": [
9
+ { "value": "edit", "conditions": {
10
+ "at_least": {"person_core": "view_people_manager"}
11
+ }
12
+ }
13
+ ],
14
+ "person_details": [
15
+ { "value": "view", "conditions": {
16
+ "at_least": {"person_core": "attach"}
17
+ }
18
+ },
19
+ { "value": "edit_public", "conditions": {
20
+ "one_of": {
21
+ "person_core_edit": "edit",
22
+ "person_core_create": "create"
23
+ }
24
+ }
25
+ },
26
+ { "value": "view_private", "conditions": {
27
+ "at_least": {"person_core": "attach" }
28
+ }
29
+ },
30
+ { "value": "edit_private", "conditions": {
31
+ "one_of": {
32
+ "person_core_edit": "edit",
33
+ "person_core_create": "create"
34
+ }
35
+ }
36
+ }
37
+ ],
38
+ "person_account": [
39
+ { "value": "view", "conditions": {
40
+ "at_least": {"person_core": "attach" }
41
+ }
42
+ },
43
+ { "value": "create", "conditions": {
44
+ "at_least": {"person_core_create": "create"}
45
+ }
46
+ },
47
+ { "value": "edit", "conditions": {
48
+ "at_least": {"person_core_edit": "edit"}
49
+ }
50
+ }
51
+ ]
52
+ }
@@ -4,7 +4,7 @@ module Eco
4
4
 
5
5
  # Provides helpers to deal with tagtrees.
6
6
  class TagTree
7
- attr_reader :tag, :nodes
7
+ attr_reader :tag, :nodes, :children_count
8
8
  attr_reader :depth, :path
9
9
  attr_reader :enviro
10
10
 
@@ -37,6 +37,7 @@ module Eco
37
37
 
38
38
  nodes = @source.is_a?(Array) ? @source : @source.dig('nodes') || []
39
39
  @nodes = nodes.map {|cnode| TagTree.new(cnode, depth: @depth + 1, path: @path.dup, enviro: @enviro)}
40
+ @children_count = @nodes.count
40
41
 
41
42
  init_hashes
42
43
  end
@@ -46,6 +47,21 @@ module Eco
46
47
  @has_tags.empty?
47
48
  end
48
49
 
50
+ # @return [Integer] the highest `depth` of all the children.
51
+ def total_depth
52
+ @total_depth ||= if children_count > 0
53
+ deepest_node = nodes.max_by {|node| node.total_depth}
54
+ deepest_node.depth
55
+ else
56
+ depth
57
+ end
58
+ end
59
+
60
+ # @return [Integer] if there's only top level.
61
+ def flat?
62
+ self.total_depth <= 0
63
+ end
64
+
49
65
  # Gets all the tags of the current node tree.
50
66
  # @note
51
67
  # - this will include the upper level tag(s) as well
@@ -147,7 +163,8 @@ module Eco
147
163
  # * take the deepest tag (the one that is further down in the tree)
148
164
  # * if there are different options (several nodes at the same depth):
149
165
  # * take the common node between them (i.e. you have Hamilton and Auckland -> take New Zealand)
150
- # * if there's no common node between them, take the `first` (unless they are at top level of the tree)
166
+ # * if there's no common node between them, take the `first`, unless they are at top level of the tree
167
+ # * to the above, take the `first` also on top level, but only if there's 1 level for the entire tree
151
168
  # @param [Array<String>] values list of tags.
152
169
  # @return [String] default tag.
153
170
  def default_tag(*values)
@@ -169,7 +186,7 @@ module Eco
169
186
  common = nodes.reduce(self.tags.reverse) {|com, cnode| com & cnode.path.reverse}
170
187
  default_tag = common.first if common.length > 0 && depth > 0
171
188
  end
172
- default_tag = nodes.first&.tag if !default_tag && depth > 0
189
+ default_tag = nodes.first&.tag if !default_tag && ( (depth > 0) || flat?)
173
190
  default_tag
174
191
  end
175
192
 
@@ -105,10 +105,15 @@ module Eco
105
105
  iterations = (data.length.to_f / per_page).ceil
106
106
 
107
107
  Eco::API::Session::Batch::Status.new(enviro, queue: data, method: method).tap do |status|
108
+ start_time = Time.now
109
+ start_slice = Time.now; slice = []
108
110
  data.each_slice(per_page) do |slice|
109
- msg = "starting batch '#{method}' iteration #{iteration}/#{iterations}, with #{slice.length} entries of #{data.length} -- #{done} done"
111
+ msg = "starting batch '#{method}' iteration #{iteration}/#{iterations},"
112
+ msg += " with #{slice.length} entries of #{data.length} -- #{done} done"
113
+ msg += " (last: #{str_stats(start_slice, slice.length)}; total: #{str_stats(start_time, done)})"
110
114
  logger.info(msg) unless silent
111
115
 
116
+ start_slice = Time.now
112
117
  people_api.batch do |batch|
113
118
  slice.each do |person|
114
119
  batch.public_send(method, person) do |response|
@@ -118,12 +123,23 @@ module Eco
118
123
  end
119
124
  end # next batch
120
125
 
121
- iteration += 1
122
- done += slice.length
126
+ iteration += 1
127
+ done += slice.length
123
128
  end # next slice
124
129
  end
125
130
  end
126
131
 
132
+ def str_stats(start, count)
133
+ now = Time.now
134
+ secs = (now - start).round(3)
135
+ if secs > 0.0
136
+ per_sec = (count.to_f / secs).round(2)
137
+ "#{secs}s -> #{per_sec} people/s"
138
+ else
139
+ " -- "
140
+ end
141
+ end
142
+
127
143
  end
128
144
  end
129
145
  end
@@ -124,7 +124,7 @@ module Eco
124
124
  # - please, observe that this can only happen if there were repeated entries in the `source_queue`
125
125
  # @return [Array<Hash>, Array<Ecoportal::API::V1::Person>, Array<Ecoportal::API::Internal::Person>]
126
126
  def entries
127
- queue.filter.with_index do |query, i|
127
+ queue.select.with_index do |query, i|
128
128
  unless response = status[i]
129
129
  msg = "Error: query with no response. You might have duplicated entries in your queue.\n"
130
130
  msg += "Queue length: #{queue.length}; Queue elements class: #{queue.first.class}\n"
@@ -45,25 +45,22 @@ module Eco
45
45
  # @!group Pure feedback methods
46
46
 
47
47
  # Slightly modifies the behaviour of `Ecoportal::API::Common::BaseModel#as_update`, so schema details fields show the `alt_id`
48
+ # It also fixes possible patch updates that are incomplete or unnecessary.
48
49
  # @note for better feedback
49
50
  # @param entry [Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
50
- def as_update(entry)
51
+ # @param add_feedback [Boolean] if `true` it tweak the hash update with additional data.
52
+ def as_update(entry, add_feedback: true)
51
53
  case
52
54
  when entry.is_a?(Hash)
53
55
  hash = entry
54
56
  else #entry.is_a?(Ecoportal::API::V1::Person)
55
57
  if only_ids?
56
- hash = {
57
- "id" => entry.id,
58
- "external_id" => entry.external_id,
59
- "email" => entry.email
60
- }
61
58
  hash = entry.as_json.slice("id", "external_id", "email")
62
59
  else
63
60
  hash = entry.as_update
64
- #if entry.details
65
- if hash["details"]
66
- if hfields = hash.dig("details", "fields")
61
+
62
+ if add_feedback && details = hash["details"]
63
+ if hfields = details["fields"]
67
64
  hfields.each do |fld|
68
65
  fld.merge!("alt_id" => entry.details.get_field(fld["id"]).alt_id)
69
66
  end
@@ -169,7 +169,8 @@ module Eco
169
169
 
170
170
  unless simulate
171
171
  if pqueue.length > 0
172
- backup_update(requests)
172
+ req_backup = pqueue.map {|e| as_update(e, add_feedback: false)}
173
+ backup_update(req_backup)
173
174
  session.batch.launch(pqueue, method: type).tap do |job_status|
174
175
  @status = job_status
175
176
  status.root = self
@@ -217,7 +218,7 @@ module Eco
217
218
  [].tap do |msg|
218
219
  subjobs.map {|subjob| msg << subjob.summary}
219
220
  end.join("\n")
220
- end
221
+ end
221
222
 
222
223
  def as_update(*args)
223
224
  feedback.as_update(*args)
@@ -287,10 +288,13 @@ module Eco
287
288
  handlers = session.config.error_handlers
288
289
  if status.errors.any? && !handlers.empty? && !error_handler?
289
290
  err_types = status.errors.by_type
291
+ logger.debug("(#{self.name}) got these error types: #{err_types.keys}")
290
292
  handlers.each do |handler|
291
293
  if entries = err_types[handler.name]
292
294
  handler_job = subjobs_add("#{self.name} => #{handler.name}", usecase: handler)
295
+ logger.debug("Running error handler #{handler.name}")
293
296
  handler.launch(people: people(entries), session: session, options: options, job: handler_job)
297
+ logger.debug("Launching job of error handler: #{handler_job.name}")
294
298
  handler_job.launch(simulate: simulate)
295
299
  end
296
300
  end
@@ -30,6 +30,7 @@ module Eco
30
30
  @usecases = {}
31
31
  @cache_init = false
32
32
  @cases_by_name = {}
33
+ init_caches
33
34
  end
34
35
 
35
36
  def length
@@ -79,6 +80,7 @@ module Eco
79
80
 
80
81
  # @return [Eco::API::UseCases] a copy of instance object of `self`.
81
82
  def dup
83
+ init_caches
82
84
  self.class.new.merge(self)
83
85
  end
84
86
 
@@ -2,18 +2,17 @@ class Eco::API::UseCases::DefaultCases::HrisCase < Eco::API::Common::Loaders::Us
2
2
  name "hris"
3
3
  type :sync
4
4
 
5
+ attr_reader :creation, :update, :supers, :leavers
6
+
5
7
  def main(entries, people, session, options, usecase)
6
8
  micro = session.micro
7
- creation = session.new_job("main", "create", :create, usecase)
8
- update = session.new_job("main", "update", :update, usecase)
9
- supers = session.new_job("post", "supers", :update, usecase, :core)
10
- leavers = session.new_job("post", "leavers", :update, usecase, :account)
9
+ @creation = session.new_job("main", "create", :create, usecase)
10
+ @update = session.new_job("main", "update", :update, usecase)
11
+ @supers = session.new_job("post", "supers", :update, usecase, :core)
12
+ @leavers = session.new_job("post", "leavers", :update, usecase, :account)
11
13
 
12
14
  micro.with_each_leaver(entries, people, options) do |person|
13
- leavers.add(person) do |person|
14
- person.supervisor_id = nil
15
- person.account = nil if person.account
16
- end
15
+ leavers.add(person, &method(:leavers_callback))
17
16
  end
18
17
 
19
18
  micro.with_each(entries, people, options) do |entry, person|
@@ -24,4 +23,11 @@ class Eco::API::UseCases::DefaultCases::HrisCase < Eco::API::Common::Loaders::Us
24
23
  end
25
24
  end
26
25
 
26
+ private
27
+
28
+ def leavers_callback(person)
29
+ person.supervisor_id = nil
30
+ person.account = nil if person.account
31
+ end
32
+
27
33
  end
@@ -2,7 +2,11 @@ class Eco::API::UseCases::DefaultCases::ToCsvCase < Eco::API::Common::Loaders::U
2
2
  name "to-csv"
3
3
  type :export
4
4
 
5
+ attr_reader :session, :options, :people
6
+
5
7
  def main(people, session, options, usecase)
8
+ @session = session; @options = options; @people = people
9
+
6
10
  unless people && !people.empty?
7
11
  session.logger.warn("No source people to create the file... aborting!")
8
12
  return false
@@ -14,32 +18,48 @@ class Eco::API::UseCases::DefaultCases::ToCsvCase < Eco::API::Common::Loaders::U
14
18
  end
15
19
 
16
20
  session.logger.info("going to create file: #{file}")
17
- CSV.open(file, "w") do |csv|
18
- deps = {"supervisor_id" => {people: people}}
19
- entry = session.new_entry(people.first, dependencies: deps)
20
- header = entry.external_entry.keys
21
-
22
- if options.dig(:nice_header) || options.dig(:export, :options, :nice_header)
23
- name_maps = session.schema.fields_by_alt_id.transform_values do |fld|
24
- fld.name
25
- end.merge({
26
- "policy_group_ids" => "User Group(s)",
27
- "email" => "Email",
28
- "name" => "Name",
29
- "supervisor_id" => "Manager ID",
30
- "filter_tags" => "Locations",
31
- "default_tag" => "Default Location",
32
- "id" => "ecoPortal ID"
33
- })
34
- header = header.map {|name| name_maps[name] ? name_maps[name] : name}
35
- end
36
21
 
37
- csv << header
22
+ CSV.open(file, "w") do |csv|
23
+ csv << spot_header
38
24
  people.each do |person|
39
- csv << session.new_entry(person, dependencies: deps).external_entry.values
25
+ csv << target_entry_type(person).values
40
26
  end
41
27
  end
42
28
  exit(0)
43
29
  end
44
30
 
31
+ private
32
+
33
+ def target_entry_type(person)
34
+ session.new_entry(person, dependencies: deps).yield_self do |person_entry|
35
+ options.dig(:export, :options, :internal_names) ? person_entry.mapped_entry : person_entry.external_entry
36
+ end
37
+ end
38
+
39
+ def deps
40
+ @deps ||= {"supervisor_id" => {people: people}}
41
+ end
42
+
43
+ def spot_header
44
+ entry = target_entry_type(people.first)
45
+ header = entry.keys
46
+
47
+ if options.dig(:nice_header) || options.dig(:export, :options, :nice_header)
48
+ name_maps = session.schema.fields_by_alt_id.transform_values do |fld|
49
+ fld.name
50
+ end.merge({
51
+ "policy_group_ids" => "User Group(s)",
52
+ "email" => "Email",
53
+ "name" => "Name",
54
+ "supervisor_id" => "Manager ID",
55
+ "filter_tags" => "Locations",
56
+ "default_tag" => "Default Location",
57
+ "id" => "ecoPortal ID"
58
+ })
59
+ header = header.map {|name| name_maps[name] ? name_maps[name] : name}
60
+ end
61
+ header
62
+ end
63
+
64
+
45
65
  end
data/lib/eco/cli.rb CHANGED
@@ -22,16 +22,17 @@ module Eco
22
22
 
23
23
  def run(session:)
24
24
  io = Eco::API::UseCases::BaseIO.new(session: session, options: options)
25
- #session.workflow.run(io: io)
26
- session.workflow(io: io) do |wf, io|
27
- io = wf.run(:options, io: io)
28
- io = wf.run(:load, io: io)
29
- io = wf.run(:usecases, io: io)
30
- io = wf.run(:launch_jobs, io: io)
31
- io = wf.run(:post_launch, io: io)
32
- io = wf.run(:end, io: io)
33
- io = wf.run(:close, io: io)
34
- end
25
+ session.workflow(io: io).run(io: io)
26
+ #session.workflow(io: io) do |wf, io|
27
+ # io = wf.run(:options, io: io)
28
+ # io = wf.run(:load, io: io)
29
+ # io = wf.run(:usecases, io: io)
30
+ # io = wf.run(:launch_jobs, io: io)
31
+ # io = wf.run(:post_launch, io: io)
32
+ # io = wf.run(:report, io: io)
33
+ # io = wf.run(:end, io: io)
34
+ # io = wf.run(:close, io: io)
35
+ #end
35
36
  end
36
37
 
37
38
  end
@@ -6,7 +6,7 @@ ASSETS.cli.config do |cnf|
6
6
  file = SCR.get_file("-people-to-csv", required: true, should_exist: false)
7
7
  options.deep_merge!(export: {file: {name: file, format: :csv}})
8
8
  options.deep_merge!(export: {options: {nice_header: true}}) if SCR.get_arg("-nice-header")
9
-
9
+ options.deep_merge!(export: {options: {internal_names: true}}) if SCR.get_arg("-internal-names")
10
10
  case_name = SCR.get_arg("-detailed")? "to-csv-detailed" : "to-csv"
11
11
  session.usecases.case(case_name)
12
12
  end
@@ -73,7 +73,7 @@ ASSETS.cli.config do |cnf|
73
73
  end
74
74
 
75
75
  options.deep_merge!(ignore: {missing: {policy_groups: true}}) if SCR.get_arg("-ignore-missing-policy-groups")
76
-
76
+
77
77
  end
78
78
 
79
79
  desc = "Restores the people manager by using a backup.json file"
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = "2.0.9"
2
+ VERSION = "2.0.14"
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.9
4
+ version: 2.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
@@ -340,6 +340,7 @@ files:
340
340
  - lib/eco/api/organization/preferences.rb
341
341
  - lib/eco/api/organization/preferences_reference.json
342
342
  - lib/eco/api/organization/presets_factory.rb
343
+ - lib/eco/api/organization/presets_integrity.json
343
344
  - lib/eco/api/organization/presets_reference.json
344
345
  - lib/eco/api/organization/presets_values.json
345
346
  - lib/eco/api/organization/tag_tree.rb