eco-helpers 2.6.4 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +95 -0
- data/CHANGELOG.md +139 -2
- data/Rakefile +13 -7
- data/eco-helpers.gemspec +2 -2
- data/lib/eco/api/common/loaders/base.rb +2 -2
- data/lib/eco/api/common/loaders/case_base.rb +1 -1
- data/lib/eco/api/common/loaders/config/workflow/mailer.rb +5 -5
- data/lib/eco/api/common/loaders/error_handler.rb +8 -5
- data/lib/eco/api/common/loaders/parser.rb +44 -22
- data/lib/eco/api/common/loaders/policy.rb +6 -4
- data/lib/eco/api/common/loaders/use_case.rb +13 -7
- data/lib/eco/api/common/people/base_parser.rb +0 -2
- data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +0 -1
- data/lib/eco/api/common/people/default_parsers/csv_parser.rb +1 -1
- data/lib/eco/api/common/people/default_parsers/date_parser.rb +64 -12
- data/lib/eco/api/common/people/default_parsers/freemium_parser.rb +0 -1
- data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +13 -5
- data/lib/eco/api/common/people/default_parsers/multi_parser.rb +0 -1
- data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +18 -5
- data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +8 -8
- data/lib/eco/api/common/people/default_parsers/select_parser.rb +50 -26
- data/lib/eco/api/common/people/default_parsers/send_invites_parser.rb +6 -6
- data/lib/eco/api/common/people/default_parsers/xls_parser.rb +9 -12
- data/lib/eco/api/common/people/default_parsers.rb +1 -12
- data/lib/eco/api/common/people/entries.rb +13 -13
- data/lib/eco/api/common/people/entry_factory.rb +76 -45
- data/lib/eco/api/common/people/person_attribute_parser.rb +8 -12
- data/lib/eco/api/common/people/person_entry.rb +86 -75
- data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +60 -44
- data/lib/eco/api/common/people/person_factory.rb +30 -22
- data/lib/eco/api/common/people/person_modifier.rb +11 -13
- data/lib/eco/api/common/people/person_parser.rb +101 -39
- data/lib/eco/api/common/people/supervisor_helpers.rb +25 -26
- data/lib/eco/api/common/session/base_session.rb +9 -9
- data/lib/eco/api/common/session/environment.rb +7 -5
- data/lib/eco/api/common/session/sftp.rb +59 -32
- data/lib/eco/api/common/version_patches/exception.rb +11 -13
- data/lib/eco/api/error.rb +32 -20
- data/lib/eco/api/organization/node_classifications.rb +82 -0
- data/lib/eco/api/organization/policy_groups.rb +4 -6
- data/lib/eco/api/organization/tag_tree.rb +169 -93
- data/lib/eco/api/organization.rb +1 -0
- data/lib/eco/api/session/batch/job.rb +1 -1
- data/lib/eco/api/session/config/tagtree.rb +41 -23
- data/lib/eco/api/session/config/workflow.rb +113 -88
- data/lib/eco/api/session/config.rb +6 -0
- data/lib/eco/api/session.rb +51 -29
- data/lib/eco/api/usecases/base_io.rb +28 -25
- data/lib/eco/api/usecases/default/locations/cli/tagtree_extract_cli.rb +7 -2
- data/lib/eco/api/usecases/default/locations/cli/tagtree_upload_cli.rb +21 -0
- data/lib/eco/api/usecases/default/locations/csv_to_tree_case.rb +3 -3
- data/lib/eco/api/usecases/default/locations/tagtree_extract_case.rb +54 -23
- data/lib/eco/api/usecases/default/locations/tagtree_upload_case.rb +87 -0
- data/lib/eco/api/usecases/default/locations.rb +1 -0
- data/lib/eco/api/usecases/default/people/analyse_people_case.rb +60 -56
- data/lib/eco/api/usecases/default/people/change_email_case.rb +8 -9
- data/lib/eco/api/usecases/default/people/clean_unknown_tags_case.rb +13 -11
- data/lib/eco/api/usecases/default/people/clear_abilities_case.rb +2 -2
- data/lib/eco/api/usecases/default/people/org_data_convert_case.rb +25 -27
- data/lib/eco/api/usecases/default/people/refresh_case.rb +2 -2
- data/lib/eco/api/usecases/default/people/reinvite_trans_case.rb +1 -1
- data/lib/eco/api/usecases/default/people/reinvite_trans_cli.rb +0 -1
- data/lib/eco/api/usecases/default/people/restore_db_case.rb +39 -34
- data/lib/eco/api/usecases/default/people/set_default_tag_case.rb +19 -15
- data/lib/eco/api/usecases/default/people/supers_cyclic_identify_case.rb +16 -12
- data/lib/eco/api/usecases/default_cases/hris_case.rb +17 -15
- data/lib/eco/api/usecases/default_cases/samples/sftp_case.rb +30 -16
- data/lib/eco/api/usecases/graphql/base.rb +5 -3
- data/lib/eco/api/usecases/graphql/helpers/base/case_env.rb +4 -1
- data/lib/eco/api/usecases/graphql/helpers/base/graphql_env.rb +14 -0
- data/lib/eco/api/usecases/graphql/helpers/base.rb +5 -4
- data/lib/eco/api/usecases/graphql/helpers/location/base/classifications_parser.rb +60 -0
- data/lib/eco/api/usecases/graphql/helpers/location/base/tree_tracking.rb +72 -0
- data/lib/eco/api/usecases/graphql/helpers/location/base.rb +25 -59
- data/lib/eco/api/usecases/graphql/helpers/location/command/diff/as_update.rb +59 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diff/compare.rb +49 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diff.rb +11 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/commandable.rb +46 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_archive.rb +23 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_unarchive.rb +65 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable.rb +49 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable/relation_safe_sort.rb +119 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable.rb +59 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages.rb +82 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs.rb +20 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/optimizations.rb +84 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/result.rb +4 -4
- data/lib/eco/api/usecases/graphql/helpers/location/command/results.rb +24 -12
- data/lib/eco/api/usecases/graphql/helpers/location/command.rb +21 -24
- data/lib/eco/api/usecases/graphql/helpers/location/tags_remap/tags_map.rb +1 -1
- data/lib/eco/api/usecases/graphql/helpers/location/tags_remap/tags_set.rb +10 -11
- data/lib/eco/api/usecases/graphql/helpers/location/tags_remap.rb +8 -9
- data/lib/eco/api/usecases/graphql/samples/location/command/dsl.rb +41 -12
- data/lib/eco/api/usecases/graphql/samples/location/command/results.rb +11 -80
- data/lib/eco/api/usecases/graphql/samples/location/command/service/tree_update.rb +89 -0
- data/lib/eco/api/usecases/graphql/samples/location/command/service.rb +6 -0
- data/lib/eco/api/usecases/graphql/samples/location/command/track_changed_ids.rb +89 -0
- data/lib/eco/api/usecases/graphql/samples/location/command.rb +3 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/base.rb +9 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/heading.rb +18 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/inputable.rb +53 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/classifications.rb +34 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/helpers.rb +28 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing.rb +46 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible.rb +38 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff.rb +105 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/discarded.rb +16 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/input.rb +15 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/node_attr_maps.rb +22 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/parser.rb +45 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter.rb +36 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/output.rb +56 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list.rb +41 -0
- data/lib/eco/api/usecases/graphql/samples/location/service.rb +8 -0
- data/lib/eco/api/usecases/graphql/samples/location.rb +1 -0
- data/lib/eco/api/usecases/graphql/utils/sftp.rb +96 -36
- data/lib/eco/api/usecases/ooze_cases/export_register_case.rb +8 -6
- data/lib/eco/api/usecases/ooze_samples/helpers/creatable.rb +4 -3
- data/lib/eco/api/usecases/ooze_samples/helpers/exportable_ooze.rb +39 -25
- data/lib/eco/api/usecases/ooze_samples/helpers/exportable_register.rb +13 -15
- data/lib/eco/api/usecases/ooze_samples/helpers/filters.rb +50 -21
- data/lib/eco/api/usecases/ooze_samples/helpers/ooze_handlers.rb +21 -11
- data/lib/eco/api/usecases/ooze_samples/helpers/rescuable.rb +2 -0
- data/lib/eco/api/usecases/ooze_samples/helpers/shortcuts.rb +49 -43
- data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +17 -19
- data/lib/eco/api/usecases/ooze_samples/register_export_case.rb +48 -43
- data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +33 -34
- data/lib/eco/api/usecases/ooze_samples/target_oozes_update_case.rb +8 -10
- data/lib/eco/api/usecases.rb +0 -1
- data/lib/eco/cli/config/use_cases.rb +31 -29
- data/lib/eco/cli_default/workflow.rb +13 -14
- data/lib/eco/csv/table.rb +34 -25
- data/lib/eco/data/hashes/array_diff.rb +24 -35
- data/lib/eco/data/hashes/diff_result/meta.rb +131 -0
- data/lib/eco/data/hashes/diff_result.rb +65 -57
- data/lib/eco/data/hashes/sanke_camel_indifferent_access.rb +278 -0
- data/lib/eco/data/hashes.rb +1 -1
- data/lib/eco/data/locations/convert.rb +1 -1
- data/lib/eco/data/locations/node_base/csv_convert.rb +19 -9
- data/lib/eco/data/locations/node_base/parsing.rb +4 -2
- data/lib/eco/data/locations/node_base/treeify.rb +149 -132
- data/lib/eco/data/locations/node_base.rb +15 -4
- data/lib/eco/data/locations/node_diff/accessors.rb +13 -5
- data/lib/eco/data/locations/node_diff/nodes_diff/clustered_treeify.rb +101 -0
- data/lib/eco/data/locations/node_diff/nodes_diff/diffs_tree.rb +99 -0
- data/lib/eco/data/locations/node_diff/{selectors.rb → nodes_diff/selectors.rb} +1 -1
- data/lib/eco/data/locations/node_diff/nodes_diff.rb +50 -35
- data/lib/eco/data/locations/node_diff.rb +45 -17
- data/lib/eco/data/locations/node_level/parsing.rb +15 -21
- data/lib/eco/data/locations/node_level.rb +66 -22
- data/lib/eco/data/locations/node_plain/parsing.rb +1 -1
- data/lib/eco/data/locations/node_plain.rb +60 -7
- data/lib/eco/data/strings/camel_case.rb +35 -0
- data/lib/eco/data/strings/snake_case.rb +18 -0
- data/lib/eco/data/strings.rb +8 -0
- data/lib/eco/data.rb +1 -0
- data/lib/eco/language/auxiliar_logger.rb +7 -5
- data/lib/eco/language/methods/call_detector.rb +11 -0
- data/lib/eco/language/methods/dsl_able.rb +7 -1
- data/lib/eco/language/methods.rb +2 -1
- data/lib/eco/language/models/collection.rb +23 -25
- data/lib/eco/language/models/parser_serializer.rb +24 -5
- data/lib/eco/version.rb +1 -1
- data/lib/eco-helpers.rb +0 -1
- metadata +52 -7
- data/lib/eco/data/hashes/diff_meta.rb +0 -52
@@ -1,12 +1,9 @@
|
|
1
1
|
class Eco::API::UseCases::GraphQL::Samples::Location
|
2
|
-
# Logic to:
|
3
|
-
# 1. Track-down results and errors
|
4
|
-
# 2. Create tags remap csv table batch design
|
2
|
+
# Logic to: Track-down results and errors
|
5
3
|
module Command::Results
|
6
|
-
include Eco::API::UseCases::GraphQL::Helpers::
|
4
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base::CaseEnv
|
7
5
|
|
8
6
|
attr_accessor :error, :exception
|
9
|
-
attr_accessor :tags_remap_csv_file
|
10
7
|
|
11
8
|
def rescued
|
12
9
|
yield
|
@@ -18,39 +15,35 @@ class Eco::API::UseCases::GraphQL::Samples::Location
|
|
18
15
|
Eco::API::UseCases::GraphQL::Helpers::Location::Command::Results
|
19
16
|
end
|
20
17
|
|
21
|
-
def tags_remap_class
|
22
|
-
Eco::API::UseCases::GraphQL::Helpers::Location::TagsRemap
|
23
|
-
end
|
24
|
-
|
25
18
|
# Capture results
|
26
19
|
def results
|
27
20
|
@results ||= {}
|
28
21
|
end
|
29
22
|
|
30
|
-
# The maps of tags to be used in batch remap tags
|
31
|
-
# @return [Array<Array>] source/destination pairs of `Array<String>`
|
32
|
-
def tags_remap_table
|
33
|
-
@tags_remap_table ||= tags_remap_class.new
|
34
|
-
end
|
35
|
-
|
36
23
|
# Errors tracking/logging.
|
37
24
|
# @note it gives feedback on where an error has occurred.
|
38
25
|
# @param page_results [Eco::API::UseCases::GraphQL::Helpers::Locations::Commands::CommandResults]
|
39
26
|
# @param stage [Symbol] used when we launch an update in different phases (i.e. rename, move, etc.)
|
40
27
|
# @return [Boolean] whether or not there was an error
|
41
28
|
def page_errors?(page_results, page, pages, done, total, stage: nil)
|
42
|
-
|
29
|
+
msg = "Expecting CommandResults object. Given: #{page_results.class}"
|
30
|
+
raise msg unless page_results.is_a?(request_results_class)
|
31
|
+
|
43
32
|
stage_str = stage ? "'#{stage}' " : ''
|
44
33
|
fingerprint = "#{stage_str}#{page} (of #{pages})"
|
45
34
|
errored = false
|
46
35
|
|
47
36
|
if page_results.error?
|
48
37
|
errored = true
|
49
|
-
log(:error) {
|
38
|
+
log(:error) {
|
39
|
+
"Error on #{fingerprint}: #{page_results.error.doc.pretty_inspect}"
|
40
|
+
}
|
50
41
|
end
|
51
42
|
|
52
43
|
if page_results.applied?
|
53
|
-
log(:info) {
|
44
|
+
log(:info) {
|
45
|
+
"Success on #{fingerprint}: #{done} (of #{total}) commands applied!"
|
46
|
+
}
|
54
47
|
elsif page_results.errored?
|
55
48
|
errored = true
|
56
49
|
msg = "Some command failed on #{fingerprint}:\n#{page_results.stats}"
|
@@ -63,67 +56,5 @@ class Eco::API::UseCases::GraphQL::Samples::Location
|
|
63
56
|
|
64
57
|
errored
|
65
58
|
end
|
66
|
-
|
67
|
-
# Based on commands that succeded, and the batch stage, it tracks
|
68
|
-
# the tag remaps that should be batches against existing pages
|
69
|
-
# @note
|
70
|
-
# 1. This requires to have available the `current_tree` locations structure
|
71
|
-
# - Fortunatelly this is being tracked, as it is returned as payload of the response.
|
72
|
-
# 2. Based on the assumption that the order of the commands (stages) happens like this:
|
73
|
-
# - :unarchive, :id_name, :insert, :move, :archive
|
74
|
-
# 3. The only update operations that generate tag remaps are `:id` (or `:id_name`) and `:move`.
|
75
|
-
def update_tags_remap_table(results, stage)
|
76
|
-
return false if [:unarchive, :archive].include?(stage)
|
77
|
-
raise "Expecting CommandResults object. Given: #{results.class}" unless results.is_a?(request_results_class)
|
78
|
-
results.applied.each do |result|
|
79
|
-
case stage
|
80
|
-
when :id, :id_name
|
81
|
-
prev_id, curr_id = result.command_input_data.values_at(:nodeId, :newId)
|
82
|
-
|
83
|
-
unless current_tree.tag?(curr_id)
|
84
|
-
msg = "Node '#{prev_id}' was updated to '#{curr_id}', "
|
85
|
-
msg << "but in current structure '#{curr_id}' is not present"
|
86
|
-
log(:warn) { msg }
|
87
|
-
end
|
88
|
-
|
89
|
-
tags_remap_table << [[prev_id], [curr_id]]
|
90
|
-
when :move
|
91
|
-
node_id, parent_id = result.command_input_data.values_at(:nodeId, :parentId)
|
92
|
-
prev_node = previous_tree.node(node_id)
|
93
|
-
curr_node = current_tree.node(node_id)
|
94
|
-
prev_path = prev_node.path.reverse
|
95
|
-
new_path = curr_node.path.reverse
|
96
|
-
|
97
|
-
curr_parent = curr_node.parent.top? ? nil : curr_node.parent
|
98
|
-
unless curr_parent&.id == parent_id
|
99
|
-
msg = "Node '#{node_id}' was moved under '#{parent_id}', "
|
100
|
-
msg << "but in current structure has parent '#{curr_parent&.id}'"
|
101
|
-
log(:warn) { msg }
|
102
|
-
end
|
103
|
-
|
104
|
-
tags_remap_table << [prev_path, new_path]
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# Generates the final tags remap file
|
110
|
-
def generate_tags_remap_csv(filename = "cache/remap_tags.csv")
|
111
|
-
return nil if tags_remap_table.empty?
|
112
|
-
timestamp_file(filename).tap do |file|
|
113
|
-
CSV.open(file, 'w') do |csv|
|
114
|
-
csv << ["source_tags", "destination_tags"]
|
115
|
-
tags_remap_table.each do |tags_remap|
|
116
|
-
csv << tags_remap.to_csv_row
|
117
|
-
end
|
118
|
-
end
|
119
|
-
log(:info) { "Generated file '#{file}'" }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# Makes the file relative to the enviro
|
124
|
-
def timestamp_file(filename, enviro_relative: true)
|
125
|
-
filename = session.file_manager.dir.file(filename) if enviro_relative
|
126
|
-
Eco::Data::Files.timestamp_file(filename)
|
127
|
-
end
|
128
59
|
end
|
129
60
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class Eco::API::UseCases::GraphQL::Samples::Location
|
2
|
+
module Command::Service
|
3
|
+
# Service to generate the command updates.
|
4
|
+
module TreeUpdate
|
5
|
+
include Eco::API::UseCases::GraphQL::Samples::Location::Service::TreeDiff
|
6
|
+
include Eco::API::UseCases::GraphQL::Samples::Location::Command::DSL
|
7
|
+
include Eco::API::UseCases::GraphQL::Utils::Sftp
|
8
|
+
|
9
|
+
# Whether to stop or continue on command fail
|
10
|
+
FORCE_CONTINUE = false
|
11
|
+
|
12
|
+
def process
|
13
|
+
super
|
14
|
+
ensure
|
15
|
+
rescued { re_archive }
|
16
|
+
rescued { email_digest('TagTree Update') }
|
17
|
+
end
|
18
|
+
|
19
|
+
# Before closing, run RE-ARCHIVE: those that where unarchived via archivedToken
|
20
|
+
# that should remain archived.
|
21
|
+
# @note this is an additional necessary step
|
22
|
+
def re_archive
|
23
|
+
return if simulate?
|
24
|
+
stage = :rearchive
|
25
|
+
|
26
|
+
nodes_diff_class.new(
|
27
|
+
hash_list(current_tree),
|
28
|
+
file_nodes_list,
|
29
|
+
original_tree: current_tree,
|
30
|
+
logger: logger
|
31
|
+
).tap do |nodes_diff|
|
32
|
+
archive_input = input(nodes_diff.stage_commands(:archive), force_continue: true)
|
33
|
+
sliced_batches(
|
34
|
+
archive_input,
|
35
|
+
desc: stage,
|
36
|
+
track_tree_mode: :once
|
37
|
+
) do |sliced_input, response, page, pages, count, total| # rubocop:disable Metrics/ParameterLists
|
38
|
+
page_results = request_results_class.new(sliced_input, response)
|
39
|
+
(results[stage] ||= []) << page_results
|
40
|
+
self.error ||= page_errors?(page_results, page, pages, count, total, stage: stage)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Work with adapted diff builders.
|
48
|
+
def nodes_diff_class
|
49
|
+
Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
|
50
|
+
end
|
51
|
+
|
52
|
+
def inputs(nodes_diff = comparer, force_continue: force_continue?)
|
53
|
+
{}.tap do |sequence|
|
54
|
+
nodes_diff.commands do |comms, stage|
|
55
|
+
sequence[stage] = input(comms, force_continue: force_continue)
|
56
|
+
end
|
57
|
+
end.tap do |sequence|
|
58
|
+
sequence.each do |stage, input|
|
59
|
+
yield(input, stage) if block_given?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Generates the file and pushes to the SFTP folder
|
65
|
+
# @note this method can only work if we can run cummulative dry-runs to the back-end.
|
66
|
+
# This is only possible using a draft, which is not that desired.
|
67
|
+
# @note the SFTP push only happens if `remote_subfolder` is defined, via:
|
68
|
+
# 1. `options.dig(:sftp, :remote_subfolder)`
|
69
|
+
# 2. `REMOTE_FOLDER` const
|
70
|
+
def close_handling_tags_remap_csv
|
71
|
+
return false unless super
|
72
|
+
upload(tags_remap_csv_file) unless remote_subfolder.nil?
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def email_digest(title)
|
77
|
+
return if simulate?
|
78
|
+
digest_msgs = logger.cache.logs(level: %i[info error warn])
|
79
|
+
exception = exception ? " - Exception!" : ''
|
80
|
+
subject = "#{config.active_enviro} - #{title}#{exception}"
|
81
|
+
session.mail(subject: subject, body: digest_msgs.join)
|
82
|
+
end
|
83
|
+
|
84
|
+
def print_diff_details?
|
85
|
+
false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class Eco::API::UseCases::GraphQL::Samples::Location
|
2
|
+
# Logic to: Create tags remap csv table batch design
|
3
|
+
module Command::TrackChangedIds
|
4
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base::CaseEnv
|
5
|
+
|
6
|
+
attr_accessor :tags_remap_csv_file
|
7
|
+
|
8
|
+
REMAP_LOC_IDS_FOLDER = 'cache'.freeze
|
9
|
+
REMAP_LOC_IDS_FILENAME = 'remap_loc_ids.csv'.freeze
|
10
|
+
|
11
|
+
def tags_remap_csv_full_filename
|
12
|
+
folder = self.class::REMAP_LOC_IDS_FOLDER
|
13
|
+
filename = self.class::REMAP_LOC_IDS_FILENAME
|
14
|
+
File.join(folder, filename)
|
15
|
+
end
|
16
|
+
|
17
|
+
def tags_remap_class
|
18
|
+
Eco::API::UseCases::GraphQL::Helpers::Location::TagsRemap
|
19
|
+
end
|
20
|
+
|
21
|
+
# The maps of tags to be used in batch remap tags
|
22
|
+
# @return [Array<Array>] source/destination pairs of `Array<String>`
|
23
|
+
def tags_remap_table
|
24
|
+
@tags_remap_table ||= tags_remap_class.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# Generates the file
|
28
|
+
# @note this method can only work if we can run cummulative dry-runs to the back-end.
|
29
|
+
# This is only possible using a draft, which is not that desired.
|
30
|
+
def close_handling_tags_remap_csv
|
31
|
+
return false if simulate?
|
32
|
+
if tags_remap_table.any?
|
33
|
+
puts "REMAP LOC IDs CSV (content):"
|
34
|
+
puts tags_remap_table
|
35
|
+
true
|
36
|
+
else
|
37
|
+
log(:info) { "Remap location ids NOT needed :)" }
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Based on commands that succeded, and the batch stage, it tracks
|
43
|
+
# the tag remaps that should be batches against existing pages
|
44
|
+
# @note The only update operation that generate tag remaps
|
45
|
+
# is `:id` (or `:id_name`).
|
46
|
+
# @return [Boolean] whether new maps were inserted to the tracking table
|
47
|
+
def update_tags_remap_table(results, stage, ref_tree = nil)
|
48
|
+
return false unless %i[id id_name].include?(stage)
|
49
|
+
|
50
|
+
msg = "Expecting CommandResults object. Given: #{results.class}"
|
51
|
+
raise msg unless results.is_a?(request_results_class)
|
52
|
+
|
53
|
+
results.applied.each do |result|
|
54
|
+
prev_id, new_id = result.command_input_data.values_at(:nodeId, :newId)
|
55
|
+
next if new_id.nil? # not an id change
|
56
|
+
next if prev_id == new_id
|
57
|
+
|
58
|
+
tags_remap_table << [[prev_id], [new_id]]
|
59
|
+
|
60
|
+
next unless ref_tree.is_a?(Eco::API::Organization::TagTree)
|
61
|
+
next unless ref_tree.tag?(new_id)
|
62
|
+
|
63
|
+
msg = "Node '#{prev_id}' was updated to '#{new_id}', "
|
64
|
+
msg << "but in current structure '#{new_id}' is not present"
|
65
|
+
log(:warn) { msg }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Generates the final tags remap file
|
70
|
+
def generate_tags_remap_csv(filename = tags_remap_csv_full_filename)
|
71
|
+
return nil if tags_remap_table.empty?
|
72
|
+
timestamp_file(filename).tap do |file|
|
73
|
+
CSV.open(file, 'w') do |csv|
|
74
|
+
csv << %w[prev_node_ids new_node_ids]
|
75
|
+
tags_remap_table.each do |tags_remap|
|
76
|
+
csv << tags_remap.to_csv_row
|
77
|
+
end
|
78
|
+
end
|
79
|
+
log(:info) { "Generated file '#{file}'" }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Makes the file relative to the enviro
|
84
|
+
def timestamp_file(filename, enviro_relative: true)
|
85
|
+
filename = session.file_manager.dir.file(filename) if enviro_relative
|
86
|
+
Eco::Data::Files.timestamp_file(filename)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -4,7 +4,10 @@ module Eco::API::UseCases::GraphQL::Samples
|
|
4
4
|
name "location-command"
|
5
5
|
|
6
6
|
require_relative 'command/results'
|
7
|
+
require_relative 'command/track_changed_ids'
|
7
8
|
require_relative 'command/dsl'
|
8
9
|
include Eco::API::UseCases::GraphQL::Samples::Location::Command::DSL
|
9
10
|
end
|
10
11
|
end
|
12
|
+
|
13
|
+
require_relative 'command/service'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Samples::Location::Service
|
2
|
+
module TreeDiff
|
3
|
+
module Convertible
|
4
|
+
# Converting headers
|
5
|
+
module Heading
|
6
|
+
# Define the maps src -> dst heading name
|
7
|
+
# @example {'parent_id' => 'parentId' }
|
8
|
+
HEADER_MAPS = {}.freeze
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def header_maps
|
13
|
+
self.class::HEADER_MAPS
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Samples::Location::Service
|
2
|
+
module TreeDiff
|
3
|
+
module Convertible
|
4
|
+
module Inputable
|
5
|
+
class << self
|
6
|
+
def included(base)
|
7
|
+
super(base)
|
8
|
+
base.send :include, Eco::Data::Files
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base::CaseEnv
|
13
|
+
|
14
|
+
IN_FILENAME = /requested_tree\.csv/.freeze
|
15
|
+
IN_FOLDER = 'sftp'.freeze
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def input_encoding
|
20
|
+
options.dig(:input, :file, :encoding) || 'utf-8'
|
21
|
+
end
|
22
|
+
|
23
|
+
def input_file
|
24
|
+
@input_file ||= (options.dig(:input, :file, :name) || newest_file).tap do |file|
|
25
|
+
if file
|
26
|
+
log(:info) { "Using input file '#{file}'" }
|
27
|
+
else
|
28
|
+
log(:warn) { "Could not find any input file" }
|
29
|
+
exit(1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def newest_file
|
35
|
+
@newest_file ||= csv_files.last
|
36
|
+
end
|
37
|
+
|
38
|
+
#@note via Eco::Data::Files
|
39
|
+
def csv_files
|
40
|
+
self.class.csv_files(input_folder, regexp: input_file_pattern)
|
41
|
+
end
|
42
|
+
|
43
|
+
def input_file_pattern
|
44
|
+
self.class::IN_FILENAME
|
45
|
+
end
|
46
|
+
|
47
|
+
def input_folder
|
48
|
+
"#{config.active_enviro}/#{self.class::IN_FOLDER}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Samples::Location::Service
|
2
|
+
module TreeDiff
|
3
|
+
module Convertible
|
4
|
+
module Parsing
|
5
|
+
module Classifications
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
# Input classification values into actual
|
9
|
+
# classification values
|
10
|
+
CLASSIFICATION_MAPS = {}.freeze
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def transform_classifications(row)
|
15
|
+
return row if node_classifications_maping.empty?
|
16
|
+
row['classifications'] = into_a(row['classifications']).map do |type|
|
17
|
+
node_classifications_map(type)
|
18
|
+
end.join('|')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Helper to map classifications
|
22
|
+
def node_classifications_map(value)
|
23
|
+
return value unless node_classifications_maping.key?(value)
|
24
|
+
node_classifications_maping[value]
|
25
|
+
end
|
26
|
+
|
27
|
+
def node_classifications_maping
|
28
|
+
self.class::CLASSIFICATION_MAPS
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/helpers.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Samples::Location::Service
|
2
|
+
module TreeDiff
|
3
|
+
module Convertible
|
4
|
+
module Parsing
|
5
|
+
module Helpers
|
6
|
+
private
|
7
|
+
|
8
|
+
def as_boolean(value)
|
9
|
+
return false if value.nil? || value == false
|
10
|
+
return true if value == true
|
11
|
+
return false if value.to_s.strip.empty?
|
12
|
+
return true if %w[yes x true].include?(value.downcase)
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
# Helper to convert to array
|
17
|
+
def into_a(value)
|
18
|
+
if value.is_a?(String)
|
19
|
+
value.split('|')
|
20
|
+
else
|
21
|
+
[value].flatten
|
22
|
+
end.compact
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'parsing/helpers'
|
2
|
+
require_relative 'parsing/classifications'
|
3
|
+
module Eco::API::UseCases::GraphQL::Samples::Location::Service
|
4
|
+
module TreeDiff
|
5
|
+
module Convertible
|
6
|
+
# Helpers for transform
|
7
|
+
module Parsing
|
8
|
+
include Helpers
|
9
|
+
include Classifications
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Custom callback to some required convertions to the input file
|
14
|
+
# provided that it fits to the required input format.
|
15
|
+
def transform_input_csv(csv)
|
16
|
+
row_transform = custom_input_row_transform_block
|
17
|
+
csv_transform = custom_input_csv_transform_block
|
18
|
+
|
19
|
+
csv = csv_transform.call(csv) if csv_transform
|
20
|
+
|
21
|
+
msg = "Expecting Eco::CSV::Table (i.e. from 'custom_input_csv_transform')."
|
22
|
+
msg << "Given: #{csv.class}"
|
23
|
+
raise ArgumentError, msg unless csv.is_a?(Eco::CSV::Table)
|
24
|
+
|
25
|
+
csv.each do |row|
|
26
|
+
row_transform&.call(row)
|
27
|
+
transform_classifications(row)
|
28
|
+
end
|
29
|
+
csv
|
30
|
+
end
|
31
|
+
|
32
|
+
# The user define block for row transformation
|
33
|
+
def custom_input_row_transform_block
|
34
|
+
return nil unless respond_to?(:custom_input_row_transform, true)
|
35
|
+
method(:custom_input_row_transform)
|
36
|
+
end
|
37
|
+
|
38
|
+
# The user define block for row transformation
|
39
|
+
def custom_input_csv_transform_block
|
40
|
+
return nil unless respond_to?(:custom_input_csv_transform, true)
|
41
|
+
method(:custom_input_csv_transform)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'convertible/heading'
|
2
|
+
require_relative 'convertible/parsing'
|
3
|
+
require_relative 'convertible/inputable'
|
4
|
+
module Eco::API::UseCases::GraphQL::Samples::Location::Service
|
5
|
+
module TreeDiff
|
6
|
+
# Offers a way to convert the values and keys/headers
|
7
|
+
# of the input csv file/rows
|
8
|
+
module Convertible
|
9
|
+
class << self
|
10
|
+
def included(base)
|
11
|
+
super(base)
|
12
|
+
base.send :include, Inputable
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
include Parsing
|
17
|
+
include Heading
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def input_csv
|
22
|
+
@input_csv ||= Eco::CSV.read(input_file, encoding: input_encoding).then do |csv|
|
23
|
+
next csv unless header_maps&.any?
|
24
|
+
|
25
|
+
csv.transform_headers do |name|
|
26
|
+
next name unless header_maps.key?(name)
|
27
|
+
header_maps[name]
|
28
|
+
end
|
29
|
+
end.then do |csv|
|
30
|
+
transform_input_csv(csv).tap do |res|
|
31
|
+
next if res.is_a?(Eco::CSV::Table)
|
32
|
+
raise ArgumentError, "Expecting and Eco::CSV::Table. Given: #{res.class}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Samples
|
2
|
+
module Location::Service
|
3
|
+
# Service to spot the differences between an input file and a locations tree.
|
4
|
+
# @example
|
5
|
+
# class Custom::UseCase::TagtreeDiff < Eco::API::UseCases::GraphQL::Samples::Location
|
6
|
+
# name 'tagtree-diff'
|
7
|
+
# type :other
|
8
|
+
|
9
|
+
# require_relative 'cli/10_tagtree_diff_cli'
|
10
|
+
|
11
|
+
# include Eco::API::UseCases::GraphQL::Samples::Location::Service::TreeDiff
|
12
|
+
|
13
|
+
# IN_FILENAME = /requested_tree\.csv/.freeze
|
14
|
+
# IN_FOLDER = 'sftp'.freeze
|
15
|
+
# HEADER_MAPS = {
|
16
|
+
# 'Code' => 'id',
|
17
|
+
# 'Description' => 'name',
|
18
|
+
# 'ParentCode' => 'parent_id',
|
19
|
+
# 'IsActive' => 'active',
|
20
|
+
# 'LevelDescription' => 'classifications'
|
21
|
+
# }.freeze
|
22
|
+
# CLASSIFICATION_MAPS = {
|
23
|
+
# 'Directorate' => 'agency',
|
24
|
+
# 'Subsection' => 'sub-section',
|
25
|
+
# 'WorkUnit' => 'work-unit'
|
26
|
+
# }.freeze
|
27
|
+
#
|
28
|
+
# def process
|
29
|
+
# compare
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# private
|
33
|
+
#
|
34
|
+
# def custom_input_csv_transform(csv)
|
35
|
+
# csv.add_column('archived')
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# def custom_input_row_transform(row)
|
39
|
+
# row['archived'] = !as_boolean(row['active'])
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
module TreeDiff
|
43
|
+
include Eco::API::UseCases::GraphQL::Samples::Location::Service::TreeToList
|
44
|
+
|
45
|
+
require_relative 'tree_diff/convertible'
|
46
|
+
include Convertible
|
47
|
+
|
48
|
+
def process
|
49
|
+
compare
|
50
|
+
end
|
51
|
+
|
52
|
+
def compare
|
53
|
+
comparer.tap do |cmp|
|
54
|
+
puts comparer.diffs_details if print_diff_details? && cmp.diffs?
|
55
|
+
log(:info) { cmp.diffs_summary }
|
56
|
+
sleep(5)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def comparer(source_1 = live_nodes_list, source_2 = file_nodes_list)
|
61
|
+
@comparer ||= nodes_diff_class.new(
|
62
|
+
source_1,
|
63
|
+
source_2,
|
64
|
+
original_tree: input_tagtree,
|
65
|
+
logger: logger
|
66
|
+
).tap do
|
67
|
+
log(:info) {
|
68
|
+
"Comparing #{source_1.count} nodes with #{source_2.count} file nodes."
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def nodes_diff_class
|
76
|
+
Eco::Data::Locations::NodeDiff::NodesDiff
|
77
|
+
end
|
78
|
+
|
79
|
+
def print_diff_details?
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate_live_nodes_file?
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
def live_nodes_list
|
88
|
+
@live_nodes_list ||= as_nodes_json(input_tagtree).tap do |list|
|
89
|
+
log(:info) { "Converted live tree to list of #{list.count} hash-nodes" }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# We accept csv input as a `:tree` or as `:nodes`
|
94
|
+
# @note
|
95
|
+
# 1. uses custom converter inherited from base case '01_tatree_to_list_case'
|
96
|
+
# - `as_nodes_json`
|
97
|
+
# 2. `org_tree` is native from `Eco::Data::Locations::NodeBase::CsvConvert`
|
98
|
+
def file_nodes_list
|
99
|
+
@file_nodes_list ||= as_nodes_json(org_tree(input_csv)).tap do |list|
|
100
|
+
log(:info) { "Converted input csv file to list of #{list.count} hash-nodes" }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/discarded.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Samples::Location::Service
|
2
|
+
module TreeToList
|
3
|
+
module Converter
|
4
|
+
module Discarded
|
5
|
+
# List of discarded node ids
|
6
|
+
DISCARDED_NODES = [].freeze
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def discarded?(tag)
|
11
|
+
self.class::DISCARDED_NODES.include?(tag)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|