peoplegroup-connectors 0.4.7 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'xml/get_organizations'
4
+ require_relative 'xml/request_one_time_payment'
5
+
6
+ module PeopleGroup
7
+ module Connectors
8
+ module Workday
9
+ module XML; end
10
+ end
11
+ end
12
+ end
@@ -1,201 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'savon'
4
- require_rel 'xml'
5
-
6
3
  module PeopleGroup
7
4
  module Connectors
8
- class Workday
9
- include XML
10
- attr_accessor :staffing_client, :compensation_client, :subdomain, :tenant
11
-
12
- # Current Workday API Version
13
- API_VERSION = 'v37.0'
14
-
15
- EmployeeNotFoundError = Class.new(StandardError)
16
-
17
- def initialize
18
- @subdomain = ENV['WORKDAY_SUBDOMAIN']
19
- @tenant = ENV['WORKDAY_TENANT']
20
- @api_base_path = "https://#{@subdomain}.#{ENV['WORKDAY_BASE_URL']}.com/ccx/service"
21
- @isu_username = ENV['WORKDAY_ISU_USERNAME']
22
- @isu_password = ENV['WORKDAY_ISU_PASSWORD']
23
-
24
- soap_debug_logs_enabled = ENV['WORKDAY_SOAP_DEBUG_LOGS'] == 'true'
25
- options = {
26
- log: soap_debug_logs_enabled,
27
- pretty_print_xml: soap_debug_logs_enabled
28
- }
29
-
30
- @staffing_client = client('Staffing', options)
31
- @compensation_client = client('Compensation', options)
32
- end
33
-
34
- def workers
35
- @workers ||= safe_report(report_name: ENV['WORKDAY_WORKERS_REPORT'])
36
- end
37
-
38
- def eligibility_status(work_email, salary_min, salary_max)
39
- params = {
40
- WorkEmail: work_email,
41
- Salary_Min: salary_min,
42
- Salary_Max: salary_max
43
- }
44
- safe_report(report_name: ENV['WORKDAY_ELIGIBILITY_REPORT'], params: params)&.first
45
- end
46
-
47
- # Grabs manager history for the specified team member or all team members.
48
- # @return <PeopleGroup::Connectors::Models::ObjectifiedHash>
49
- # keys:
50
- # employeeNumber - The team members employee number.
51
- # hireDate - The team members hireDate or transition date.
52
- # supervisorId - The team members future manager ID.
53
- # previousManagerId - The team members previous manager id.
54
- # department - The team members upcoming department
55
- # division - The team members upcoming division.
56
- # managerChangeGroup - This will always be nil.
57
- def manager_history(employee_number = nil)
58
- options = { report_name: ENV['WORKDAY_MANAGER_REPORT'] }
59
- options[:params] = { 'Employee_ID' => employee_number } unless employee_number.nil?
60
-
61
- resp = safe_report(**options).first
62
- change_group = resp[:JOB_INFO_group]
63
- reformatted = {
64
- **resp.hash.except(:JOB_INFO_group),
65
- 'transitionDate' => change_group.first['transitionDate'],
66
- 'supervisorId' => change_group.first['supervisorId'],
67
- 'jobTitle' => change_group.first['jobTitle'],
68
- 'department' => change_group.first['department'],
69
- 'division' => change_group.first['division'],
70
- 'previousManagerId' => change_group[1]['supervisorId'],
71
- 'previousJobTitle' => change_group[1]['jobTitle']
72
- }
73
-
74
- ObjectifiedHash.new(reformatted)
75
- end
76
-
77
- private
78
-
79
- # A generalized report method for Workday.
80
- # @param! [String] report_name the name of the report.
81
- # @param [Hash] params key value parameters for the report.
82
- # @return [Array<PeopleGroup::Models::ObjectifiedHash>]
83
- def report(report_name:, params: {}, nested_key: nil)
84
- url = report_url(report_name, params)
85
- p "Accessing Report: #{url}" if ENV['WORKDAY_SOAP_DEBUG_LOGS']
86
- response = retry_on_error { RestClient.get(url, basic_auth_header) }
87
- data = JSON.parse(response.body)['Report_Entry']
88
- data = data.first[nested_key] if nested_key.is_a?(String) && data.first[nested_key]
89
- data.map { |obj| XML::ObjectifiedHash.new obj }
90
- end
91
-
92
- # A wrapper for the report logic to handle any Workday specific errors.
93
- # @param [Hash] args
94
- def safe_report(**args)
95
- report(**args)
96
- rescue RestClient::InternalServerError => e
97
- pp "Encountered an error when accessing report from Workday.\nArgs: #{args}"
98
- raise e
99
- rescue StandardError => e
100
- raise e
101
- end
102
-
103
- def report_url(report_name, params)
104
- options = URI.encode_www_form({ format: 'json', **params })
105
- name = report_name.tr(' ', '_')
106
- "#{@api_base_path}/customreport2/#{@tenant}/#{@isu_username}/#{name}?#{options}"
107
- end
108
-
109
- def retry_on_error(&block)
110
- Utils.retry_on_error(errors: [Net::ReadTimeout], delay: 3, &block)
111
- end
112
-
113
- def client_from_operation(operation_name)
114
- return @staffing_client if @staffing_client.operations.include?(operation_name)
115
-
116
- @compensation_client
117
- end
118
-
119
- def call(operation_name, options = {}, &block)
120
- client = client_from_operation(operation_name)
121
- response = client.call(operation_name, { **options, **attributes }, &block)
122
- { **response.body, code: response.http.code }
123
- end
124
-
125
- def auto_paginated_call(operation_name, options = {}, &block)
126
- client = client_from_operation(operation_name)
127
- data = nil
128
- page = 1
129
-
130
- loop do
131
- response = client.call(operation_name, { **options, **attributes }, &block)
132
- # The response hash contains only one key named after the operation performed
133
- # eg. get_workers_response
134
- _operation_response_name, operation_result = response.to_hash.first
135
-
136
- page = operation_result.dig(:response_results, :page).to_i
137
- total_pages = operation_result.dig(:response_results, :total_pages).to_i
138
-
139
- # The operation data hash contains only one key named after the Workday object(s) retrieved
140
- # eg. worker
141
- _object_label, partial_data = operation_result[:response_data].first
142
-
143
- if page == 1
144
- data = partial_data
145
- else
146
- data.concat(partial_data)
147
- end
148
-
149
- break if page == total_pages
150
-
151
- page += 1
152
- end
153
-
154
- data
155
- end
156
-
157
- # Default Workday specific body paramaters
158
- # xmlns:wd - The URN of the XMLNS file
159
- # wd:version - The API Version of workday
160
- def attributes
161
- { attributes: { 'xmlns:wd' => 'urn:com.workday/bsvc', 'wd:version' => API_VERSION } }
162
- end
163
-
164
- # Returns the client based on the service.
165
- # @param Service [String] The service to use, ie: Staffing, Compensation
166
- # @param options [Hash] default options for the client.
167
- #
168
- # @return [Savon::Client] The client connected to the specified service.
169
- def client(service, options = {})
170
- client_opts = {
171
- log: false,
172
- wsse_auth: [
173
- "#{@isu_username}@#{@tenant}",
174
- @isu_password
175
- ],
176
- pretty_print_xml: false,
177
- convert_request_keys_to: :camelcase,
178
- env_namespace: :env,
179
- namespace_identifier: :wd,
180
- wsdl: "#{@api_base_path}/#{@tenant}/#{service}/#{API_VERSION}?wsdl",
181
- namespaces: {
182
- 'xmlns' => nil,
183
- 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
184
- 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
185
- 'xmlns:wsse' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
186
- },
187
- **options
188
- }
189
-
190
- Savon.client(**client_opts)
191
- end
192
-
193
- def basic_auth_header
194
- return @basic_auth_header unless @basic_auth_header.nil?
195
-
196
- base_64 = Base64.strict_encode64("#{@isu_username}:#{@isu_password}")
197
- @basic_auth_header = { Authorization: "Basic #{base_64}" }
198
- end
199
- end
5
+ module Workday; end
200
6
  end
201
7
  end
8
+
9
+ require_relative 'workday/client'
10
+ require_relative 'workday/report'
11
+ require_relative 'workday/xml'
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'require_all'
4
- require_rel 'utils'
5
- require_rel 'connectors'
3
+ require_relative 'utils'
4
+
5
+ # include the 'connectors' directory.
6
+ Dir.glob(File.join(File.dirname(__FILE__), 'connectors', '**', '*.rb')).each { |x| require(x) }
6
7
 
7
8
  module PeopleGroup
8
9
  module Connectors
9
- class Error < StandardError; end
10
+ Error = Class.new(StandardError)
10
11
  end
11
12
  end
metadata CHANGED
@@ -1,85 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peoplegroup-connectors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.7
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - lien van den steen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-11 00:00:00.000000000 Z
11
+ date: 2023-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: gitlab
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: google_drive
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '3.0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '3.0'
41
- - !ruby/object:Gem::Dependency
42
- name: slack-ruby-client
14
+ name: bamboozled-gitlab
43
15
  requirement: !ruby/object:Gem::Requirement
44
16
  requirements:
45
17
  - - "~>"
46
18
  - !ruby/object:Gem::Version
47
- version: '1.0'
19
+ version: 0.2.14
48
20
  type: :runtime
49
21
  prerelease: false
50
22
  version_requirements: !ruby/object:Gem::Requirement
51
23
  requirements:
52
24
  - - "~>"
53
25
  - !ruby/object:Gem::Version
54
- version: '1.0'
26
+ version: 0.2.14
55
27
  - !ruby/object:Gem::Dependency
56
- name: splinter-pto
28
+ name: gitlab
57
29
  requirement: !ruby/object:Gem::Requirement
58
30
  requirements:
59
- - - "~>"
31
+ - - ">="
60
32
  - !ruby/object:Gem::Version
61
- version: '0.1'
33
+ version: '0'
62
34
  type: :runtime
63
35
  prerelease: false
64
36
  version_requirements: !ruby/object:Gem::Requirement
65
37
  requirements:
66
- - - "~>"
38
+ - - ">="
67
39
  - !ruby/object:Gem::Version
68
- version: '0.1'
40
+ version: '0'
69
41
  - !ruby/object:Gem::Dependency
70
- name: bamboozled-gitlab
42
+ name: google_drive
71
43
  requirement: !ruby/object:Gem::Requirement
72
44
  requirements:
73
45
  - - "~>"
74
46
  - !ruby/object:Gem::Version
75
- version: 0.2.14
47
+ version: '3.0'
76
48
  type: :runtime
77
49
  prerelease: false
78
50
  version_requirements: !ruby/object:Gem::Requirement
79
51
  requirements:
80
52
  - - "~>"
81
53
  - !ruby/object:Gem::Version
82
- version: 0.2.14
54
+ version: '3.0'
83
55
  - !ruby/object:Gem::Dependency
84
56
  name: greenhouse_io-gitlab
85
57
  requirement: !ruby/object:Gem::Requirement
@@ -123,159 +95,33 @@ dependencies:
123
95
  - !ruby/object:Gem::Version
124
96
  version: 2.12.1
125
97
  - !ruby/object:Gem::Dependency
126
- name: require_all
98
+ name: slack-ruby-client
127
99
  requirement: !ruby/object:Gem::Requirement
128
100
  requirements:
129
101
  - - "~>"
130
102
  - !ruby/object:Gem::Version
131
- version: '3.0'
103
+ version: '1.0'
132
104
  type: :runtime
133
105
  prerelease: false
134
106
  version_requirements: !ruby/object:Gem::Requirement
135
107
  requirements:
136
108
  - - "~>"
137
109
  - !ruby/object:Gem::Version
138
- version: '3.0'
139
- - !ruby/object:Gem::Dependency
140
- name: rspec
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '3.11'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '3.11'
153
- - !ruby/object:Gem::Dependency
154
- name: rubocop
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: '0.91'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: '0.91'
167
- - !ruby/object:Gem::Dependency
168
- name: rake
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - "~>"
172
- - !ruby/object:Gem::Version
173
- version: '13.0'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - "~>"
179
- - !ruby/object:Gem::Version
180
- version: '13.0'
181
- - !ruby/object:Gem::Dependency
182
- name: gitlab-styles
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - "~>"
186
- - !ruby/object:Gem::Version
187
- version: '7.0'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - "~>"
193
- - !ruby/object:Gem::Version
194
- version: '7.0'
195
- - !ruby/object:Gem::Dependency
196
- name: rubocop-packaging
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '0.5'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - "~>"
207
- - !ruby/object:Gem::Version
208
- version: '0.5'
209
- - !ruby/object:Gem::Dependency
210
- name: rubocop-rspec
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - "~>"
214
- - !ruby/object:Gem::Version
215
- version: '1.44'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - "~>"
221
- - !ruby/object:Gem::Version
222
- version: '1.44'
223
- - !ruby/object:Gem::Dependency
224
- name: dotenv
225
- requirement: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - "~>"
228
- - !ruby/object:Gem::Version
229
- version: '2.7'
230
- type: :development
231
- prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- requirements:
234
- - - "~>"
235
- - !ruby/object:Gem::Version
236
- version: '2.7'
237
- - !ruby/object:Gem::Dependency
238
- name: simplecov
239
- requirement: !ruby/object:Gem::Requirement
240
- requirements:
241
- - - "~>"
242
- - !ruby/object:Gem::Version
243
- version: '0.21'
244
- type: :development
245
- prerelease: false
246
- version_requirements: !ruby/object:Gem::Requirement
247
- requirements:
248
- - - "~>"
249
- - !ruby/object:Gem::Version
250
- version: '0.21'
251
- - !ruby/object:Gem::Dependency
252
- name: simplecov-cobertura
253
- requirement: !ruby/object:Gem::Requirement
254
- requirements:
255
- - - "~>"
256
- - !ruby/object:Gem::Version
257
- version: '2.1'
258
- type: :development
259
- prerelease: false
260
- version_requirements: !ruby/object:Gem::Requirement
261
- requirements:
262
- - - "~>"
263
- - !ruby/object:Gem::Version
264
- version: '2.1'
110
+ version: '1.0'
265
111
  - !ruby/object:Gem::Dependency
266
- name: byebug
112
+ name: splinter-pto
267
113
  requirement: !ruby/object:Gem::Requirement
268
114
  requirements:
269
115
  - - "~>"
270
116
  - !ruby/object:Gem::Version
271
- version: '11.1'
272
- type: :development
117
+ version: '0.1'
118
+ type: :runtime
273
119
  prerelease: false
274
120
  version_requirements: !ruby/object:Gem::Requirement
275
121
  requirements:
276
122
  - - "~>"
277
123
  - !ruby/object:Gem::Version
278
- version: '11.1'
124
+ version: '0.1'
279
125
  description: Avoid repeating methods in different projects for our connectos.
280
126
  email:
281
127
  - lvandensteen@gitlab.com
@@ -291,15 +137,16 @@ files:
291
137
  - lib/peoplegroup/connectors/google_sheets.rb
292
138
  - lib/peoplegroup/connectors/greenhouse.rb
293
139
  - lib/peoplegroup/connectors/hris.rb
294
- - lib/peoplegroup/connectors/models/objectified_hash.rb
295
140
  - lib/peoplegroup/connectors/pto_roots.rb
296
141
  - lib/peoplegroup/connectors/slack.rb
297
142
  - lib/peoplegroup/connectors/version.rb
298
143
  - lib/peoplegroup/connectors/workday.rb
299
- - lib/peoplegroup/connectors/xml.rb
300
- - lib/peoplegroup/connectors/xml/get_organizations.rb
301
- - lib/peoplegroup/connectors/xml/helpers.rb
302
- - lib/peoplegroup/connectors/xml/request_one_time_payment.rb
144
+ - lib/peoplegroup/connectors/workday/client.rb
145
+ - lib/peoplegroup/connectors/workday/report.rb
146
+ - lib/peoplegroup/connectors/workday/xml.rb
147
+ - lib/peoplegroup/connectors/workday/xml/get_organizations.rb
148
+ - lib/peoplegroup/connectors/workday/xml/helpers.rb
149
+ - lib/peoplegroup/connectors/workday/xml/request_one_time_payment.rb
303
150
  - lib/peoplegroup/utils.rb
304
151
  homepage: https://gitlab.com/gitlab-com/people-group/peopleops-eng/connectors-gem
305
152
  licenses:
@@ -308,6 +155,7 @@ metadata:
308
155
  homepage_uri: https://gitlab.com/gitlab-com/people-group/peopleops-eng/connectors-gem
309
156
  source_code_uri: https://gitlab.com/gitlab-com/people-group/peopleops-eng/connectors-gem
310
157
  changelog_uri: https://gitlab.com/gitlab-com/people-group/peopleops-eng/connectors-gem
158
+ rubygems_mfa_required: 'true'
311
159
  post_install_message:
312
160
  rdoc_options: []
313
161
  require_paths:
@@ -1,105 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- module PeopleGroup
6
- module Connectors
7
- module Models
8
- # Turns a hash into a Ruby object.
9
- # This will assign the key of the hash as an instance method, and the value as the return value.
10
- # This will also convert any nested hashes into another ObjectifiedHash.
11
- class ObjectifiedHash
12
- # The raw hash prior to objectification.
13
- attr_reader :hash
14
-
15
- # The data with any objectified children.
16
- attr_reader :data
17
-
18
- def initialize(hash)
19
- @hash = hash.transform_keys(&:to_sym)
20
- @data = hash.transform_keys(&:to_s)
21
- hash.each do |key, value|
22
- if value.is_a?(Hash) && value.size.positive?
23
- value = self.class.new(value)
24
- elsif value.is_a?(Array) && value.first.is_a?(Hash)
25
- value = value.map { |data| self.class.new(data) }
26
- end
27
-
28
- instance_variable_set("@#{key}", value)
29
- @data[key.to_s] = value
30
- @hash[key.to_sym] = value
31
- self.class.send(:attr_reader, key) # rubocop:disable GitlabSecurity/PublicSend
32
- end
33
- end
34
-
35
- # Mimicks the Hash#dig method.
36
- # @param [Array] Nested keys of the object.
37
- # @return The value of the key at the nested location.
38
- def dig(*args)
39
- @data.dig(*args)
40
- end
41
-
42
- def except(*args)
43
- args.each do |key|
44
- @data.delete(key.to_s)
45
- @hash.delete(key.to_sym)
46
- instance_variable_set("@#{key}", nil)
47
- end
48
- self
49
- end
50
-
51
- # Create a new instance from an array of Hashes
52
- def self.from_array(array)
53
- array.map { |data| new(data) if data.is_a?(Hash) }
54
- end
55
-
56
- # Maintains normal json data structure
57
- def [](key)
58
- @data[key.to_s] || @hash[key.to_sym]
59
- end
60
-
61
- # Allows us to override the json data
62
- def []=(key, value)
63
- sym = key.to_sym
64
- str = key.to_s
65
- @data[str] = value if @data[str]
66
- @hash[sym] = value if @hash[sym]
67
- end
68
-
69
- # Return the stored raw hash value.
70
- def to_h
71
- @hash
72
- end
73
-
74
- # Returns the hash with keys converted to strings.
75
- def to_json # rubocop:disable Lint/ToJSON
76
- JSON.parse(hash.to_json)
77
- end
78
-
79
- # Returns both the hash and json styled keys.
80
- def keys
81
- @keys ||= @hash.keys + @data.keys
82
- end
83
-
84
- private
85
-
86
- # For handling Object.respond_to?(:method)
87
- def respond_to_missing?(method, include_private = false)
88
- super
89
- end
90
-
91
- # Enforces read only access as well as mimicking the return value of a hash.
92
- # @param method [Symbol] The method to be called.
93
- # @param args [Array] The arguments attempted to be passed into the method.
94
- # @raises [NoMethodError] if the method is attempting to set data on the object.
95
- # @return nil
96
- def method_missing(method, *args)
97
- return raise NoMethodError, "This object is read-only." if method.end_with?('=')
98
- return nil if method.start_with?('[')
99
-
100
- raise NoMethodError, "Undefined method `#{method}` called for #{inspect}"
101
- end
102
- end
103
- end
104
- end
105
- end