eco-helpers 0.6.17 → 0.7.1
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 +4 -4
- data/.gitignore +19 -0
- data/.yardopts +2 -2
- data/Gemfile +6 -0
- data/Rakefile +27 -0
- data/eco-helpers.gemspec +9 -6
- data/lib/eco/api.rb +2 -1
- data/lib/eco/api/common/people.rb +1 -1
- data/lib/eco/api/common/people/base_parser.rb +31 -1
- data/lib/eco/api/common/people/default_parsers.rb +5 -1
- data/lib/eco/api/common/people/default_parsers/csv_parser.rb +37 -0
- data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +0 -1
- data/lib/eco/api/common/people/entries.rb +14 -18
- data/lib/eco/api/common/people/entry_factory.rb +97 -9
- data/lib/eco/api/common/people/person_entry.rb +147 -206
- data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +212 -0
- data/lib/eco/api/common/people/person_factory.rb +10 -12
- data/lib/eco/api/common/people/person_parser.rb +97 -37
- data/lib/eco/api/common/session/base_session.rb +1 -2
- data/lib/eco/api/common/session/file_manager.rb +1 -1
- data/lib/eco/api/organization.rb +2 -1
- data/lib/eco/api/organization/people.rb +54 -22
- data/lib/eco/api/organization/person_schemas.rb +54 -0
- data/lib/eco/api/organization/policy_groups.rb +5 -9
- data/lib/eco/api/organization/{presets.rb → presets_factory.rb} +1 -1
- data/lib/eco/api/policies.rb +10 -0
- data/lib/eco/api/policies/base_policy.rb +14 -0
- data/lib/eco/api/policies/policy.rb +20 -0
- data/lib/eco/api/policies/used_policies.rb +37 -0
- data/lib/eco/api/session.rb +36 -34
- data/lib/eco/api/session/batch.rb +94 -44
- data/lib/eco/api/session/batch_job.rb +108 -48
- data/lib/eco/api/session/batch_jobs.rb +4 -5
- data/lib/eco/api/session/batch_status.rb +70 -11
- data/lib/eco/api/session/config.rb +22 -5
- data/lib/eco/api/session/config/files.rb +10 -1
- data/lib/eco/api/session/config/people.rb +18 -5
- data/lib/eco/api/session/config/policies.rb +29 -0
- data/lib/eco/api/session/config/use_cases.rb +3 -7
- data/lib/eco/api/session/job_groups.rb +9 -10
- data/lib/eco/api/usecases.rb +2 -1
- data/lib/eco/api/usecases/base_case.rb +7 -2
- data/lib/eco/api/usecases/default_cases/change_email_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/create_case.rb +2 -1
- data/lib/eco/api/usecases/default_cases/create_details_case.rb +3 -1
- data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/hris_case.rb +20 -13
- data/lib/eco/api/usecases/default_cases/new_email_case.rb +3 -1
- data/lib/eco/api/usecases/default_cases/new_id_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/recover_db_case.rb +9 -5
- data/lib/eco/api/usecases/default_cases/remove_account_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/to_csv_case.rb +2 -2
- data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +2 -2
- data/lib/eco/api/usecases/default_cases/update_case.rb +16 -2
- data/lib/eco/api/usecases/default_cases/update_details_case.rb +3 -1
- data/lib/eco/api/usecases/default_cases/upsert_case.rb +25 -3
- data/lib/eco/api/usecases/use_case.rb +23 -140
- data/lib/eco/api/usecases/use_case_chain.rb +95 -0
- data/lib/eco/api/usecases/use_case_io.rb +117 -0
- data/lib/eco/api/usecases/use_group.rb +25 -5
- data/lib/eco/common/base_cli_backup.rb +1 -0
- data/lib/eco/language/models.rb +1 -1
- data/lib/eco/language/models/collection.rb +42 -31
- data/lib/eco/language/models/parser_serializer.rb +68 -0
- data/lib/eco/version.rb +1 -1
- metadata +93 -38
- data/lib/eco/api/common/people/types.rb +0 -47
- data/lib/eco/api/usecases/case_data.rb +0 -13
- data/lib/eco/language/models/attribute_parser.rb +0 -38
- data/lib/eco/lexic/dictionary.rb +0 -33
- data/lib/eco/lexic/dictionary/dictionary.txt +0 -355484
- data/lib/eco/lexic/dictionary/tags.json +0 -38
@@ -16,8 +16,7 @@ module Eco
|
|
16
16
|
|
17
17
|
def initialize(e)
|
18
18
|
raise "Expected object Eco::API::Common::Session::Environment. Given: #{e.class}" unless e.is_a?(Environment)
|
19
|
-
|
20
|
-
self.environment = e #if e.is_a?(Environment)
|
19
|
+
self.environment = e
|
21
20
|
end
|
22
21
|
|
23
22
|
def session
|
data/lib/eco/api/organization.rb
CHANGED
@@ -6,7 +6,8 @@ module Eco
|
|
6
6
|
end
|
7
7
|
|
8
8
|
require_relative 'organization/tag_tree'
|
9
|
-
require_relative 'organization/
|
9
|
+
require_relative 'organization/presets_factory'
|
10
10
|
require_relative 'organization/preferences'
|
11
11
|
require_relative 'organization/people'
|
12
12
|
require_relative 'organization/policy_groups'
|
13
|
+
require_relative 'organization/person_schemas'
|
@@ -2,7 +2,6 @@ module Eco
|
|
2
2
|
module API
|
3
3
|
module Organization
|
4
4
|
class People < Eco::Language::Models::Collection
|
5
|
-
|
6
5
|
# build the shortcuts of Collection
|
7
6
|
attr_collection :id, :external_id, :email, :name, :supervisor_id
|
8
7
|
attr_presence :account, :details
|
@@ -16,7 +15,7 @@ module Eco
|
|
16
15
|
end
|
17
16
|
|
18
17
|
def [](id_or_ext)
|
19
|
-
|
18
|
+
id(id_or_ext) || external_id(id_or_ext)
|
20
19
|
end
|
21
20
|
|
22
21
|
def id(*args)
|
@@ -28,32 +27,65 @@ module Eco
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def users
|
31
|
-
|
30
|
+
account_present(true)
|
32
31
|
end
|
33
32
|
|
34
33
|
def contacts
|
35
|
-
|
34
|
+
details_present(true)
|
36
35
|
end
|
37
36
|
|
38
37
|
def non_users
|
39
|
-
|
38
|
+
account_present(false)
|
40
39
|
end
|
41
40
|
|
42
|
-
|
41
|
+
# It searches a person using the paramters given.
|
42
|
+
# @param id [String] the `internal id` of the person
|
43
|
+
# @param external_id [String] the `exernal_id` of the person
|
44
|
+
# @param email [String] the `email` of the person
|
45
|
+
# @param strict [Boolean] if should perform a `soft` or a `strict` search. `strict` will avoid repeated email addresses.
|
46
|
+
# @return [Person, nil] the person we were searching, or `nil` if not found.
|
47
|
+
def person(id: nil, external_id: nil, email: nil, strict: false)
|
43
48
|
init_caches
|
44
49
|
pers = @by_id[id]&.first if id
|
45
|
-
pers = @by_external_id[external_id&.strip]&.first
|
46
|
-
|
47
|
-
|
48
|
-
|
50
|
+
pers = @by_external_id[external_id&.strip]&.first if !pers && !external_id.to_s.strip.empty?
|
51
|
+
|
52
|
+
# strict prevents taking existing user for searched person with same email
|
53
|
+
# specially useful if the organisation ensures all have external id (no need for email search)
|
54
|
+
if !pers && (!strict || external_id.to_s.strip.empty?)
|
55
|
+
# person still not found and either not strict or no external_id provided
|
56
|
+
pers = @by_users_email[email&.downcase.strip]&.first if !email.to_s.strip.empty?
|
57
|
+
|
58
|
+
if !pers && !strict && !email.to_s.strip.empty?
|
59
|
+
candidates = @by_non_users_email[email&.downcase.strip] || []
|
60
|
+
raise "Too many non-user candidates (#{candiates.length}) with email '#{email}'" if candidates.length > 1
|
61
|
+
pers = candidates.first
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
pers = @by_external_id[email&.downcase.strip]&.first if !pers && !email.to_s.strip.empty?
|
66
|
+
|
49
67
|
pers
|
50
68
|
end
|
51
69
|
|
52
|
-
def find(object)
|
53
|
-
id
|
70
|
+
def find(object, strict: false)
|
71
|
+
id = object.respond_to?("id")? object.send("id") : nil
|
54
72
|
external_id = object.respond_to?("external_id")? object.send("external_id") : nil
|
55
|
-
email
|
56
|
-
person(id: id, external_id: external_id, email: email)
|
73
|
+
email = object.respond_to?("email")? object.send("email") : nil
|
74
|
+
person(id: id, external_id: external_id, email: email, strict: strict)
|
75
|
+
end
|
76
|
+
|
77
|
+
def uniq(include_unsearchable: false)
|
78
|
+
init_caches
|
79
|
+
unsearchable = []
|
80
|
+
newFrom to_a.each_with_object([]) do |person, people|
|
81
|
+
if found = find(person)
|
82
|
+
people << found
|
83
|
+
else
|
84
|
+
unsearchable << person
|
85
|
+
end
|
86
|
+
end.tap do |people|
|
87
|
+
people << unsearchable if include_unsearchable
|
88
|
+
end
|
57
89
|
end
|
58
90
|
|
59
91
|
def exclude(object)
|
@@ -64,15 +96,15 @@ module Eco
|
|
64
96
|
discarded = list.map do |person|
|
65
97
|
find(person)
|
66
98
|
end.compact
|
67
|
-
newFrom
|
99
|
+
newFrom to_a - discarded
|
68
100
|
end
|
69
101
|
|
70
102
|
def email_id_maps
|
71
|
-
|
103
|
+
users.group_by(:email).transform_values { |person| person.id }
|
72
104
|
end
|
73
105
|
|
74
106
|
def group_by_supervisor
|
75
|
-
|
107
|
+
to_h(:supervisor_id)
|
76
108
|
end
|
77
109
|
|
78
110
|
# only those that are present
|
@@ -89,7 +121,7 @@ module Eco
|
|
89
121
|
sup_ids - (sup_ids & self.ids)
|
90
122
|
end
|
91
123
|
|
92
|
-
def to_h(attr)
|
124
|
+
def to_h(attr = "id")
|
93
125
|
super(attr || "id")
|
94
126
|
end
|
95
127
|
|
@@ -103,10 +135,10 @@ module Eco
|
|
103
135
|
|
104
136
|
def init_caches
|
105
137
|
return if @caches_init
|
106
|
-
@by_id
|
107
|
-
@by_external_id
|
108
|
-
@by_users_email
|
109
|
-
@by_non_users_email =
|
138
|
+
@by_id = to_h
|
139
|
+
@by_external_id = to_h('external_id')
|
140
|
+
@by_users_email = users.to_h('email')
|
141
|
+
@by_non_users_email = non_users.to_h('email')
|
110
142
|
@caches_init = true
|
111
143
|
end
|
112
144
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
module Organization
|
4
|
+
class PersonSchemas < Eco::Language::Models::Collection
|
5
|
+
# build the shortcuts of Collection
|
6
|
+
attr_collection :id, :name
|
7
|
+
|
8
|
+
def initialize(schemas = [], klass: Ecoportal::API::Internal::PersonSchema)
|
9
|
+
@klass = Ecoportal::API::Internal::PersonSchema
|
10
|
+
@caches_init = false
|
11
|
+
super(schemas, klass: @klass)
|
12
|
+
init_caches
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_id(name)
|
16
|
+
case name
|
17
|
+
when Enumerable
|
18
|
+
name.map do |n|
|
19
|
+
schema(n)&.id
|
20
|
+
end.compact
|
21
|
+
else
|
22
|
+
schema(name)&.id
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_name(id)
|
27
|
+
schema(id)&.name
|
28
|
+
end
|
29
|
+
|
30
|
+
def schema(id_name)
|
31
|
+
@by_id.fetch(schema_id(id_name), nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def schema_name(id_name)
|
37
|
+
(@by_id[id_name] || @by_name[id_name&.downcase])&.name&.downcase
|
38
|
+
end
|
39
|
+
|
40
|
+
def schema_id(id_name)
|
41
|
+
(@by_name[id_name&.downcase] || @by_id[id_name])&.id
|
42
|
+
end
|
43
|
+
|
44
|
+
def init_caches
|
45
|
+
return if @caches_init
|
46
|
+
@by_id = self.map { |pg| [pg.id, pg] }.to_h
|
47
|
+
@by_name = self.map { |pg| [pg.name&.downcase, pg] }.to_h
|
48
|
+
@caches_init = true
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -5,10 +5,8 @@ module Eco
|
|
5
5
|
# build the shortcuts of Collection
|
6
6
|
attr_collection :id, :name
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(policy_groups = [], klass: INTERNAL::PolicyGroup)
|
11
|
-
@klass = INTERNAL::PolicyGroup
|
8
|
+
def initialize(policy_groups = [], klass: Ecoportal::API::Internal::PolicyGroup)
|
9
|
+
@klass = Ecoportal::API::Internal::PolicyGroup
|
12
10
|
@caches_init = false
|
13
11
|
super(policy_groups, klass: @klass)
|
14
12
|
init_caches
|
@@ -16,7 +14,7 @@ module Eco
|
|
16
14
|
|
17
15
|
def to_id(name)
|
18
16
|
case name
|
19
|
-
when
|
17
|
+
when Enumerable
|
20
18
|
name.map do |n|
|
21
19
|
policy_group(n)&.id
|
22
20
|
end.compact
|
@@ -54,13 +52,11 @@ module Eco
|
|
54
52
|
private
|
55
53
|
|
56
54
|
def policy_group_name(id_name)
|
57
|
-
@by_id
|
58
|
-
@by_name.fetch(id_name&.downcase, nil)&.name&.downcase
|
55
|
+
(@by_id[id_name] || @by_name[id_name&.downcase])&.name&.downcase
|
59
56
|
end
|
60
57
|
|
61
58
|
def policy_group_id(id_name)
|
62
|
-
@by_name
|
63
|
-
@by_id.fetch(id_name, nil)&.id
|
59
|
+
(@by_name[id_name&.downcase] || @by_id[id_name])&.id
|
64
60
|
end
|
65
61
|
|
66
62
|
def init_caches
|
@@ -5,7 +5,7 @@ module Eco
|
|
5
5
|
class PresetsFactory
|
6
6
|
ABILITIES = File.join(__dir__, 'presets_values.json')
|
7
7
|
DEFAULT_CUSTOM = 'presets_custom.json'
|
8
|
-
DEFAULT_MAP
|
8
|
+
DEFAULT_MAP = 'presets_map.json'
|
9
9
|
|
10
10
|
def initialize(presets_custom: DEFAULT_CUSTOM, presets_map: DEFAULT_MAP, enviro: nil, policy_groups: nil)
|
11
11
|
@abilities = JSON.load(File.open(ABILITIES))
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
module Policies
|
4
|
+
class BasePolicy < Eco::API::UseCases::BaseCase
|
5
|
+
|
6
|
+
def initialize(policies, **options)
|
7
|
+
raise "Expected UsedPolicies. Given: #{policies.class}" unless policies.is_a?(UsedPolicies)
|
8
|
+
super(policies, **options)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
module Policies
|
4
|
+
class Policy < Eco::API::UseCases::UseCase
|
5
|
+
TYPES = [:transform]
|
6
|
+
|
7
|
+
def initialize(name, type: :transform, root:, options: {}, &block)
|
8
|
+
raise "Undefine usecase type #{type}. Please, use any of #{TYPES}" unless self.class.valid_type?(type)
|
9
|
+
super(name, type: type, root: root, options: options, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def root=(value)
|
13
|
+
raise "Root should be a UsedPolicies object. Given: #{value}" if !value.is_a?(UsedPolicies)
|
14
|
+
@root = value
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
module Policies
|
4
|
+
class UsedPolicies < Eco::API::UseCases::UseGroup
|
5
|
+
|
6
|
+
attr_reader :policies
|
7
|
+
|
8
|
+
def add(policy)
|
9
|
+
raise "Expected Policy object. Given: #{policy}" if !policy || !policy.is_a?(Policy)
|
10
|
+
super(policy)
|
11
|
+
end
|
12
|
+
|
13
|
+
def define(name, type: :transform, &block)
|
14
|
+
Policy.new(name, type: type, root: self, &block).tap do |policy|
|
15
|
+
add(policy)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO: decide if policies deal with queue or single person
|
20
|
+
def launch(people:, session:, options: {})
|
21
|
+
|
22
|
+
args = {
|
23
|
+
people: people,
|
24
|
+
session: session,
|
25
|
+
options: options
|
26
|
+
}
|
27
|
+
|
28
|
+
items.map do |policy|
|
29
|
+
session.logger.debug("UsedPolicies: going to process '#{policy.name}' policy")
|
30
|
+
policy.launch(**args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/eco/api/session.rb
CHANGED
@@ -1,13 +1,10 @@
|
|
1
1
|
module Eco
|
2
2
|
module API
|
3
3
|
class Session < Common::Session::BaseSession
|
4
|
-
attr_reader :batch, :policy_groups
|
5
|
-
attr_accessor :schema, :schemas_hash
|
6
|
-
attr_reader :tagtree
|
4
|
+
attr_reader :batch, :policy_groups, :tagtree
|
7
5
|
attr_reader :job_groups
|
8
|
-
|
9
|
-
|
10
|
-
#alias_method :org, :organization
|
6
|
+
attr_reader :schemas
|
7
|
+
attr_accessor :schema
|
11
8
|
|
12
9
|
def initialize(init = {})
|
13
10
|
e = init
|
@@ -24,13 +21,9 @@ module Eco
|
|
24
21
|
|
25
22
|
@use_cases = Eco::API::UseCases::DefaultCases.new.merge(config.usecases.use_group)
|
26
23
|
|
27
|
-
@schemas
|
28
|
-
@schemas_hash = @schemas.map do |sch|
|
29
|
-
[[sch.id, sch], [sch.name.downcase, sch]]
|
30
|
-
end.flatten(1).to_h
|
31
|
-
|
24
|
+
@schemas = config.schemas
|
32
25
|
self.schema = config.people.default_schema || @schemas.first
|
33
|
-
@policy_groups =
|
26
|
+
@policy_groups = config.policy_groups
|
34
27
|
|
35
28
|
@tagtree = nil
|
36
29
|
if tree_file = config.dig('org', 'tagtree')
|
@@ -50,10 +43,9 @@ module Eco
|
|
50
43
|
end
|
51
44
|
|
52
45
|
def self.configure
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
conf
|
46
|
+
Session::Config.new.tap do |conf|
|
47
|
+
yield(conf) if block_given?
|
48
|
+
end
|
57
49
|
end
|
58
50
|
|
59
51
|
# TASKS & JOBS
|
@@ -99,9 +91,9 @@ module Eco
|
|
99
91
|
def schema=(value)
|
100
92
|
case value
|
101
93
|
when String
|
102
|
-
|
103
|
-
|
104
|
-
|
94
|
+
unless @schema = @schemas.schema(value)
|
95
|
+
fatal "The schema with id or name '#{value}' does not exist"
|
96
|
+
end
|
105
97
|
when Ecoportal::API::V1::PersonSchema
|
106
98
|
@schema = value
|
107
99
|
else
|
@@ -109,16 +101,24 @@ module Eco
|
|
109
101
|
return
|
110
102
|
end
|
111
103
|
|
112
|
-
@person_factory
|
104
|
+
@person_factory = Eco::API::Common::People::PersonFactory.new(schema: @schema)
|
105
|
+
|
106
|
+
# TODO: check PersonEntry#to_internal and #to_external in init_attr_trackers
|
107
|
+
# => when attr_map is avoided, it doesn't work as it should
|
108
|
+
if map_file = config.people.fields_mapper
|
109
|
+
mappings = map_file ? file_manager.load_json(map_file) : []
|
110
|
+
else
|
111
|
+
mappings = []
|
112
|
+
end
|
113
|
+
attr_map = Eco::Data::Mapper.new(mappings)
|
113
114
|
|
114
|
-
|
115
|
-
|
116
|
-
@entry_factory = Eco::API::Common::People::EntryFactory.new({
|
117
|
-
schema: @schema,
|
115
|
+
@entry_factory = Eco::API::Common::People::EntryFactory.new({
|
116
|
+
schema: @schema,
|
118
117
|
person_parser: config.people.parser,
|
119
|
-
|
120
|
-
logger:
|
118
|
+
attr_map: attr_map,
|
119
|
+
logger: logger
|
121
120
|
})
|
121
|
+
self
|
122
122
|
end
|
123
123
|
|
124
124
|
def new_preset(input)
|
@@ -140,14 +140,16 @@ module Eco
|
|
140
140
|
@entry_factory.new(data, dependencies: dependencies)
|
141
141
|
end
|
142
142
|
|
143
|
+
def entries(*args)
|
144
|
+
@entry_factory.entries(*args)
|
145
|
+
end
|
146
|
+
|
147
|
+
def export(*args)
|
148
|
+
@entry_factory.export(*args)
|
149
|
+
end
|
150
|
+
|
143
151
|
def csv_entries(file)
|
144
|
-
|
145
|
-
if Eco::API::Common::Session::FileManager.file_exists?(file)
|
146
|
-
CSV.foreach(file, headers: true, encoding: Eco::API::Common::Session::FileManager.encoding(file)).with_index do |row, i|
|
147
|
-
rows.push(row)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
@entry_factory.entries(rows)
|
152
|
+
return entries(file: file, format: :csv)
|
151
153
|
end
|
152
154
|
|
153
155
|
def discarded_entries
|
@@ -160,7 +162,7 @@ module Eco
|
|
160
162
|
args = { session: self }.merge(params)
|
161
163
|
fatal("Undefined usecase '#{name}' of type '#{type.to_s}'") if !@use_cases.defined?(name, type: type)
|
162
164
|
logger.debug("Session: going to process '#{name}' defined case")
|
163
|
-
@use_cases.case(name, type: type).
|
165
|
+
@use_cases.case(name, type: type).launch(**args)
|
164
166
|
end
|
165
167
|
|
166
168
|
end
|