eco-helpers 1.4.1 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +145 -3
  3. data/LICENSE +21 -0
  4. data/eco-helpers.gemspec +11 -10
  5. data/lib/eco/api.rb +3 -0
  6. data/lib/eco/api/common.rb +5 -1
  7. data/lib/eco/api/common/base_loader.rb +54 -0
  8. data/lib/eco/api/common/class_auto_loader.rb +109 -0
  9. data/lib/eco/api/common/class_helpers.rb +33 -0
  10. data/lib/eco/api/common/class_hierarchy.rb +1 -1
  11. data/lib/eco/api/common/class_meta_basics.rb +16 -0
  12. data/lib/eco/api/common/loaders.rb +13 -0
  13. data/lib/eco/api/common/loaders/error_handler.rb +41 -0
  14. data/lib/eco/api/common/loaders/parser.rb +127 -0
  15. data/lib/eco/api/common/loaders/policy.rb +25 -0
  16. data/lib/eco/api/common/loaders/use_case.rb +40 -0
  17. data/lib/eco/api/common/people/default_parsers.rb +5 -10
  18. data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +13 -23
  19. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +20 -35
  20. data/lib/eco/api/common/people/default_parsers/date_parser.rb +15 -26
  21. data/lib/eco/api/common/people/default_parsers/freemium_parser.rb +20 -0
  22. data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +26 -0
  23. data/lib/eco/api/common/people/default_parsers/multi_parser.rb +15 -27
  24. data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +14 -19
  25. data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +31 -0
  26. data/lib/eco/api/common/people/default_parsers/send_invites_parser.rb +15 -24
  27. data/lib/eco/api/common/people/entries.rb +54 -24
  28. data/lib/eco/api/common/people/entry_factory.rb +18 -15
  29. data/lib/eco/api/common/people/person_attribute_parser.rb +29 -12
  30. data/lib/eco/api/common/people/person_entry.rb +308 -216
  31. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +5 -2
  32. data/lib/eco/api/common/people/person_parser.rb +52 -19
  33. data/lib/eco/api/common/session/base_session.rb +3 -6
  34. data/lib/eco/api/common/session/environment.rb +2 -23
  35. data/lib/eco/api/common/session/logger.rb +4 -0
  36. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +2 -0
  37. data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +9 -1
  38. data/lib/eco/api/common/version_patches/exception.rb +24 -2
  39. data/lib/eco/api/custom.rb +13 -0
  40. data/lib/eco/api/custom/error_handler.rb +20 -0
  41. data/lib/eco/api/custom/namespace.rb +7 -0
  42. data/lib/eco/api/custom/parser.rb +50 -0
  43. data/lib/eco/api/custom/policy.rb +28 -0
  44. data/lib/eco/api/custom/use_case.rb +16 -0
  45. data/lib/eco/api/error.rb +1 -0
  46. data/lib/eco/api/error/handlers.rb +10 -3
  47. data/lib/eco/api/microcases.rb +35 -0
  48. data/lib/eco/api/microcases/account_excluded.rb +24 -0
  49. data/lib/eco/api/microcases/append_usergroups.rb +19 -0
  50. data/lib/eco/api/microcases/core_excluded.rb +20 -0
  51. data/lib/eco/api/microcases/fix_default_group.rb +34 -0
  52. data/lib/eco/api/microcases/fix_filter_tags.rb +42 -0
  53. data/lib/eco/api/microcases/people_cache.rb +17 -0
  54. data/lib/eco/api/microcases/people_load.rb +59 -0
  55. data/lib/eco/api/microcases/people_refresh.rb +31 -0
  56. data/lib/eco/api/microcases/people_search.rb +65 -0
  57. data/lib/eco/api/microcases/refresh_abilities.rb +19 -0
  58. data/lib/eco/api/microcases/refresh_default_tag.rb +27 -0
  59. data/lib/eco/api/microcases/s3upload_targets.rb +39 -0
  60. data/lib/eco/api/microcases/set_account.rb +20 -0
  61. data/lib/eco/api/microcases/set_core.rb +18 -0
  62. data/lib/eco/api/microcases/set_core_with_supervisor.rb +23 -0
  63. data/lib/eco/api/microcases/set_supervisor.rb +30 -0
  64. data/lib/eco/api/microcases/strict_search.rb +19 -0
  65. data/lib/eco/api/microcases/with_each.rb +27 -0
  66. data/lib/eco/api/microcases/with_each_leaver.rb +24 -0
  67. data/lib/eco/api/microcases/with_each_present.rb +30 -0
  68. data/lib/eco/api/microcases/with_each_starter.rb +30 -0
  69. data/lib/eco/api/microcases/with_each_subordinate.rb +34 -0
  70. data/lib/eco/api/microcases/with_supervisor.rb +36 -0
  71. data/lib/eco/api/organization/people.rb +72 -35
  72. data/lib/eco/api/organization/presets_factory.rb +13 -4
  73. data/lib/eco/api/organization/presets_reference.json +9 -1
  74. data/lib/eco/api/organization/presets_values.json +4 -1
  75. data/lib/eco/api/policies.rb +11 -7
  76. data/lib/eco/api/session.rb +62 -29
  77. data/lib/eco/api/session/batch.rb +2 -45
  78. data/lib/eco/api/session/batch/base_policy.rb +7 -6
  79. data/lib/eco/api/session/batch/errors.rb +28 -4
  80. data/lib/eco/api/session/batch/feedback.rb +7 -1
  81. data/lib/eco/api/session/batch/job.rb +40 -23
  82. data/lib/eco/api/session/batch/jobs.rb +9 -4
  83. data/lib/eco/api/session/batch/jobs_groups.rb +1 -1
  84. data/lib/eco/api/session/batch/request_stats.rb +95 -58
  85. data/lib/eco/api/session/batch/status.rb +35 -31
  86. data/lib/eco/api/session/config.rb +106 -44
  87. data/lib/eco/api/session/config/api.rb +132 -7
  88. data/lib/eco/api/session/config/apis.rb +24 -25
  89. data/lib/eco/api/session/config/logger.rb +2 -2
  90. data/lib/eco/api/session/config/post_launch.rb +1 -1
  91. data/lib/eco/api/session/config/workflow.rb +8 -7
  92. data/lib/eco/api/usecases.rb +47 -33
  93. data/lib/eco/api/usecases/backup/append_usergroups_case.rb +36 -0
  94. data/lib/eco/api/usecases/backup/create_case.rb +104 -0
  95. data/lib/eco/api/usecases/backup/create_details_case.rb +31 -0
  96. data/lib/eco/api/usecases/backup/create_details_with_supervisor_case.rb +48 -0
  97. data/lib/eco/api/usecases/backup/hris_case.rb +124 -0
  98. data/lib/eco/api/usecases/backup/set_default_tag_case.rb +49 -0
  99. data/lib/eco/api/usecases/backup/set_supervisor_case.rb +41 -0
  100. data/lib/eco/api/usecases/backup/transfer_account_case.rb +90 -0
  101. data/lib/eco/api/usecases/backup/update_case.rb +112 -0
  102. data/lib/eco/api/usecases/backup/update_details_case.rb +64 -0
  103. data/lib/eco/api/usecases/backup/upsert_case.rb +114 -0
  104. data/lib/eco/api/usecases/base_case.rb +2 -0
  105. data/lib/eco/api/usecases/base_io.rb +3 -3
  106. data/lib/eco/api/usecases/default_cases.rb +23 -53
  107. data/lib/eco/api/usecases/default_cases/append_usergroups_case.rb +10 -31
  108. data/lib/eco/api/usecases/default_cases/change_email_case.rb +23 -47
  109. data/lib/eco/api/usecases/default_cases/codes_to_tags_case.rb +56 -43
  110. data/lib/eco/api/usecases/default_cases/create_case.rb +15 -101
  111. data/lib/eco/api/usecases/default_cases/create_details_case.rb +11 -26
  112. data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +12 -43
  113. data/lib/eco/api/usecases/default_cases/delete_sync_case.rb +11 -0
  114. data/lib/eco/api/usecases/default_cases/delete_trans_case.rb +14 -0
  115. data/lib/eco/api/usecases/default_cases/email_as_id_case.rb +10 -21
  116. data/lib/eco/api/usecases/default_cases/hris_case.rb +23 -120
  117. data/lib/eco/api/usecases/default_cases/new_email_case.rb +10 -23
  118. data/lib/eco/api/usecases/default_cases/new_id_case.rb +11 -25
  119. data/lib/eco/api/usecases/default_cases/new_id_case0.rb +14 -0
  120. data/lib/eco/api/usecases/default_cases/org_data_convert_case.rb +83 -0
  121. data/lib/eco/api/usecases/default_cases/refresh_abilities_case.rb +30 -0
  122. data/lib/eco/api/usecases/default_cases/refresh_case.rb +7 -20
  123. data/lib/eco/api/usecases/default_cases/reinvite_sync_case.rb +11 -0
  124. data/lib/eco/api/usecases/default_cases/reinvite_trans_case.rb +17 -0
  125. data/lib/eco/api/usecases/default_cases/remove_account_sync_case.rb +11 -0
  126. data/lib/eco/api/usecases/default_cases/remove_account_trans_case.rb +17 -0
  127. data/lib/eco/api/usecases/default_cases/reset_landing_page_case.rb +9 -19
  128. data/lib/eco/api/usecases/default_cases/restore_db_case.rb +92 -0
  129. data/lib/eco/api/usecases/default_cases/set_default_tag_case.rb +32 -40
  130. data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +15 -33
  131. data/lib/eco/api/usecases/default_cases/switch_supervisor_case.rb +66 -57
  132. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +36 -44
  133. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +40 -55
  134. data/lib/eco/api/usecases/default_cases/transfer_account_case.rb +264 -84
  135. data/lib/eco/api/usecases/default_cases/update_case.rb +15 -109
  136. data/lib/eco/api/usecases/default_cases/update_details_case.rb +14 -61
  137. data/lib/eco/api/usecases/default_cases/upsert_case.rb +16 -111
  138. data/lib/eco/api/usecases/use_case_io.rb +9 -9
  139. data/lib/eco/cli/config.rb +10 -2
  140. data/lib/eco/cli/config/default.rb +2 -1
  141. data/lib/eco/cli/config/default/input_filters.rb +58 -0
  142. data/lib/eco/cli/config/default/options.rb +60 -25
  143. data/lib/eco/cli/config/default/people.rb +4 -4
  144. data/lib/eco/cli/config/default/people_filters.rb +108 -0
  145. data/lib/eco/cli/config/default/usecases.rb +69 -32
  146. data/lib/eco/cli/config/default/workflow.rb +37 -27
  147. data/lib/eco/cli/config/filters.rb +50 -0
  148. data/lib/eco/cli/config/filters/input_filters.rb +29 -0
  149. data/lib/eco/cli/config/filters/people_filters.rb +29 -0
  150. data/lib/eco/cli/config/help.rb +49 -0
  151. data/lib/eco/cli/config/options_set.rb +17 -1
  152. data/lib/eco/cli/config/use_cases.rb +79 -53
  153. data/lib/eco/cli/scripting.rb +10 -2
  154. data/lib/eco/cli/scripting/args_helpers.rb +25 -15
  155. data/lib/eco/cli/scripting/argument.rb +1 -0
  156. data/lib/eco/cli/scripting/arguments.rb +1 -1
  157. data/lib/eco/csv.rb +8 -3
  158. data/lib/eco/csv/table.rb +1 -1
  159. data/lib/eco/data/crypto/encryption.rb +3 -0
  160. data/lib/eco/data/files/helpers.rb +6 -1
  161. data/lib/eco/language/match.rb +19 -9
  162. data/lib/eco/language/match_modifier.rb +13 -5
  163. data/lib/eco/language/models/collection.rb +77 -56
  164. data/lib/eco/language/models/parser_serializer.rb +39 -15
  165. data/lib/eco/version.rb +1 -1
  166. metadata +149 -63
  167. data/lib/eco/api/session/task.rb +0 -175
  168. data/lib/eco/api/usecases/default_case.rb +0 -19
  169. data/lib/eco/api/usecases/default_cases/delete_case.rb +0 -32
  170. data/lib/eco/api/usecases/default_cases/recover_db_case.rb +0 -98
  171. data/lib/eco/api/usecases/default_cases/refresh_presets_case.rb +0 -26
  172. data/lib/eco/api/usecases/default_cases/reinvite_case.rb +0 -41
  173. data/lib/eco/api/usecases/default_cases/remove_account_case.rb +0 -38
  174. data/lib/eco/cli/config/default/filters.rb +0 -70
  175. data/lib/eco/cli/config/people_filters.rb +0 -38
@@ -2,7 +2,7 @@ module Eco
2
2
  module API
3
3
  class Session
4
4
  class Batch
5
- # Helper object linked to a `batch status`
5
+ # Helper object linked to a `Batch::Status`. Its aim is to manage the errors of the batch status.
6
6
  class Errors
7
7
 
8
8
  # @attr_reader status [Eco::API::Session::Batch::Status] `batch status` this `Errors` object is associated to.
@@ -14,6 +14,8 @@ module Eco
14
14
  @status = status
15
15
  end
16
16
 
17
+ # @!group Status object shortcuts
18
+
17
19
  # @see [Eco::API::Session::Batch::Status#queue]
18
20
  def queue
19
21
  status.queue
@@ -24,6 +26,7 @@ module Eco
24
26
  status.method
25
27
  end
26
28
 
29
+ # @param (see Eco::API::Session::Batch::Status#to_index)
27
30
  # @see [Eco::API::Session::Batch::Status#to_index]
28
31
  def to_index(*args)
29
32
  status.to_index(*args)
@@ -37,6 +40,9 @@ module Eco
37
40
  def logger
38
41
  status.logger
39
42
  end
43
+ # @!endgroup
44
+
45
+ # @!group Pure errors helper methods
40
46
 
41
47
  # Was there any _Sever_ (reply) **error** as a result of this batch?
42
48
  # @return [Boolean] `true` if any of the queried _entries_ got an unsuccessful `Ecoportal::API::Common::BatchResponse`
@@ -44,6 +50,11 @@ module Eco
44
50
  queue.any? {|query| !status[query].success?}
45
51
  end
46
52
 
53
+ # @return [Integer] the number of `entries` that got error.
54
+ def count
55
+ entries.length
56
+ end
57
+
47
58
  # Input entries that got **error** response from the _Server_.
48
59
  # @raise [Exception] if there are elements of the final `queue` that did not get response
49
60
  # @note discards those that did not get _response_ from the Server (so those that were not queried)
@@ -67,6 +78,11 @@ module Eco
67
78
  end.compact
68
79
  end
69
80
 
81
+ # For all the `entries` with errors generates a `Hash` object
82
+ # @return [Array<Hash>] where each `Hash` has
83
+ # 1. `:type` -> the error type
84
+ # 2. `:err` -> the error `class` of that `:type`
85
+ # 3. `:entry` -> the entry that generated the error
70
86
  def errors
71
87
  entries.each_with_object([]) do |entry, arr|
72
88
  if body = status[entry].body
@@ -83,6 +99,9 @@ module Eco
83
99
  end
84
100
  end
85
101
 
102
+ # Groups `entries` with error `type`
103
+ # @return [Hash] where each `key` is a `type` **error** and each value is
104
+ # an `Array` of `entries` that got that error
86
105
  def by_type
87
106
  errors.group_by do |h|
88
107
  h[:type]
@@ -90,11 +109,13 @@ module Eco
90
109
  arr.map {|h| h[:entry]}
91
110
  end
92
111
  end
112
+ # @!endgroup
93
113
 
94
- def count
95
- entries.length
96
- end
114
+ # @!group Messaging methods
97
115
 
116
+ # Generates a `String` specifying the error for the entry `key`.
117
+ # @param key [Integer, Ecoportal::API::V1::Person]
118
+ # @return [String] the error description.
98
119
  def str(key)
99
120
  msg = ""
100
121
  unless status.success?(key)
@@ -107,6 +128,8 @@ module Eco
107
128
  msg
108
129
  end
109
130
 
131
+ # Sorts the entries that got server error by error `type` and generates the error messages.
132
+ # @return [Array<String>] the errors messages.
110
133
  def strs
111
134
  by_type.values.flatten(1).each_with_object([]) do |query, msgs|
112
135
  msgs.push(str(query))
@@ -136,6 +159,7 @@ module Eco
136
159
  logger.info("There were no errors for the current batch '#{method}'!! ;)")
137
160
  end
138
161
  end
162
+ # @!endgroup
139
163
 
140
164
  private
141
165
 
@@ -13,6 +13,8 @@ module Eco
13
13
  @job = job
14
14
  end
15
15
 
16
+ # @!group Job shortcut methods
17
+
16
18
  # @see Eco::API::Session::Batch::Job#name
17
19
  # @return [String] name of the `batch job`
18
20
  def name
@@ -38,6 +40,9 @@ module Eco
38
40
  def job_requests
39
41
  job.requests
40
42
  end
43
+ # @!endgroup
44
+
45
+ # @!group Pure feedback methods
41
46
 
42
47
  # Slightly modifies the behaviour of `Ecoportal::API::Common::BaseModel#as_update`, so schema details fields show the `alt_id`
43
48
  # @note for better feedback
@@ -88,7 +93,7 @@ module Eco
88
93
  # Generates the lines of feedback of the current requests
89
94
  # @note if `requests` is not provided, it uses the last requests of the parent `Batch::Job` `job`
90
95
  # @param requests [Enumerable<Hash>] raw requests as they would be sent to the _Server_
91
- # @param max_charts [Integer] the max number of characters for the current feedback message
96
+ # @param max_chars [Integer] the max number of characters for the current feedback message
92
97
  # @param only_stats [Boolean] whether or not should only include a brief summary of stats
93
98
  # @return [String] the feedback message
94
99
  def generate(requests = nil, max_chars: 800, only_stats: false)
@@ -117,6 +122,7 @@ module Eco
117
122
  end
118
123
  end.join("\n")
119
124
  end
125
+ # @!endgroup
120
126
 
121
127
  private
122
128
 
@@ -7,7 +7,7 @@ module Eco
7
7
  # @attr_reader sets [Array<Symbol>] the parts of the person model this batch is supposed to affect
8
8
  # @attr_reader usecase [Eco::API::UseCases::UseCase, nil] when provided: `usecase` that generated this `batch job`
9
9
  # @attr_reader status [Eco::API::Session::Batch::Status] if launched: the `status` of the `batch`
10
- # @attr_reader feedback [Eco::API::Session::Batch::Feedback] helper class for feedback and decision making
10
+ # @attr_reader feedback [Eco::API::Session::Batch::Feedback] helper class for feedback and end-user decision making
11
11
  class Job < Eco::API::Common::Session::BaseSession
12
12
  @types = [:get, :create, :update, :delete]
13
13
  @sets = [:core, :details, :account]
@@ -29,10 +29,11 @@ module Eco
29
29
  attr_reader :usecase
30
30
  attr_reader :status, :feedback
31
31
 
32
- # @param e [Eco::API::Common::Session::Environment] requires a session environment, as any child of `Eco::API::Common::Session::BaseSession`
32
+ # @param e [Eco::API::Common::Session::Environment] requires a session environment, as any child of `Eco::API::Common::Session::BaseSession`.
33
33
  # @param name [String] the name of this `batch job`
34
- # @param type [Symbol] a valid batch operation
35
- # @param usecase [Eco::API::UseCases::UseCase, nil] when provided: `usecase` that generated this `batch job`
34
+ # @param type [Symbol] a valid batch operation.
35
+ # @param usecase [Eco::API::UseCases::UseCase, nil] when provided: `usecase` that generated this `batch job`.
36
+ # This is necessary to know the `options` used to run the usecase, which could modify the `Batch::Job` behviour.
36
37
  def initialize(e, name:, type:, sets:, usecase: nil)
37
38
  raise "A name is required to refer a job. Given: #{name}" if !name
38
39
  raise "Type should be one of #{self.class.types}. Given: #{type}" unless self.class.valid_type?(type)
@@ -61,10 +62,21 @@ module Eco
61
62
  # * this job will not be linked to the `Batch::Jobs` model of the current session
62
63
  # * mostly used for error_handlers
63
64
  # @return [Eco::API::Session::Batch::Job]
64
- def dup(name = "ad-hoc:job-from:#{self.name}", usecase: nil)
65
+ def dup(name = "ad-hoc:job-from:#{self.name}", usecase: self.usecase)
65
66
  self.class.new(enviro, name: name, type: type, sets: sets, usecase: usecase)
66
67
  end
67
68
 
69
+ # @return [Eco::API::Session::Batch::Jobs] group of subjobs of this `Batch::Job`
70
+ def subjobs
71
+ @subjobs ||= Eco::API::Session::Batch::Jobs.new(enviro, name: "childs-of:#{self.name}")
72
+ end
73
+
74
+ def subjobs_add(name = "ad-hoc:job-from:#{self.name}", usecase: self.usecase, &block)
75
+ dup(name, usecase: usecase).tap do |subjob|
76
+ subjobs.add(subjob, &block)
77
+ end
78
+ end
79
+
68
80
  # @return [Boolean] `true` if the current batch job is a result of an error_handler
69
81
  def error_handler?
70
82
  usecase? && usecase.is_a?(Eco::API::Error::Handler)
@@ -81,11 +93,11 @@ module Eco
81
93
  end
82
94
 
83
95
  # Adds an entry(ies) to the job queue.
84
- # @param entry [Person, Enumberable<Person>] the person(s) we want to update, carrying the changes to be done.
96
+ # @param entry [Ecoportal::API::V1::Person, Enumberable<Person>] the person(s) we want to update, carrying the changes to be done.
85
97
  # @param unique [Boolean] specifies if repeated entries should be avoided in the queue.
86
98
  # @yield [person] callback before launching the batch job request against the server.
87
- # @yeldparam param [Person] current person object that that should be treated by the callback before launching the batch.
88
- # @return [Void]
99
+ # @yieldparam param [Person] current person object that that should be treated by the callback before launching the batch.
100
+ # @return [Eco::API::Session::Batch::Job] this `Batch::Job`.
89
101
  def add(entry, unique: true, &block)
90
102
  case entry
91
103
  when Enumerable
@@ -99,13 +111,9 @@ module Eco
99
111
  end
100
112
  end
101
113
  end
114
+ self
102
115
  end
103
116
 
104
- #def match?(type:, sets:)
105
- # sets = [sets].flatten
106
- # type == self.type && (sets.order == self.sets.order)
107
- #end
108
-
109
117
  # @return [Boolean] has been this `batch job` launched?
110
118
  def pending?
111
119
  @pending
@@ -140,21 +148,21 @@ module Eco
140
148
  # Processes the `queue` and, unless `simulate` is `true`, launches against the server:
141
149
  # 1. pre_processes the queue obtaining the `requests`:
142
150
  # - if the entries of `queue` got pending _callbacks_ (delayed changes), it processes them
143
- # - unless type == `:create`: if there's a defined `api_excluded` _callback_ it calls it (see `Eco::API::Session::Config::People#api_excluded`)
151
+ # - unless type == `:create`: if there's a defined `api_excluded` _callback_ it calls it (see {Eco::API::Session::Config::People#api_excluded})
144
152
  # - transforms the result to a `Eco::API::Organization::People` object
145
- # - if there are `api policies` defined, it passes the entries through them in order (see `Eco::API::Session::Config#policies`)
153
+ # - if there are `api policies` defined, it passes the entries through them in order (see {Eco::API::Session::Config#policies})
146
154
  # - this step is **skipped** if the option `-skip-api-policies` was used in the command line
147
155
  # - at this point all the transformations have taken place...
148
156
  # - only include the entries that, after all above, still hold pending changes (`!as_update.empty?`) to be launched as update
149
157
  # 2. pre launch checks against the `requests`:
150
158
  # - it generates `stats` (`Eco::API::Session::Batch::RequestStats`) out of the requests
151
- # - if there is a batch policy declared for the current job `type`, it checks compliance against `stats` (`Eco::API::Session::Batch::Policies`),
159
+ # - if there is a batch policy declared for the current job `type`, it checks compliance against `stats` (see {Eco::API::Session::Batch::Policies}),
152
160
  # - a non-compliant batch will stop the current session by raising an `Exception`
153
161
  # - this setp is **skipped** if the option `-skip-batch-policy` was used in the command line
154
162
  # 3. if we are **not** in `dry-run` (or `simulate`), it:
155
163
  # - backs up the raw queries (`requests`) launched to the Server, if we are **not** in `dry-run` (or `simulate`)
156
- # - **launches the batch** request against the _Server_ (see `Eco::API::Session::Batch#launch`)
157
- # - links the resulting batch `status` to this `Batch::Job` (see `Eco::API::Session::Batch::Status`)
164
+ # - **launches the batch** request against the _Server_ (see {Eco::API::Session::Batch#launch})
165
+ # - links the resulting batch `status` to this `Batch::Job` (see {Eco::API::Session::Batch::Status})
158
166
  # - prints any `errors` replied by the _Server_
159
167
  # 4. the post launch kicks in, and:
160
168
  # - for success requests, it consolidates the associated entries (see `Ecoportal::API::V1::Person#consolidate!`)
@@ -163,7 +171,6 @@ module Eco
163
171
  def launch(simulate: false)
164
172
  pqueue = processed_queue
165
173
  @requests = pqueue.map {|e| as_update(e)}
166
-
167
174
  pre_checks(requests, simulate: simulate)
168
175
 
169
176
  unless simulate
@@ -177,8 +184,8 @@ module Eco
177
184
  end
178
185
  end
179
186
 
180
- unless requests.empty?
181
- logger.info("--- simulate mode (dry-run) -- job '#{name}' -- this would have launched #{type.to_s.upcase}") if simulate
187
+ unless requests.empty? || !simulate
188
+ logger.info("--- simulate mode (dry-run) -- job '#{name}' -- this would have launched #{type.to_s.upcase}")
182
189
  end
183
190
 
184
191
  post_launch(queue: pqueue, simulate: simulate)
@@ -186,7 +193,10 @@ module Eco
186
193
  return status
187
194
  end
188
195
 
189
- # Provides a text summary of the current status
196
+ # Provides a text summary of the current status including:
197
+ # 1. stats of the changes introduced by the job in the different parts of the person model
198
+ # 2. if the job is compliant with the batch policy
199
+ # 3. error messages in case they were errors from the server
190
200
  # @note if `launch` was not invoked, it specifies so
191
201
  # @return [String] the summary
192
202
  def summary
@@ -225,6 +235,7 @@ module Eco
225
235
  full_queue.select {|entry| !excluded.call(entry, session, options, self)}
226
236
  end
227
237
 
238
+ # Applies the changes introduced by api policies
228
239
  def apply_policies(pre_queue)
229
240
  people(pre_queue).tap do |entries|
230
241
  policies = session.config.policies
@@ -234,12 +245,14 @@ module Eco
234
245
  end
235
246
  end
236
247
 
248
+ # Shortcut to get the batch (belt) policy
237
249
  def batch_policy
238
250
  unless options.dig(:skip, :batch_policy)
239
251
  @batch_policy ||= session.config.batch_policies[self.type]
240
252
  end
241
253
  end
242
254
 
255
+ # Checks batch policy compliance and displays the feedback on request stats
243
256
  def pre_checks(requests, simulate: false)
244
257
  only_stats = options.dig(:feedback, :only_stats)
245
258
  max_chars = simulate ? 2500 : 800
@@ -257,6 +270,9 @@ module Eco
257
270
  end
258
271
  end
259
272
 
273
+ # after launched to the server
274
+ # 1. `consolidate!` person model if succeeded (person.doc -> person.original_doc)
275
+ # 2. if there were errors: launch specific error handlers if they are defined for the type of error
260
276
  def post_launch(queue: [], simulate: false)
261
277
  if !simulate && status
262
278
  status.queue.map do |entry|
@@ -271,7 +287,7 @@ module Eco
271
287
  err_types = status.errors.by_type
272
288
  handlers.each do |handler|
273
289
  if entries = err_types[handler.name]
274
- handler_job = self.dup("#{self.name} => #{handler.name}", usecase: handler)
290
+ handler_job = subjobs_add("#{self.name} => #{handler.name}", usecase: handler)
275
291
  handler.launch(people: people(entries), session: session, options: options, job: handler_job)
276
292
  handler_job.launch(simulate: simulate)
277
293
  end
@@ -284,6 +300,7 @@ module Eco
284
300
  end
285
301
  end
286
302
 
303
+ # Keep a copy of the requests for future reference
287
304
  def backup_update(requests)
288
305
  dir = config.people.requests_folder
289
306
  file = File.join(dir, "#{type}_data.json")
@@ -25,7 +25,7 @@ module Eco
25
25
  count == 0
26
26
  end
27
27
 
28
- def each(params: {}, &block)
28
+ def each(&block)
29
29
  return to_enum(:each) unless block
30
30
  items.each(&block)
31
31
  end
@@ -49,15 +49,20 @@ module Eco
49
49
  end
50
50
  end
51
51
 
52
- def new(name, type:, sets:, usecase: nil)
52
+ def new(name, type:, sets:, usecase: nil, &block)
53
53
  fatal "Can't create job named '#{name}' because it already exists." if exists?(name)
54
54
 
55
55
  Batch::Job.new(enviro, name: name, type: type, sets: sets, usecase: usecase).tap do |job|
56
- @jobs[name] = job
57
- @callbacks[job] = Proc.new if block_given?
56
+ add(job, &block)
58
57
  end
59
58
  end
60
59
 
60
+ def add(job)
61
+ fatal "Expected Eco::API::Session::Batch::Job object. Given #{job.class}" unless job.is_a?(Eco::API::Session::Batch::Job)
62
+ @jobs[job.name] = job
63
+ @callbacks[job] = Proc.new if block_given?
64
+ end
65
+
61
66
  def pending?
62
67
  any? {|job| job.pending?}
63
68
  end
@@ -41,7 +41,7 @@ module Eco
41
41
  count == 0
42
42
  end
43
43
 
44
- def each(params: {}, &block)
44
+ def each(&block)
45
45
  return to_enum(:each) unless block
46
46
  items.each(&block)
47
47
  end
@@ -5,9 +5,10 @@ module Eco
5
5
  # @attr_reader count [Integer] the total number of requests
6
6
  # @attr_reader stats [Hash] plain `Hash` with the number of requests that include an attribute
7
7
  class RequestStats
8
- CORE_ATTRS = Eco::API::Common::People::PersonParser::CORE_ATTRS
9
- ACCOUNT_ATTRS = (Eco::API::Common::People::PersonParser::ACCOUNT_ATTRS + ["permissions_custom"]).uniq
10
- DETAILS_ATTRS = ["fields"]
8
+ CORE_ATTRS = Eco::API::Common::People::PersonParser::CORE_ATTRS
9
+ ACCOUNT_ATTRS = (Eco::API::Common::People::PersonParser::ACCOUNT_ATTRS + ["permissions_custom"]).uniq
10
+ DETAILS_ATTRS = ["fields"]
11
+ BLANKED_PREFIX = "blanked_"
11
12
 
12
13
  class << self
13
14
 
@@ -17,7 +18,10 @@ module Eco
17
18
 
18
19
  def core_attrs(stats: false, all: false)
19
20
  CORE_ATTRS.dup.tap do |attrs|
20
- attrs.unshift("core") if stats || all
21
+ if stats || all
22
+ attrs.unshift("core")
23
+ attrs.concat(blank_attrs(CORE_ATTRS))
24
+ end
21
25
  end
22
26
  end
23
27
 
@@ -26,6 +30,7 @@ module Eco
26
30
  if stats || all
27
31
  attrs.unshift("account_remove")
28
32
  attrs.unshift("account") if all
33
+ attrs.concat(blank_attrs(ACCOUNT_ATTRS))
29
34
  end
30
35
  end
31
36
  end
@@ -39,6 +44,20 @@ module Eco
39
44
  end
40
45
  end
41
46
 
47
+ def blanked_prefix(attr = nil)
48
+ @blanked_prefix ||= BLANKED_PREFIX
49
+ return @blanked_prefix unless attr
50
+ "#{blanked_prefix}#{attr}"
51
+ end
52
+
53
+ def blanked_prefix=(value)
54
+ @blanked_prefix = value || blanked_prefix
55
+ end
56
+
57
+ def blank_attrs(attrs)
58
+ attrs.map {|attr| "#{blanked_prefix}#{attr}"}
59
+ end
60
+
42
61
  end
43
62
 
44
63
  attr_reader :type, :count
@@ -54,17 +73,22 @@ module Eco
54
73
  @stats
55
74
  end
56
75
 
57
- def core_attrs
58
- @core_attrs ||= self.class.core_attrs
59
- end
76
+ def message(percent: false)
77
+ key_val_delimiter = ": "; attr_delimiter = " ++ "
78
+ pairs_to_line = Proc.new do |pairs|
79
+ pairs.map do |p|
80
+ [p.first.to_s, "#{p.last.to_s}" + (percent ? "%" : "")].join(key_val_delimiter)
81
+ end.join(attr_delimiter)
82
+ end
60
83
 
61
- def account_attrs
62
- @account_attrs ||= self.class.account_attrs
84
+ lines = []
85
+ lines << pairs_to_line.call(core_pairs(percent: percent))
86
+ lines << pairs_to_line.call(account_pairs(percent: percent))
87
+ lines << pairs_to_line.call(details_pairs(percent: percent))
88
+ lines.join("\n")
63
89
  end
64
90
 
65
- def details_attrs
66
- @details_attrs ||= self.class.details_attrs
67
- end
91
+ private
68
92
 
69
93
  def attr(attr, percent: false, total: count)
70
94
  i = @stats["#{attr}"]
@@ -80,52 +104,10 @@ module Eco
80
104
  attr("account", percent: percent)
81
105
  end
82
106
 
83
- def account_remove(percent: false)
84
- attr("account_remove", percent: percent)
85
- end
86
-
87
107
  def details(percent: false)
88
108
  attr("details", percent: percent)
89
109
  end
90
110
 
91
- def details_remove(percent: false)
92
- attr("details_remove", percent: percent)
93
- end
94
-
95
- def fields_average
96
- if (fields_num = attr("fields")) && (total = details) > 0
97
- (fields_num.to_f / total.to_f).round(2)
98
- end
99
- end
100
-
101
- def message(percent: false)
102
- key_val_delimiter = ": "; attr_delimiter = " ++ "
103
- pairs_to_line = Proc.new do |pairs|
104
- pairs.map do |p|
105
- [p.first.to_s, "#{p.last.to_s}" + (percent ? "%" : "")].join(key_val_delimiter)
106
- end.join(attr_delimiter)
107
- end
108
-
109
- lines = []
110
- lines << pairs_to_line.call(core_pairs(percent: percent))
111
- lines << pairs_to_line.call(account_pairs(percent: percent))
112
- lines << pairs_to_line.call(details_pairs(percent: percent))
113
- lines.join("\n")
114
- end
115
-
116
- def model
117
-
118
- end
119
-
120
- private
121
-
122
- def percentage(num, total: count)
123
- total ||= count
124
- if num
125
- (num.to_f / total * 100).round(2)
126
- end
127
- end
128
-
129
111
  def build(requests)
130
112
  Hash.new(0).tap do |stats|
131
113
  stats[type] = count
@@ -141,7 +123,12 @@ module Eco
141
123
 
142
124
  def attrs_to_stat(stats, hash, attrs)
143
125
  stats.tap do |st|
144
- attrs.each {|attr| st[attr] += 1 if hash.key?(attr)}
126
+ attrs.each do |attr|
127
+ if hash.key?(attr)
128
+ st[attr] += 1
129
+ st[blanked_prefix(attr)]+= 1 if blanked_value?(hash[attr])
130
+ end
131
+ end
145
132
  end
146
133
  end
147
134
 
@@ -175,12 +162,13 @@ module Eco
175
162
  end
176
163
 
177
164
  def core_pairs(percent: false)
178
- [["core", core(percent: percent)]] + pairs(core_attrs, percent: percent, total: core)
165
+ cattrs = core_attrs + blank_attrs(core_attrs)
166
+ [["core", core(percent: percent)]] + pairs(cattrs, percent: percent, total: core)
179
167
  end
180
168
 
181
169
  def account_pairs(percent: false)
182
- aattrs = ["account_remove"] + account_attrs
183
- [["account", account(percent: percent)]] + pairs(aattrs, percent: percent, total: account)
170
+ aattrs = ["account_remove"] + account_attrs + blank_attrs(account_attrs)
171
+ [["account", account(percent: percent)]] + pairs(aattrs, percent: percent, total: account)
184
172
  end
185
173
 
186
174
  def details_pairs(percent: false)
@@ -188,6 +176,55 @@ module Eco
188
176
  details_pairs += [["fields", fields_average]] if attr("fields") && fields_average
189
177
  details_pairs += pairs(["details_remove"], percent: percent, total: details)
190
178
  end
179
+
180
+ def fields_average
181
+ if (fields_num = attr("fields")) && (total = details) > 0
182
+ (fields_num.to_f / total.to_f).round(2)
183
+ end
184
+ end
185
+
186
+ def percentage(num, total: count)
187
+ total ||= count
188
+ if num
189
+ (num.to_f / total * 100).round(2)
190
+ end
191
+ end
192
+
193
+ def core_attrs
194
+ @core_attrs ||= self.class.core_attrs
195
+ end
196
+
197
+ def account_attrs
198
+ @account_attrs ||= self.class.account_attrs
199
+ end
200
+
201
+ def details_attrs
202
+ @details_attrs ||= self.class.details_attrs
203
+ end
204
+
205
+ def blank_attrs(attrs)
206
+ self.class.blank_attrs(attrs)
207
+ end
208
+
209
+ def blanked_prefix(attr = nil)
210
+ self.class.blanked_prefix(attr)
211
+ end
212
+
213
+ def blanked_value?(value)
214
+ case value
215
+ when nil
216
+ true
217
+ when false
218
+ true
219
+ when Numeric
220
+ value == 0
221
+ when Array
222
+ value.compact.empty?
223
+ when String
224
+ value.to_s.strip.empty?
225
+ end
226
+ end
227
+
191
228
  end
192
229
  end
193
230
  end