eco-helpers 1.5.1 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -2
- data/LICENSE +21 -0
- data/eco-helpers.gemspec +1 -1
- data/lib/eco/api.rb +2 -0
- data/lib/eco/api/common.rb +4 -0
- data/lib/eco/api/common/base_loader.rb +54 -0
- data/lib/eco/api/common/class_auto_loader.rb +109 -0
- data/lib/eco/api/common/class_helpers.rb +33 -0
- data/lib/eco/api/common/class_hierarchy.rb +1 -1
- data/lib/eco/api/common/class_meta_basics.rb +16 -0
- data/lib/eco/api/common/loaders.rb +13 -0
- data/lib/eco/api/common/loaders/error_handler.rb +41 -0
- data/lib/eco/api/common/loaders/parser.rb +127 -0
- data/lib/eco/api/common/loaders/policy.rb +25 -0
- data/lib/eco/api/common/loaders/use_case.rb +40 -0
- data/lib/eco/api/common/people/default_parsers.rb +3 -12
- data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +13 -23
- data/lib/eco/api/common/people/default_parsers/csv_parser.rb +20 -35
- data/lib/eco/api/common/people/default_parsers/date_parser.rb +15 -26
- data/lib/eco/api/common/people/default_parsers/freemium_parser.rb +15 -25
- data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +26 -0
- data/lib/eco/api/common/people/default_parsers/multi_parser.rb +15 -27
- data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +14 -19
- data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +24 -35
- data/lib/eco/api/common/people/default_parsers/send_invites_parser.rb +15 -25
- data/lib/eco/api/common/people/entries.rb +54 -24
- data/lib/eco/api/common/people/entry_factory.rb +10 -8
- data/lib/eco/api/common/people/person_attribute_parser.rb +29 -12
- data/lib/eco/api/common/people/person_entry.rb +308 -216
- data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +3 -2
- data/lib/eco/api/common/people/person_parser.rb +51 -18
- data/lib/eco/api/common/session/logger.rb +4 -0
- data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +2 -0
- data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +1 -1
- data/lib/eco/api/common/version_patches/exception.rb +22 -0
- data/lib/eco/api/custom.rb +13 -0
- data/lib/eco/api/custom/error_handler.rb +20 -0
- data/lib/eco/api/custom/namespace.rb +7 -0
- data/lib/eco/api/custom/parser.rb +50 -0
- data/lib/eco/api/custom/policy.rb +28 -0
- data/lib/eco/api/custom/use_case.rb +16 -0
- data/lib/eco/api/error.rb +1 -0
- data/lib/eco/api/error/handlers.rb +10 -3
- data/lib/eco/api/microcases.rb +17 -13
- data/lib/eco/api/microcases/account_excluded.rb +24 -0
- data/lib/eco/api/microcases/append_usergroups.rb +19 -0
- data/lib/eco/api/microcases/core_excluded.rb +4 -4
- data/lib/eco/api/microcases/{set_default_group.rb → fix_default_group.rb} +10 -9
- data/lib/eco/api/microcases/fix_filter_tags.rb +26 -6
- data/lib/eco/api/microcases/people_cache.rb +17 -0
- data/lib/eco/api/microcases/people_load.rb +59 -0
- data/lib/eco/api/microcases/people_refresh.rb +31 -0
- data/lib/eco/api/microcases/people_search.rb +65 -0
- data/lib/eco/api/microcases/refresh_abilities.rb +19 -0
- data/lib/eco/api/microcases/refresh_default_tag.rb +27 -0
- data/lib/eco/api/microcases/s3upload_targets.rb +39 -0
- data/lib/eco/api/microcases/set_account.rb +7 -19
- data/lib/eco/api/microcases/set_core.rb +5 -5
- data/lib/eco/api/microcases/set_core_with_supervisor.rb +23 -0
- data/lib/eco/api/microcases/set_supervisor.rb +17 -13
- data/lib/eco/api/microcases/strict_search.rb +12 -7
- data/lib/eco/api/microcases/with_each.rb +27 -0
- data/lib/eco/api/microcases/with_each_leaver.rb +24 -0
- data/lib/eco/api/microcases/with_each_present.rb +30 -0
- data/lib/eco/api/microcases/with_each_starter.rb +30 -0
- data/lib/eco/api/microcases/with_each_subordinate.rb +34 -0
- data/lib/eco/api/microcases/with_supervisor.rb +36 -0
- data/lib/eco/api/organization/people.rb +72 -35
- data/lib/eco/api/organization/presets_factory.rb +13 -4
- data/lib/eco/api/policies.rb +11 -7
- data/lib/eco/api/session.rb +54 -24
- data/lib/eco/api/session/batch.rb +1 -1
- data/lib/eco/api/session/batch/base_policy.rb +7 -6
- data/lib/eco/api/session/batch/errors.rb +28 -4
- data/lib/eco/api/session/batch/feedback.rb +7 -1
- data/lib/eco/api/session/batch/job.rb +40 -23
- data/lib/eco/api/session/batch/jobs.rb +9 -4
- data/lib/eco/api/session/batch/jobs_groups.rb +1 -1
- data/lib/eco/api/session/batch/request_stats.rb +91 -58
- data/lib/eco/api/session/batch/status.rb +35 -31
- data/lib/eco/api/session/config.rb +104 -42
- data/lib/eco/api/session/config/api.rb +17 -6
- data/lib/eco/api/session/config/logger.rb +2 -2
- data/lib/eco/api/session/config/post_launch.rb +1 -1
- data/lib/eco/api/session/config/workflow.rb +8 -7
- data/lib/eco/api/usecases.rb +47 -33
- data/lib/eco/api/usecases/backup/append_usergroups_case.rb +36 -0
- data/lib/eco/api/usecases/backup/create_case.rb +104 -0
- data/lib/eco/api/usecases/backup/create_details_case.rb +31 -0
- data/lib/eco/api/usecases/backup/create_details_with_supervisor_case.rb +48 -0
- data/lib/eco/api/usecases/backup/hris_case.rb +124 -0
- data/lib/eco/api/usecases/backup/set_default_tag_case.rb +49 -0
- data/lib/eco/api/usecases/backup/set_supervisor_case.rb +41 -0
- data/lib/eco/api/usecases/backup/transfer_account_case.rb +90 -0
- data/lib/eco/api/usecases/backup/update_case.rb +112 -0
- data/lib/eco/api/usecases/backup/update_details_case.rb +64 -0
- data/lib/eco/api/usecases/backup/upsert_case.rb +114 -0
- data/lib/eco/api/usecases/base_case.rb +2 -0
- data/lib/eco/api/usecases/base_io.rb +3 -3
- data/lib/eco/api/usecases/default_cases.rb +23 -53
- data/lib/eco/api/usecases/default_cases/append_usergroups_case.rb +10 -31
- data/lib/eco/api/usecases/default_cases/change_email_case.rb +23 -47
- data/lib/eco/api/usecases/default_cases/codes_to_tags_case.rb +56 -43
- data/lib/eco/api/usecases/default_cases/create_case.rb +15 -101
- data/lib/eco/api/usecases/default_cases/create_details_case.rb +11 -26
- data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +12 -43
- data/lib/eco/api/usecases/default_cases/delete_sync_case.rb +11 -0
- data/lib/eco/api/usecases/default_cases/delete_trans_case.rb +14 -0
- data/lib/eco/api/usecases/default_cases/email_as_id_case.rb +10 -21
- data/lib/eco/api/usecases/default_cases/hris_case.rb +23 -120
- data/lib/eco/api/usecases/default_cases/new_email_case.rb +10 -23
- data/lib/eco/api/usecases/default_cases/new_id_case.rb +11 -25
- data/lib/eco/api/usecases/default_cases/new_id_case0.rb +14 -0
- data/lib/eco/api/usecases/default_cases/org_data_convert_case.rb +83 -0
- data/lib/eco/api/usecases/default_cases/refresh_abilities_case.rb +30 -0
- data/lib/eco/api/usecases/default_cases/refresh_case.rb +7 -20
- data/lib/eco/api/usecases/default_cases/reinvite_sync_case.rb +11 -0
- data/lib/eco/api/usecases/default_cases/reinvite_trans_case.rb +17 -0
- data/lib/eco/api/usecases/default_cases/remove_account_sync_case.rb +11 -0
- data/lib/eco/api/usecases/default_cases/remove_account_trans_case.rb +17 -0
- data/lib/eco/api/usecases/default_cases/reset_landing_page_case.rb +9 -19
- data/lib/eco/api/usecases/default_cases/restore_db_case.rb +92 -0
- data/lib/eco/api/usecases/default_cases/set_default_tag_case.rb +32 -40
- data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +15 -33
- data/lib/eco/api/usecases/default_cases/switch_supervisor_case.rb +66 -57
- data/lib/eco/api/usecases/default_cases/to_csv_case.rb +36 -44
- data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +40 -55
- data/lib/eco/api/usecases/default_cases/transfer_account_case.rb +264 -84
- data/lib/eco/api/usecases/default_cases/update_case.rb +15 -109
- data/lib/eco/api/usecases/default_cases/update_details_case.rb +14 -61
- data/lib/eco/api/usecases/default_cases/upsert_case.rb +16 -111
- data/lib/eco/api/usecases/use_case_io.rb +9 -9
- data/lib/eco/cli/config.rb +10 -2
- data/lib/eco/cli/config/default.rb +2 -1
- data/lib/eco/cli/config/default/input_filters.rb +58 -0
- data/lib/eco/cli/config/default/options.rb +60 -25
- data/lib/eco/cli/config/default/people.rb +4 -4
- data/lib/eco/cli/config/default/people_filters.rb +108 -0
- data/lib/eco/cli/config/default/usecases.rb +69 -32
- data/lib/eco/cli/config/default/workflow.rb +37 -27
- data/lib/eco/cli/config/filters.rb +50 -0
- data/lib/eco/cli/config/filters/input_filters.rb +29 -0
- data/lib/eco/cli/config/filters/people_filters.rb +29 -0
- data/lib/eco/cli/config/help.rb +49 -0
- data/lib/eco/cli/config/options_set.rb +17 -1
- data/lib/eco/cli/config/use_cases.rb +79 -53
- data/lib/eco/cli/scripting.rb +10 -2
- data/lib/eco/cli/scripting/args_helpers.rb +25 -15
- data/lib/eco/cli/scripting/argument.rb +1 -0
- data/lib/eco/cli/scripting/arguments.rb +1 -1
- data/lib/eco/csv/table.rb +1 -1
- data/lib/eco/data/crypto/encryption.rb +3 -0
- data/lib/eco/language/match.rb +19 -9
- data/lib/eco/language/match_modifier.rb +13 -5
- data/lib/eco/language/models/collection.rb +77 -56
- data/lib/eco/language/models/parser_serializer.rb +39 -15
- data/lib/eco/version.rb +1 -1
- metadata +63 -18
- data/lib/eco/api/microcases/set_default_tag.rb +0 -23
- data/lib/eco/api/session/task.rb +0 -175
- data/lib/eco/api/usecases/default_case.rb +0 -19
- data/lib/eco/api/usecases/default_cases/delete_case.rb +0 -32
- data/lib/eco/api/usecases/default_cases/recover_db_case.rb +0 -99
- data/lib/eco/api/usecases/default_cases/refresh_presets_case.rb +0 -26
- data/lib/eco/api/usecases/default_cases/reinvite_case.rb +0 -41
- data/lib/eco/api/usecases/default_cases/remove_account_case.rb +0 -38
- data/lib/eco/api/usecases/microed_cases/hris_case.rb +0 -53
- data/lib/eco/api/usecases/microed_cases/update_case.rb +0 -33
- data/lib/eco/api/usecases/microed_cases/update_details_case.rb +0 -30
- data/lib/eco/api/usecases/microed_cases/upsert_case.rb +0 -36
- data/lib/eco/cli/config/default/filters.rb +0 -70
- data/lib/eco/cli/config/people_filters.rb +0 -38
@@ -1,33 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Common
|
4
|
-
module People
|
5
|
-
class DefaultParsers
|
6
|
-
class MultiParser < People::BaseParser
|
1
|
+
class Eco::API::Common::People::DefaultParsers::MultiParser < Eco::API::Common::Loaders::Parser
|
2
|
+
attribute :multiple
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
next value if value.is_a?(Array)
|
12
|
-
value = value.split("|") if value&.include?("|")
|
13
|
-
into_a(value)
|
14
|
-
end.def_serializer do |value|
|
15
|
-
into_a(value).join("|")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
4
|
+
def parser(value, deps)
|
5
|
+
into_a(value)
|
6
|
+
end
|
19
7
|
|
20
|
-
|
8
|
+
def serializer(value, deps)
|
9
|
+
into_a(value).join("|")
|
10
|
+
end
|
21
11
|
|
22
|
-
|
23
|
-
value = [] if value == nil
|
24
|
-
value = [].push(value) unless value.is_a?(Array)
|
25
|
-
value
|
26
|
-
end
|
12
|
+
private
|
27
13
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
14
|
+
def into_a(value)
|
15
|
+
return [] if value.nil?
|
16
|
+
return value if value.is_a?(Array)
|
17
|
+
return value.split("|") if value.is_a?(String) && value.include?("|")
|
18
|
+
[].push(value)
|
32
19
|
end
|
20
|
+
|
33
21
|
end
|
@@ -1,23 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Common
|
4
|
-
module People
|
5
|
-
class DefaultParsers
|
6
|
-
class NumericParser < People::BaseParser
|
1
|
+
class Eco::API::Common::People::DefaultParsers::NumericParser < Eco::API::Common::Loaders::Parser
|
2
|
+
attribute :number
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
value = value.to_s.strip.empty? ? nil : (value.to_f rescue nil)
|
12
|
-
end.def_serializer do |value|
|
13
|
-
value.is_a?(Array) ? value.map { |v| v.to_s } : value.to_s
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
4
|
+
def parser(value, deps)
|
5
|
+
value.is_a?(Array) ? value.map { |v| parse_number(v) } : parse_number(value)
|
6
|
+
end
|
17
7
|
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
8
|
+
def serializer(value, deps)
|
9
|
+
value.is_a?(Array) ? value.map { |v| v.to_s } : value.to_s
|
22
10
|
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse_number(value)
|
15
|
+
value.to_s.strip.empty? ? nil : (value.to_f rescue nil)
|
16
|
+
end
|
17
|
+
|
23
18
|
end
|
@@ -1,42 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Common
|
4
|
-
module People
|
5
|
-
class DefaultParsers
|
6
|
-
class PolicyGroupsParser < People::BaseParser
|
1
|
+
class Eco::API::Common::People::DefaultParsers::PolicyGroupsParser < Eco::API::Common::Loaders::Parser
|
2
|
+
attribute "policy_group_ids"
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
policy_group_ids.empty?? default_id : policy_group_ids.join("|")
|
18
|
-
end.def_serializer do |person|
|
19
|
-
ids = person&.account&.policy_group_ids || []
|
20
|
-
ids.map do |id|
|
21
|
-
policy_groups.to_name(id)
|
22
|
-
end.compact.join("|")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
4
|
+
def parser(hash, deps)
|
5
|
+
policy_group_ids = []
|
6
|
+
if policy_ids = hash["policy_group_ids"]
|
7
|
+
policy_group_ids = policy_ids.split("|").map do |name|
|
8
|
+
policy_groups.to_id(name&.downcase.strip)
|
9
|
+
end.compact
|
10
|
+
end
|
11
|
+
policy_group_ids.empty?? default_id : policy_group_ids.join("|")
|
12
|
+
end
|
26
13
|
|
27
|
-
|
14
|
+
def serializer(person, deps)
|
15
|
+
ids = person&.account&.policy_group_ids || []
|
16
|
+
ids.map do |id|
|
17
|
+
policy_groups.to_name(id)
|
18
|
+
end.compact.join("|")
|
19
|
+
end
|
28
20
|
|
29
|
-
|
30
|
-
@policy_groups ||= ASSETS.config.policy_groups
|
31
|
-
end
|
21
|
+
private
|
32
22
|
|
33
|
-
|
34
|
-
|
35
|
-
|
23
|
+
def policy_groups
|
24
|
+
@policy_groups ||= ASSETS.config.policy_groups
|
25
|
+
end
|
36
26
|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
27
|
+
def default_id
|
28
|
+
@default_id ||= policy_groups.to_id(ASSETS.config.people.default_usergroup)
|
41
29
|
end
|
30
|
+
|
42
31
|
end
|
@@ -1,30 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Common
|
4
|
-
module People
|
5
|
-
class DefaultParsers
|
6
|
-
class SendInvitesParser < People::BaseParser
|
1
|
+
class Eco::API::Common::People::DefaultParsers::SendInvitesParser < Eco::API::Common::Loaders::Parser
|
2
|
+
attribute "send_invites"
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
truthy(value)
|
14
|
-
end.def_serializer do |person|
|
15
|
-
person.account && person.account.send_invites&.to_s
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
4
|
+
def parser(hash, deps)
|
5
|
+
value = hash["send_invites"]
|
6
|
+
value = value.first if value.is_a?(Array)
|
7
|
+
truthy(value)
|
8
|
+
end
|
19
9
|
|
20
|
-
|
10
|
+
def serializer(person, deps)
|
11
|
+
person.account && person.account.send_invites&.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
21
15
|
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
16
|
+
def truthy (value)
|
17
|
+
%w[true y yes x].include?(value.to_s&.downcase)
|
29
18
|
end
|
19
|
+
|
30
20
|
end
|
@@ -3,7 +3,7 @@ module Eco
|
|
3
3
|
module Common
|
4
4
|
module People
|
5
5
|
# Class meant to offer a _collection_ of entries, normally used to get parsed input data.
|
6
|
-
# @attr_reader entries [Array<Eco::API::Common::
|
6
|
+
# @attr_reader entries [Array<Eco::API::Common::PeopleEntry] a pure `Array` object.
|
7
7
|
class Entries < Eco::Language::Models::Collection
|
8
8
|
# build the shortcuts of Collection
|
9
9
|
attr_collection :id, :external_id, :email, :name, :supervisor_id
|
@@ -17,37 +17,41 @@ module Eco
|
|
17
17
|
@caches_init = false
|
18
18
|
end
|
19
19
|
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
# @!group Main identifier helpers
|
21
|
+
|
22
|
+
def id(*args)
|
23
|
+
attr('id', *args).first
|
24
|
+
end
|
25
|
+
|
26
|
+
def external_id(*args)
|
27
|
+
attr('external_id', *args).first
|
25
28
|
end
|
26
29
|
|
27
30
|
def [](id_or_ext)
|
28
31
|
id(id_or_ext) || external_id(id_or_ext)
|
29
32
|
end
|
33
|
+
# @!endgroup
|
30
34
|
|
31
|
-
|
32
|
-
|
35
|
+
# @!group Special filters
|
36
|
+
|
37
|
+
def filter_tags_any(tags)
|
38
|
+
attr("filter_tags", tags, default_modifier.any.insensitive)
|
33
39
|
end
|
34
40
|
|
35
|
-
def
|
36
|
-
attr(
|
41
|
+
def filter_tags_all(tags)
|
42
|
+
attr("filter_tags", tags, default_modifier.all.insensitive)
|
37
43
|
end
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
csv << header
|
46
|
-
self.each do |entry|
|
47
|
-
csv << entry.internal_entry.values
|
48
|
-
end
|
49
|
-
end
|
45
|
+
def policy_group_ids_any(ids)
|
46
|
+
attr("policy_group_ids", tags, default_modifier.any.insensitive)
|
47
|
+
end
|
48
|
+
|
49
|
+
def policy_group_ids_all(ids)
|
50
|
+
attr("policy_group_ids", tags, default_modifier.all.insensitive)
|
50
51
|
end
|
52
|
+
# @!endgroup
|
53
|
+
|
54
|
+
# @!group Searchers
|
51
55
|
|
52
56
|
# Search function to find an `entry` based on one of different options
|
53
57
|
def entry(id: nil, external_id: nil, email: nil, strict: false)
|
@@ -68,11 +72,21 @@ module Eco
|
|
68
72
|
# Search function to find an `entry` based on one of different options
|
69
73
|
# see Eco::API::Common::People::Entries#entry
|
70
74
|
def find(object, strict: false)
|
71
|
-
id =
|
72
|
-
external_id = object
|
73
|
-
email =
|
75
|
+
id = attr_value(object, "id")
|
76
|
+
external_id = attr_value(object, "external_id")
|
77
|
+
email = attr_value(object, "email")
|
74
78
|
entry(id: id, external_id: external_id, email: email, strict: strict)
|
75
79
|
end
|
80
|
+
# @!endgroup
|
81
|
+
|
82
|
+
# @!group Basic Collection Methods
|
83
|
+
|
84
|
+
# Override `each` to make it work with supervisor hiearchy
|
85
|
+
def each(&block)
|
86
|
+
return to_enum(:each) unless block
|
87
|
+
@array_supers = sort_by_supervisors(@items) unless @caches_init
|
88
|
+
@array_supers.each(&block)
|
89
|
+
end
|
76
90
|
|
77
91
|
def exclude(object)
|
78
92
|
exclude_people(into_a(object))
|
@@ -85,6 +99,21 @@ module Eco
|
|
85
99
|
newFrom to_a - discarded
|
86
100
|
end
|
87
101
|
|
102
|
+
# Helper to dump the entries into a CSV
|
103
|
+
# @param filename [String] the destination file
|
104
|
+
def export(filename)
|
105
|
+
CSV.open(filename, "w") do |csv|
|
106
|
+
entry = self.first
|
107
|
+
header = entry.internal_entry.keys
|
108
|
+
csv << header
|
109
|
+
self.each do |entry|
|
110
|
+
csv << entry.internal_entry.values
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# @!group Groupping methods
|
116
|
+
|
88
117
|
def email_id_maps
|
89
118
|
email_present.group_by(:email).transform_values { |person| person.id }
|
90
119
|
end
|
@@ -96,6 +125,7 @@ module Eco
|
|
96
125
|
def to_h(attr = "id")
|
97
126
|
super(attr || "id")
|
98
127
|
end
|
128
|
+
# @!endgroup
|
99
129
|
|
100
130
|
protected
|
101
131
|
|
@@ -12,7 +12,6 @@ module Eco
|
|
12
12
|
# @param schema [Ecoportal::API::V1::PersonSchema] schema of person details that the parser will be based upon.
|
13
13
|
# @param person_parser [nil, Eco::API::Common::People::PersonParser] set of attribute, type and format parsers/serializers.
|
14
14
|
# @param attr_map [nil, Eco::Data::Mapper] attribute names mapper to translate external names into internal ones and _vice versa_.
|
15
|
-
# @param logger [Common::Session::Logger, ::Logger] object to manage logs.
|
16
15
|
def initialize(e, schema:, person_parser: nil, attr_map: nil)
|
17
16
|
fatal "Constructor needs a PersonSchema. Given: #{schema}" if !schema.is_a?(Ecoportal::API::V1::PersonSchema)
|
18
17
|
fatal "Expecting PersonParser. Given: #{person_parser}" if person_parser && !person_parser.is_a?(Eco::API::Common::People::PersonParser)
|
@@ -20,13 +19,12 @@ module Eco
|
|
20
19
|
super(e)
|
21
20
|
|
22
21
|
@schema = Ecoportal::API::V1::PersonSchema.new(JSON.parse(schema.doc.to_json))
|
23
|
-
|
24
22
|
@source_person_parser = person_parser
|
25
23
|
|
26
|
-
# load default parsers
|
27
|
-
|
28
|
-
#
|
29
|
-
@person_parser = @
|
24
|
+
# load default parser + custom parsers
|
25
|
+
base_parser = Eco::API::Common::People::DefaultParsers.new(schema: @schema).merge(@source_person_parser)
|
26
|
+
# new parser with linked schema
|
27
|
+
@person_parser = @source_person_parser.new(schema: @schema).merge(base_parser)
|
30
28
|
@person_parser_patch_version = @source_person_parser.patch_version
|
31
29
|
|
32
30
|
@attr_map = attr_map
|
@@ -79,8 +77,12 @@ module Eco
|
|
79
77
|
arr_hash = []
|
80
78
|
if Eco::API::Common::Session::FileManager.file_exists?(file)
|
81
79
|
encoding ||= Eco::API::Common::Session::FileManager.encoding(file)
|
80
|
+
encoding = (encoding != "utf-8")? "#{encoding}|utf-8": encoding
|
82
81
|
file_content = File.read(file, encoding: encoding)
|
83
|
-
arr_hash = person_parser.parse(format, file_content)
|
82
|
+
arr_hash = person_parser.parse(format, file_content).map.each_with_index do |entry_hash, i|
|
83
|
+
j = (format == :csv)? i + 2 : i + 1
|
84
|
+
entry_hash.tap {|hash| hash["idx"] = j}
|
85
|
+
end
|
84
86
|
else
|
85
87
|
logger.warn("File does not exist: #{file}")
|
86
88
|
end
|
@@ -119,7 +121,7 @@ module Eco
|
|
119
121
|
deps = {"supervisor_id" => {people: data}}
|
120
122
|
|
121
123
|
data_entries = data.map do |person|
|
122
|
-
self.new(person, dependencies: deps).
|
124
|
+
self.new(person, dependencies: deps).external_entry
|
123
125
|
end
|
124
126
|
|
125
127
|
File.open(file, "w", enconding: encoding) do |fd|
|
@@ -12,21 +12,39 @@ module Eco
|
|
12
12
|
# parser will be active/used.
|
13
13
|
# - this is important to help avoiding to set values that are not present in the input entry.
|
14
14
|
# - if you have doubts about using it or not, do not use it.
|
15
|
-
# @param
|
15
|
+
# @param phase [Symbol] the phase when this parser should be active.
|
16
|
+
# Must be one of [`:internal`, `:final`]
|
17
|
+
# @param active_when [Proc] that expects a list of internal attributes or the internal entry itself.
|
16
18
|
# By default, an attribute paraser is active if in the entry to parse the internal attribute is present.
|
17
|
-
def def_parser(active_when: nil, &block)
|
19
|
+
def def_parser(phase = :internal, active_when: nil, &block)
|
18
20
|
@active_when = attribute_present(active_when)
|
19
|
-
super(&block)
|
21
|
+
super(phase, &block)
|
20
22
|
end
|
21
23
|
|
22
|
-
#
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
@active_when.call(source_data)
|
24
|
+
# @param phase [Symbol] the phase when this serializer should be active.
|
25
|
+
# Must be one of [`:person,` `:final`, `:internal`]
|
26
|
+
def def_serializer(phase = :person, &block)
|
27
|
+
super(phase, &block)
|
27
28
|
end
|
28
29
|
|
29
|
-
#
|
30
|
+
# Determines if for a given source data to parse, this parser should be active or not.
|
31
|
+
# @param phase [Symbol] the phase when this parser should be active.
|
32
|
+
# Must be one of [`:internal`, `:final`]
|
33
|
+
# @return [Boolean] `true` if there's parser defined and `source_data` activates it.
|
34
|
+
def parser_active?(source_data, phase = :any)
|
35
|
+
(phase == :any || parser_category?(phase)) && @active_when.call(source_data)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Determines a serializer should be active or not.
|
39
|
+
# @param phase [Symbol] the phase when this serializer should be active.
|
40
|
+
# Must be one of [`:person,` `:final`, `:internal`]
|
41
|
+
# @return [Boolean] `true` if there's serializer defined.
|
42
|
+
def serializer_active?(phase = :any)
|
43
|
+
(phase == :any) || serializer_category?(phase)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Helper to build the `active_when` condition.
|
30
48
|
def active_when_any?(*attrs)
|
31
49
|
Proc.new do |source_data|
|
32
50
|
keys = data_keys(source_data)
|
@@ -34,7 +52,7 @@ module Eco
|
|
34
52
|
end
|
35
53
|
end
|
36
54
|
|
37
|
-
# Helper to build the `active_when` condition
|
55
|
+
# Helper to build the `active_when` condition.
|
38
56
|
def active_when_all?(*attrs)
|
39
57
|
Proc.new do |source_data|
|
40
58
|
keys = data_keys(source_data)
|
@@ -44,7 +62,7 @@ module Eco
|
|
44
62
|
|
45
63
|
private
|
46
64
|
|
47
|
-
#
|
65
|
+
# By default, an attribute paraser is active if in the entry to parse
|
48
66
|
# the internal attribute is present
|
49
67
|
def attribute_present(active_when)
|
50
68
|
Proc.new do |source_data|
|
@@ -67,7 +85,6 @@ module Eco
|
|
67
85
|
end
|
68
86
|
end
|
69
87
|
|
70
|
-
|
71
88
|
end
|
72
89
|
end
|
73
90
|
end
|
@@ -9,7 +9,7 @@ module Eco
|
|
9
9
|
# - if `data` is a `Person` object, its behaviour is `serialise`.
|
10
10
|
# - if `data` is **not** a `Person` object, it does a `parse`.
|
11
11
|
# - currently **in rework**, so there may be subtle differences that make it temporarily unstable (yet it is reliable).
|
12
|
-
# @param data [Hash, Person] `Person` object to be serialized or hashed entry (`CSV::Row` is accepted).
|
12
|
+
# @param data [Hash, Ecoportal::API::V1::Person] `Person` object to be serialized or hashed entry (`CSV::Row` is accepted).
|
13
13
|
# @param person_parser [Common::People::PersonParser] parser/serializer of person attributes (it contains a set of attribute parsers).
|
14
14
|
# @param attr_map [Eco::Data::Mapper] mapper to translate attribute names from _external_ to _internal_ names and _vice versa_.
|
15
15
|
# @param dependencies [Hash] hash where _keys_ are internal attribute names. It is mostly used to deliver final dependencies to attribute parsers/serializers.
|
@@ -26,17 +26,43 @@ module Eco
|
|
26
26
|
@emap = PersonEntryAttributeMapper.new(@source, person_parser: @person_parser, attr_map: @attr_map, logger: @logger)
|
27
27
|
|
28
28
|
if parsing?
|
29
|
-
@external_entry = data
|
30
|
-
@
|
31
|
-
@internal_entry =
|
29
|
+
@external_entry = __external_entry(data)
|
30
|
+
@mapped_entry = __mapped_entry(@external_entry)
|
31
|
+
@internal_entry = __internal_entry(@mapped_entry)
|
32
|
+
@final_entry = __final_entry(@internal_entry)
|
32
33
|
else # SERIALIZING
|
33
34
|
@person = data
|
34
|
-
@
|
35
|
-
@
|
36
|
-
|
35
|
+
@final_entry = __final_entry(@person)
|
36
|
+
@internal_entry = __internal_entry(@final_entry)
|
37
|
+
@mapped_entry = __mapped_entry(@internal_entry)
|
38
|
+
@external_entry = __external_entry(@mapped_entry)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
42
|
+
# Generates a new entry
|
43
|
+
# @return [PersonEntry]
|
44
|
+
def new(data)
|
45
|
+
self.class.new(data, person_parser: @person_parser, attr_map: @attr_map, dependencies: @deps, logger: @logger)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @note completely serialized entry.
|
49
|
+
# @return [Hash] entry `Hash` with **external** attribute names, and values and types thereof.
|
50
|
+
def external_entry
|
51
|
+
@external_entry
|
52
|
+
end
|
53
|
+
|
54
|
+
# @note just one step away from being completely parsed (only types parsing pending).
|
55
|
+
# @return [Hash] entry `Hash` with **internal** attribute names and values, but **external** types.
|
56
|
+
def internal_entry
|
57
|
+
@internal_entry
|
58
|
+
end
|
59
|
+
|
60
|
+
# @note values ready to be set to a person.
|
61
|
+
# @return [Hash] entry `Hash` with **internal** attribute names, values and types.
|
62
|
+
def final_entry
|
63
|
+
@final_entry
|
64
|
+
end
|
65
|
+
|
40
66
|
# To know if currently the object is in parse or serialize mode.
|
41
67
|
# @return [Boolean] returns `true` if we are **parsing**, `false` otherwise.
|
42
68
|
def parsing?
|
@@ -49,73 +75,83 @@ module Eco
|
|
49
75
|
!parsing?
|
50
76
|
end
|
51
77
|
|
78
|
+
# @note `Eco::API::Common::People::EntryFactory#entries` adds this `idx`
|
79
|
+
# @return [Integer] the entry number in the input file
|
80
|
+
def idx
|
81
|
+
final_entry["idx"]
|
82
|
+
end
|
83
|
+
|
52
84
|
# @return [String, nil] the _internal id_ of this person if defined.
|
53
85
|
def id
|
54
|
-
|
86
|
+
final_entry["id"]
|
55
87
|
end
|
56
88
|
|
57
89
|
def id?
|
58
|
-
|
90
|
+
final_entry.key?("id")
|
59
91
|
end
|
60
92
|
|
61
93
|
# @return [String, nil] the _external id_ of this person if defined.
|
62
94
|
def external_id
|
63
|
-
|
95
|
+
final_entry["external_id"]
|
64
96
|
end
|
65
97
|
|
66
98
|
def external_id?
|
67
|
-
|
99
|
+
final_entry.key?("external_id")
|
68
100
|
end
|
69
101
|
|
70
102
|
# @return [String, nil] the _name_ of this person if defined.
|
71
103
|
def name
|
72
|
-
|
104
|
+
final_entry["name"]
|
73
105
|
end
|
74
106
|
|
75
107
|
def name?
|
76
|
-
|
108
|
+
final_entry.key?("name")
|
77
109
|
end
|
78
110
|
|
79
111
|
# @return [String, nil] the _email_ of this person if defined.
|
80
112
|
def email
|
81
|
-
|
113
|
+
final_entry["email"]
|
82
114
|
end
|
83
115
|
|
84
116
|
def email?
|
85
|
-
|
117
|
+
final_entry.key?("email")
|
86
118
|
end
|
87
119
|
|
88
120
|
# @return [String, nil] the _supervisor id_ of this person if defined.
|
89
121
|
def supervisor_id
|
90
|
-
|
122
|
+
final_entry["supervisor_id"]
|
91
123
|
end
|
92
124
|
|
93
125
|
def supervisor_id=(value)
|
94
|
-
|
126
|
+
final_entry["supervisor_id"] = value
|
95
127
|
end
|
96
128
|
|
97
129
|
def supervisor_id?
|
98
|
-
|
130
|
+
final_entry.key?("supervisor_id")
|
99
131
|
end
|
100
132
|
|
101
133
|
def filter_tags
|
102
|
-
|
134
|
+
final_entry["filter_tags"] || []
|
103
135
|
end
|
104
136
|
|
105
137
|
def filter_tags?
|
106
|
-
|
138
|
+
final_entry.key?("filter_tags")
|
139
|
+
end
|
140
|
+
|
141
|
+
def policy_group_ids
|
142
|
+
final_entry["policy_group_ids"] || []
|
107
143
|
end
|
108
144
|
|
109
145
|
def policy_group_ids?
|
110
|
-
|
146
|
+
final_entry.key?("policy_group_ids")
|
111
147
|
end
|
112
148
|
|
113
149
|
def default_tag?
|
114
|
-
|
150
|
+
final_entry.key?("default_tag")
|
115
151
|
end
|
116
152
|
|
117
153
|
def default_tag
|
118
|
-
|
154
|
+
final_entry["default_tag"]
|
119
155
|
end
|
120
156
|
|
121
157
|
# Provides a reference of this person.
|
@@ -124,9 +160,10 @@ module Eco
|
|
124
160
|
options = into_a(options)
|
125
161
|
case
|
126
162
|
when options.include?(:identify)
|
127
|
-
"'#{
|
163
|
+
str_id = id ? "id: '#{id}'; " : ""
|
164
|
+
"(row: #{idx}) '#{name}' (#{str_id}ext_id: '#{external_id}'; email: '#{email}')"
|
128
165
|
else
|
129
|
-
|
166
|
+
final_entry.each.map do |k, v|
|
130
167
|
"'#{k}': '#{v.to_json}'"
|
131
168
|
end.join(" | ")
|
132
169
|
end
|
@@ -135,257 +172,302 @@ module Eco
|
|
135
172
|
# Setter to fill in all the `core` properties of the `Person` that are present in the `Entry`.
|
136
173
|
# @note it only sets those core properties defined in the entry.
|
137
174
|
# Meaning that if an core property is not present in the entry, this will not be set on the target person.
|
138
|
-
# @param person [Person] the person we want to set the core values to.
|
175
|
+
# @param person [Ecoportal::API::V1::Person] the person we want to set the core values to.
|
139
176
|
# @param exclude [String, Array<String>] core attributes that should not be set/changed to the person.
|
140
177
|
def set_core(person, exclude: nil)
|
141
178
|
scoped_attrs = @emap.core_attrs - into_a(exclude)
|
142
|
-
@
|
143
|
-
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# Setter to fill in all the schema `details` fields of the `Person` that are present in the `Entry`.
|
148
|
-
# @note it only sets those details properties defined in the entry.
|
149
|
-
# Meaning that if an details property is not present in the entry, this will not be set on the target person.
|
150
|
-
# @param person [Person] the person we want to set the schema fields' values to.
|
151
|
-
# @param exclude [String, Array<String>] schema field attributes that should not be set/changed to the person.
|
152
|
-
def set_details(person, exclude: nil)
|
153
|
-
person.add_details(@person_parser.schema) if !person.details || !person.details.schema_id
|
154
|
-
scoped_attrs = @emap.details_attrs - into_a(exclude)
|
155
|
-
@internal_entry.slice(*scoped_attrs).each do |attr, value|
|
156
|
-
_set_to_details(person, attr, value)
|
179
|
+
@final_entry.slice(*scoped_attrs).each do |attr, value|
|
180
|
+
set_part(person, attr, value)
|
157
181
|
end
|
158
182
|
end
|
159
183
|
|
160
184
|
# Setter to fill in the `account` properties of the `Person` that are present in the `Entry`.
|
161
185
|
# @note it only sets those account properties defined in the entry.
|
162
186
|
# Meaning that if an account property is not present in the entry, this will not be set on the target person.
|
163
|
-
# @param person [Person] the person we want to set the account values to.
|
187
|
+
# @param person [Ecoportal::API::Internal::Person] the person we want to set the account values to.
|
164
188
|
# @param exclude [String, Array<String>] account properties that should not be set/changed to the person.
|
165
189
|
def set_account(person, exclude: nil)
|
166
190
|
person.account = {} if !person.account
|
167
191
|
person.account.permissions_preset = nil unless person.account.permissions_preset = "custom"
|
168
192
|
scoped_attrs = @emap.account_attrs - into_a(exclude)
|
169
|
-
@
|
170
|
-
|
193
|
+
@final_entry.slice(*scoped_attrs).each do |attr, value|
|
194
|
+
set_part(person.account, attr, value)
|
171
195
|
end
|
172
196
|
end
|
173
197
|
|
174
|
-
#
|
175
|
-
# @note
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
def external_entry
|
185
|
-
@emap.all_attrs.each_with_object({}) do |attr, hash|
|
186
|
-
unless hash.key?(ext_attr = @emap.to_external(attr))
|
187
|
-
hash[ext_attr] = @serialized_entry[attr]
|
188
|
-
end
|
198
|
+
# Setter to fill in all the schema `details` fields of the `Person` that are present in the `Entry`.
|
199
|
+
# @note it only sets those details properties defined in the entry.
|
200
|
+
# Meaning that if an details property is not present in the entry, this will not be set on the target person.
|
201
|
+
# @param person [Ecoportal::API::V1::Person] the person we want to set the schema fields' values to.
|
202
|
+
# @param exclude [String, Array<String>] schema field attributes that should not be set/changed to the person.
|
203
|
+
def set_details(person, exclude: nil)
|
204
|
+
person.add_details(@person_parser.schema) if !person.details || !person.details.schema_id
|
205
|
+
scoped_attrs = @emap.details_attrs - into_a(exclude)
|
206
|
+
@final_entry.slice(*scoped_attrs).each do |attr, value|
|
207
|
+
set_part(person.details, attr, value)
|
189
208
|
end
|
190
209
|
end
|
191
210
|
|
192
|
-
|
193
|
-
|
211
|
+
private
|
212
|
+
|
213
|
+
# @return [Hash] entry in raw: that with **external** names, values and types.
|
214
|
+
def __external_entry(data)
|
215
|
+
return data if parsing?
|
216
|
+
_external_serializing(data)
|
194
217
|
end
|
195
218
|
|
196
|
-
|
197
|
-
|
219
|
+
# @return [Hash] that with **internal** names but **external** values and types.
|
220
|
+
def __mapped_entry(data)
|
221
|
+
return _mapped_parsing(data) if parsing?
|
222
|
+
_mapped_serializing(data)
|
223
|
+
end
|
198
224
|
|
199
|
-
|
200
|
-
|
201
|
-
|
225
|
+
# @return [Hash] that with **internal** names and values, but **external** values and types.
|
226
|
+
def __internal_entry(data)
|
227
|
+
return _internal_parsing(data) if parsing?
|
228
|
+
_internal_serializing(data)
|
229
|
+
end
|
202
230
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
flds << fld.merge("value" => internal_entry[fld.alt_id]).slice("id", "alt_id", "type", "name", "shared", "multiple", "value")
|
209
|
-
end
|
210
|
-
end
|
211
|
-
core_hash.merge!({
|
212
|
-
"details" => {
|
213
|
-
"schema_id" => schema_id,
|
214
|
-
"fields" => details_fields
|
215
|
-
}
|
216
|
-
})
|
217
|
-
end
|
231
|
+
# @return [Hash] that with **internal** names, values and types.
|
232
|
+
def __final_entry(data)
|
233
|
+
return _final_parsing(data) if parsing?
|
234
|
+
_final_serializing(data)
|
235
|
+
end
|
218
236
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
237
|
+
# Serializing helper that maps internal attributes to external attribute names
|
238
|
+
# @note **Serialize**: here we unaliase internal attribute names into external ones.
|
239
|
+
# @param mapped_entry [Hash] that with **internal** names but **external** values and types.
|
240
|
+
# @return [Hash] with **external** names, values and types.
|
241
|
+
def _external_serializing(mapped_entry)
|
242
|
+
target_attrs = @emap.all_attrs | @emap.aliased_attrs
|
243
|
+
rest_keys = mapped_entry.keys - target_attrs
|
244
|
+
target_attrs -= ["send_invites"]
|
245
|
+
external_entry = target_attrs.each_with_object({}) do |attr, hash|
|
246
|
+
unless hash.key?(ext_attr = @emap.to_external(attr))
|
247
|
+
hash[ext_attr] = mapped_entry[attr]
|
224
248
|
end
|
225
249
|
end
|
250
|
+
merge_missing_attrs(external_entry, mapped_entry.slice(*rest_keys))
|
226
251
|
end
|
227
252
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
value = value.map { |v| v&.upcase } if attr == "filter_tags"
|
236
|
-
# preserve previous order
|
237
|
-
current = into_a(person.send(attr))
|
238
|
-
value = (current & value) + (value - current)
|
239
|
-
else
|
240
|
-
value = value&.strip
|
253
|
+
# Parsing helper that aliases attribute names (from internal to external names)
|
254
|
+
# @note **Parse**: here we aliase external attribute names into internal ones.
|
255
|
+
# @param external_entry [Hash] entry in raw, with **external** names and values.
|
256
|
+
# @return [Hash] entry with **internal** names, but still **external** values and types.
|
257
|
+
def _mapped_parsing(external_entry)
|
258
|
+
mapped_hash = @emap.aliased_attrs.each_with_object({}) do |attr, hash|
|
259
|
+
hash[attr] = external_entry[@emap.to_external(attr)]
|
241
260
|
end
|
261
|
+
external_entry.slice(*@emap.direct_attrs).merge(mapped_hash)
|
262
|
+
end
|
242
263
|
|
243
|
-
|
264
|
+
# Serializing helper that **serializes values** that have a parser/serializer defined.
|
265
|
+
# @note **Serializing**:
|
266
|
+
# 1. here we tranform internal into external **values**.
|
267
|
+
# 2. when running the serializers, it overrides existing keys.
|
268
|
+
# @param internal_entry [Hash] entry with **internal** names and values, but **external** types.
|
269
|
+
# @return [Hash] entry with **internal** names and **external** values and types.
|
270
|
+
def _mapped_serializing(internal_entry)
|
271
|
+
internal_entry.merge(_serialize_values(internal_entry, :internal))
|
244
272
|
end
|
245
273
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
274
|
+
# Parsing helper that just **parses the values** that have a parser/serializer defined.
|
275
|
+
# @note this entry will still miss the type parsing (i.e. to `Array` if `multiple`)
|
276
|
+
# @param mapped_entry [Hash] the entry with the _internal attribute_ names but the _external values_.
|
277
|
+
# @return [Hash] the `internal entry` with the **internal** attributes names and values.
|
278
|
+
def _internal_parsing(mapped_entry)
|
279
|
+
mapped_entry.merge(_parse_values(mapped_entry, :internal))
|
280
|
+
end
|
281
|
+
|
282
|
+
# Serializing helper that just creates the _internal entry_ out of a _parsed entry_ (serializes the type).
|
283
|
+
# @param final_entry [Hash] the entry with all _internal_ (attributes, values and types)
|
284
|
+
# @return [Hash] the `internal entry` with the **internal** attributes names and values, but external types.
|
285
|
+
def _internal_serializing(final_entry)
|
286
|
+
final_entry = final_entry.merge(_serialize_values(final_entry, :final))
|
287
|
+
core_account = @person_parser.target_attrs_account + @person_parser.target_attrs_core
|
288
|
+
core_account_hash = core_account.reduce({}) do |hash, attr|
|
289
|
+
hash.merge(hash_attr(attr, _serialize_type(attr, final_entry[attr])))
|
290
|
+
end
|
291
|
+
details_hash = @person_parser.target_attrs_details.reduce({}) do |hash, attr|
|
292
|
+
hash.merge(hash_attr(attr, _serialize_type(attr, final_entry[attr], schema: @person_parser.schema)))
|
293
|
+
end
|
294
|
+
merging(core_account_hash, details_hash) do |internal_entry|
|
295
|
+
merge_missing_attrs(internal_entry, final_entry)
|
254
296
|
end
|
255
|
-
|
256
|
-
person.account.send("#{attr}=", value)
|
257
297
|
end
|
258
298
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
299
|
+
# Parsing helper where attributes with custom parsers are already parsed, but
|
300
|
+
# it finishes to parse the types (i.e. to `Array` if `multiple`)
|
301
|
+
# @param internal_entry [Hash] the entry with the **internal** _attribute_ names and values but the **external** types.
|
302
|
+
# @return [Hash] the `parsed entry` with the **internal** final attributes names, values and types.
|
303
|
+
def _final_parsing(internal_entry)
|
304
|
+
core_account = @emap.account_attrs + @emap.core_attrs
|
305
|
+
core_account_hash = internal_entry.slice(*core_account).each_with_object({}) do |(attr, value), hash|
|
306
|
+
hash[attr] = _parse_type(attr, value)
|
263
307
|
end
|
264
|
-
value = nil if value.to_s.empty?
|
265
|
-
value = @person_parser.parse(:multiple, value) if field.multiple
|
266
308
|
|
267
|
-
|
268
|
-
|
309
|
+
details_hash = internal_entry.slice(*@emap.details_attrs).each_with_object({}) do |(attr, value), hash|
|
310
|
+
hash[attr] = _parse_type(attr, value, schema: @person_parser.schema)
|
269
311
|
end
|
270
312
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
person.send(attr)
|
313
|
+
merging(core_account_hash, details_hash) do |final_entry|
|
314
|
+
final_entry = merge_missing_attrs(final_entry, internal_entry)
|
315
|
+
final_entry.merge(_parse_values(final_entry, :final))
|
316
|
+
end
|
276
317
|
end
|
277
318
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
319
|
+
# Serializing helper that just creates the _parsed entry_ out of a `Person` object.
|
320
|
+
# @note
|
321
|
+
# - when unnesting attributes, the overriding precedence for collisions is
|
322
|
+
# - `core` -> _overrides_ -> `account` -> _overrides_ -> `details`
|
323
|
+
# - to keep things consistent, the `internal entry` hash has keys in this order:
|
324
|
+
# - `core`, `account`, `details`.
|
325
|
+
# @param person [Ecoportal::API::V1::Person] the `Person` object to transform into a _parsed entry_.
|
326
|
+
# @return [Hash] the `parsed entry` with the **internal** attributes names and internal typed values.
|
327
|
+
def _final_serializing(person)
|
328
|
+
core_hash = @person_parser.target_attrs_core.reduce({}) do |hash, attr|
|
329
|
+
hash.merge(hash_attr(attr, get_part(person, attr)))
|
330
|
+
end
|
331
|
+
account_hash = @person_parser.target_attrs_account.reduce({}) do |hash, attr|
|
332
|
+
hash.merge(hash_attr(attr, get_part(person.account, attr)))
|
333
|
+
end
|
334
|
+
details_hash = @person_parser.target_attrs_details.reduce({}) do |hash, attr|
|
335
|
+
hash.merge(hash_attr(attr, get_part(person.details, attr)))
|
336
|
+
end
|
337
|
+
merging(core_hash, account_hash, details_hash) do |final_entry|
|
338
|
+
final_entry["Has account?"] = !!person.account
|
339
|
+
final_entry.merge(_serialize_values(person, :person))
|
340
|
+
end
|
284
341
|
end
|
285
342
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
343
|
+
# HELPERS
|
344
|
+
def _serialize_values(entry, phase = :person)
|
345
|
+
@person_parser.active_attrs(entry, phase, process: :serialize).each_with_object({}) do |attr, hash|
|
346
|
+
data = entry.is_a?(Hash)? entry.merge(hash) : entry
|
347
|
+
serial_attr = @person_parser.serialize(attr, data, phase, deps: @deps[attr] || {})
|
348
|
+
hash.merge!(hash_attr(attr, serial_attr))
|
290
349
|
end
|
291
|
-
value = person.details[attr]
|
292
|
-
value = @person_parser.serialize(:date, value) if field.type == "date"
|
293
|
-
value = @person_parser.serialize(:multiple, value) if field.multiple
|
294
|
-
value
|
295
350
|
end
|
296
351
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
return _aliased_entry(data) if parsing?
|
303
|
-
_serialized_entry(data)
|
352
|
+
def _parse_values(entry, phase = :internal)
|
353
|
+
@person_parser.active_attrs(entry, phase).each_with_object({}) do |attr, hash|
|
354
|
+
parsed_attr = @person_parser.parse(attr, entry.merge(hash), phase)
|
355
|
+
hash.merge!(hash_attr(attr, parsed_attr))
|
356
|
+
end
|
304
357
|
end
|
305
358
|
|
306
|
-
#
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
359
|
+
# Transforms each **typed** value into its `String` version
|
360
|
+
def _serialize_type(attr, value, schema: nil)
|
361
|
+
case
|
362
|
+
when !!schema
|
363
|
+
unless field = schema[attr]
|
364
|
+
fatal("Field '#{attr}' does not exist in details of schema: '#{schema.name}'")
|
365
|
+
end
|
366
|
+
value = @person_parser.serialize(:multiple, value) if field.multiple
|
367
|
+
if @person_parser.defined?(field.type.to_sym)
|
368
|
+
value = @person_parser.serialize(field.type.to_sym, value, deps: {"attr" => attr})
|
369
|
+
end
|
370
|
+
value
|
371
|
+
when ["policy_group_ids", "filter_tags", "login_provider_ids", "starred_ids"].include?(attr)
|
372
|
+
@person_parser.serialize(:multiple, value)
|
373
|
+
when ["freemium", "accept_eula"].include?(attr)
|
374
|
+
@person_parser.serialize(:boolean, value)
|
375
|
+
when ["subordinates"].include?(attr)
|
376
|
+
@person_parser.serialize(:number, value)
|
377
|
+
else
|
378
|
+
value
|
379
|
+
end
|
316
380
|
end
|
317
381
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
382
|
+
# Transforms each `String` value into its **typed** version
|
383
|
+
def _parse_type(attr, value, schema: nil)
|
384
|
+
value = value.strip if value.is_a?(String)
|
385
|
+
value = nil if value.to_s.strip.empty?
|
386
|
+
case
|
387
|
+
when !!schema
|
388
|
+
unless field = schema[attr]
|
389
|
+
fatal("Field '#{attr}' does not exist in details of schema: '#{schema.name}'")
|
390
|
+
end
|
391
|
+
value = @person_parser.parse(:multiple, value) if field.multiple
|
322
392
|
|
323
|
-
|
324
|
-
|
325
|
-
# 1. here we tranform internal into external **values**.
|
326
|
-
# 2. when running the serializers, it overrides existing keys.
|
327
|
-
# @param unserialized_entry [Hash] entry with **internal** names and values.
|
328
|
-
# @return [Hash] entry with **internal names** and **external values**.
|
329
|
-
def _serialized_entry(unserialized_entry)
|
330
|
-
serial_attrs = @person_parser.defined_attrs.reduce({}) do |serial_hash, attr|
|
331
|
-
deps = @deps[attr] || {}
|
332
|
-
serial_attr = @person_parser.serialize(attr, @person, deps: deps)
|
333
|
-
serial_hash.merge(hash_attr(attr, serial_attr))
|
334
|
-
end
|
335
|
-
unserialized_entry.merge(serial_attrs).tap do |hash|
|
336
|
-
if hash.key?("filter_tags") && hash["filter_tags"].is_a?(Array)
|
337
|
-
hash["filter_tags"] = @person_parser.serialize(:multiple, hash["filter_tags"])
|
393
|
+
if @person_parser.defined?(field.type.to_sym)
|
394
|
+
value = @person_parser.parse(field.type.to_sym, value, deps: {"attr" => attr})
|
338
395
|
end
|
396
|
+
value
|
397
|
+
when attr == "email"
|
398
|
+
value = value.strip.downcase if value
|
399
|
+
value
|
400
|
+
when ["policy_group_ids", "filter_tags", "login_provider_ids", "starred_ids"].include?(attr)
|
401
|
+
value = @person_parser.parse(:multiple, value)
|
402
|
+
value = (attr == "filter_tags")? value.compact.map(&:upcase) : value
|
403
|
+
value
|
404
|
+
when ["freemium", "accept_eula"].include?(attr)
|
405
|
+
@person_parser.parse(:boolean, value)
|
406
|
+
when ["subordinates"].include?(attr)
|
407
|
+
@person_parser.parse(:number, value)
|
408
|
+
else
|
409
|
+
value
|
339
410
|
end
|
340
411
|
end
|
341
412
|
|
342
|
-
#
|
343
|
-
# @
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
413
|
+
# Merges multiple hashes giving overriding perference to the first ones.
|
414
|
+
# @return [Hash] with well sorted keys, as they came in the order of the input hashes.
|
415
|
+
def merging(*hashes)
|
416
|
+
sorted_keys = hashes.map {|h| h.keys}.flatten.uniq
|
417
|
+
rev_hash = hashes.reverse.each_with_object({}) {|h, out| out.merge!(h)}
|
418
|
+
merged = sorted_keys.each_with_object({}) do |k, h|
|
419
|
+
h[k] = rev_hash[k]
|
420
|
+
end
|
421
|
+
merged = yield(merged) if block_given?
|
422
|
+
merged
|
348
423
|
end
|
349
424
|
|
350
|
-
#
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
parsed = @person_parser.active_attrs(aliased_entry).each_with_object({}) do |attr, hash|
|
355
|
-
hash[attr] = @person_parser.parse(attr, aliased_entry.merge(hash))
|
356
|
-
end
|
357
|
-
aliased_entry.merge(parsed)
|
425
|
+
# Adds to `dest_entry` the `keys` it misses from `source_entry`
|
426
|
+
def merge_missing_attrs(dest_entry, source_entry)
|
427
|
+
keys_rest = source_entry.keys - dest_entry.keys
|
428
|
+
dest_entry.merge(source_entry.slice(*keys_rest))
|
358
429
|
end
|
359
430
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
# - `core`, `account`, `details`.
|
366
|
-
# @param person [Ecoportal::API::V1::Person] the `Person` object to transform into an _internal entry_.
|
367
|
-
# @return [Hash] the `internal entry` with the **internal** attributes names and values.
|
368
|
-
def _unserialized_entry(person)
|
369
|
-
core_hash = @person_parser.target_attrs_core.reduce({}) do |hash, attr|
|
370
|
-
value = _get_from_core(person, attr)
|
371
|
-
hash.merge(hash_attr(attr, value))
|
372
|
-
end
|
431
|
+
def into_a(value)
|
432
|
+
value = [] if value == nil
|
433
|
+
value = [].push(value) unless value.is_a?(Array)
|
434
|
+
value
|
435
|
+
end
|
373
436
|
|
374
|
-
|
375
|
-
|
376
|
-
|
437
|
+
def get_part(obj, attr)
|
438
|
+
return unless obj
|
439
|
+
case obj
|
440
|
+
when Ecoportal::API::V1::PersonDetails
|
441
|
+
#unless field = obj.get_field(attr)
|
442
|
+
# fatal("Field '#{attr}' does not exist in details of schema: '#{obj.schema_id}'")
|
443
|
+
#end
|
444
|
+
obj[attr]
|
445
|
+
else
|
446
|
+
obj.send(attr)
|
377
447
|
end
|
448
|
+
end
|
378
449
|
|
379
|
-
|
380
|
-
|
381
|
-
|
450
|
+
def set_part(obj, attr, value)
|
451
|
+
return unless obj
|
452
|
+
begin
|
453
|
+
case obj
|
454
|
+
when Ecoportal::API::V1::PersonDetails
|
455
|
+
unless field = obj.get_field(attr)
|
456
|
+
fatal("Field '#{attr}' does not exist in details of schema: '#{obj.schema_id}'")
|
457
|
+
end
|
458
|
+
obj[attr] = value
|
459
|
+
else
|
460
|
+
obj.send("#{attr}=", value)
|
461
|
+
end
|
462
|
+
rescue Exception => e
|
463
|
+
raise e.append_message " -- Entry #{to_s(:identify)}"
|
382
464
|
end
|
465
|
+
end
|
383
466
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
sorted_keys.reduce({}) {|h,k| h[k] = rh[k]; h}
|
467
|
+
# @return [Hash] `value` if it was a `Hash`, and `{ attr => value}` otherwise
|
468
|
+
def hash_attr(attr, value)
|
469
|
+
return value if value.is_a?(Hash)
|
470
|
+
{ attr => value }
|
389
471
|
end
|
390
472
|
|
391
473
|
# LOGGER
|
@@ -398,11 +480,21 @@ module Eco
|
|
398
480
|
raise msg
|
399
481
|
end
|
400
482
|
|
401
|
-
#
|
402
|
-
def
|
403
|
-
|
404
|
-
|
405
|
-
|
483
|
+
# Function to debug faste
|
484
|
+
def print_models
|
485
|
+
print_it = Proc.new do |name, model|
|
486
|
+
puts "#{name}:"
|
487
|
+
pp model
|
488
|
+
puts "*" * 30
|
489
|
+
end
|
490
|
+
|
491
|
+
fin = Proc.new {|x_| print_it.call("final_entry", @final_entry) }
|
492
|
+
int = Proc.new {|x_| print_it.call("internal_entry", @internal_entry) }
|
493
|
+
mad = Proc.new {|x_| print_it.call("mapped_entry", @mapped_entry) }
|
494
|
+
ext = Proc.new {|x_| print_it.call("external_entry", @external_entry) }
|
495
|
+
|
496
|
+
call_order = parsing? ? [ext, mad, int, fin] : [fin, int, mad, ext]
|
497
|
+
call_order.each {|proc| proc.call}
|
406
498
|
end
|
407
499
|
|
408
500
|
end
|