bobhr 0.5.33 → 0.5.34

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a51b60f5c4ce454ba34104e17e5d7c9043b60a49ade8878ced0f3464cb6dde28
4
- data.tar.gz: 96aff1182f54706bb5cb4fde06d94abb665f1ad361333df941a7a6e9a305c020
3
+ metadata.gz: ebc2afc6969d6c4e35d6ece1fd8c3b47971ef5f42903b64dc02ba969381cca06
4
+ data.tar.gz: bdc0fa6014ddea81eb2c7f766163226d840dc960fe492ea65a9cf386f5f1fda8
5
5
  SHA512:
6
- metadata.gz: 91687da4b837df04d75160c36b5057c8f4809df7cea5a16ddcb15a793e775003370cde593afa787acbbe1e6d9d8fcc95756464b15c9ea1745e7059fc3bb91d84
7
- data.tar.gz: cf7f4bfbd9e63dcb7d7029a62fb7d947df61e55fde6a961f0819dbc7836bac10fc332b5754a5f3ec1c46cc51a9af57231b08036c779e7ceccffe0bd14abc051f
6
+ metadata.gz: 5af1f851e13b3ccdb3493729ac942c04383deabccb45bd9572627d4b728e9272c80084099f7b52a41e5c75b77291fb53c65d9de08a45a98216070609a35ed503
7
+ data.tar.gz: 2b578ba593f6884f99a71b7d61de8ca4267be6e1498d0cc615f3ebb132f64a81eabf9b8dc0b9f9e1e400a5b175ed129d2bcad57d86f9cf22291fdc56b68a9bc1
data/lib/bob/api/api.rb CHANGED
@@ -13,78 +13,62 @@ module Bob
13
13
 
14
14
  def self.get(endpoint, params = {}, csv_response: false)
15
15
  url = build_url(endpoint, params)
16
- response = RestClient.get(url, authorization_header)
16
+ response = RestClient.get(url, headers)
17
17
  return create_csv(response.body) if csv_response
18
18
 
19
19
  JSON.parse(response.body)
20
20
  end
21
21
 
22
- def self.post(endpoint, params = {}, use_api_key: false)
22
+ def self.post(endpoint, params = {})
23
23
  url = build_url(endpoint)
24
24
  response = RestClient.post(
25
25
  url,
26
26
  params.to_json,
27
- authorization_header(use_api_key: use_api_key).merge(content_headers)
27
+ headers
28
28
  )
29
29
  rescue RestClient::BadRequest => e
30
30
  p e
31
- response.code
31
+ response.code if response.try(:code)
32
32
  end
33
33
 
34
34
  def self.post_media(endpoint, params = {})
35
35
  url = build_url(endpoint)
36
- response = RestClient.post(url, params.to_json, authorization_header.merge(content_headers))
36
+ response = RestClient.post(url, params.to_json, headers)
37
37
  response.code
38
38
  end
39
39
 
40
- def self.post_file(endpoint, file_path) # rubocop:disable Metrics/MethodLength
40
+ def self.post_file(endpoint, file_path)
41
41
  url = build_url(endpoint)
42
42
  payload = {
43
43
  multipart: true,
44
44
  file: File.new(file_path)
45
45
  }
46
46
 
47
- headers = {
48
- Accept: 'application/json',
49
- 'Content-Type': 'multipart/form-data',
50
- Authorization: "Basic #{Base64.strict_encode64("#{Bob.access_user_name}:#{Bob.access_token}")}"
51
- }
52
- response = RestClient.post(url, payload, headers)
47
+ response = RestClient.post(url, payload, headers.merge({ 'Content-Type': 'multipart/form-data' }))
53
48
  response.code
54
49
  end
55
50
 
56
51
  def self.delete(endpoint)
57
52
  url = build_url(endpoint)
58
- response = RestClient.delete(url, authorization_header)
53
+ response = RestClient.delete(url, headers)
59
54
  response.code
60
55
  end
61
56
 
62
- def self.put(endpoint, params = {}, use_api_key: false)
57
+ def self.put(endpoint, params = {})
63
58
  url = build_url(endpoint)
64
59
  response = RestClient.put(
65
60
  url,
66
61
  params.to_json,
67
- authorization_header(use_api_key: use_api_key).merge(content_headers)
62
+ headers
68
63
  )
69
64
  response.code
70
65
  end
71
66
 
72
- def self.authorization_header(use_api_key: false)
73
- if use_api_key
74
- {
75
- Authorization: Bob.api_key
76
- }
77
- else
78
- {
79
- Authorization: "Basic #{Base64.strict_encode64("#{Bob.access_user_name}:#{Bob.access_token}")}"
80
- }
81
- end
82
- end
83
-
84
- def self.content_headers
67
+ def self.headers
85
68
  {
86
69
  Accept: 'application/json',
87
- 'Content-Type': 'application/json'
70
+ 'Content-Type': 'application/json',
71
+ Authorization: "Basic #{Base64.strict_encode64("#{Bob.access_user_name}:#{Bob.access_token}")}"
88
72
  }
89
73
  end
90
74
 
@@ -3,13 +3,17 @@
3
3
  module Bob
4
4
  module Employee
5
5
  class CustomTables < API
6
- def self.rows(employee_id, table_id)
7
- response = get("people/custom-tables/#{employee_id}/#{table_id}")
6
+ def self.rows(employee_id, table_id, options = { includeHumanReadable: true })
7
+ response = get("people/custom-tables/#{employee_id}/#{table_id}", options)
8
8
  TableParser.new(response).rows
9
9
  end
10
10
 
11
11
  def self.add_row(employee_id, table_id, row_data)
12
- post("people/custom-tables/#{employee_id}/#{table_id}", {values: row_data})
12
+ post("people/custom-tables/#{employee_id}/#{table_id}", { values: row_data })
13
+ end
14
+
15
+ def self.update_row(employee_id, table_id, row_id, row_data)
16
+ put("people/custom-tables/#{employee_id}/#{table_id}/#{row_id}", row_data)
13
17
  end
14
18
 
15
19
  def self.remove_row(employee_id, table_id, row_id)
@@ -4,11 +4,11 @@ module Bob
4
4
  module Employee
5
5
  class Documents < API
6
6
  def self.add_public_document(employee_id, params = {})
7
- post("docs/people/#{employee_id}/shared", params, use_api_key: true)
7
+ post("docs/people/#{employee_id}/shared", params)
8
8
  end
9
9
 
10
10
  def self.add_private_document(employee_id, params = {})
11
- post("docs/people/#{employee_id}/confidential", params, use_api_key: true)
11
+ post("docs/people/#{employee_id}/confidential", params)
12
12
  end
13
13
 
14
14
  def self.upload_public_document(employee_id, file_path)
@@ -15,8 +15,7 @@ module Bob
15
15
  def self.update(employee_id, employment_entry_id, params)
16
16
  put(
17
17
  "people/#{employee_id}/employment/#{employment_entry_id}",
18
- params,
19
- use_api_key: true
18
+ params
20
19
  )
21
20
  end
22
21
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bob
4
+ module Employee
5
+ class Payroll < API
6
+ # Fetches all payroll histories.
7
+ # @param params [Hash] Optional parameters for the request.
8
+ # @return [Array<PayrollHistory>] An array of payroll history records.
9
+ def self.all(params = { showInactive: false })
10
+ response = get('payroll/history', params)
11
+ PayrollParser.new(response).payroll_histories
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,7 +4,7 @@ module Bob
4
4
  module Employee
5
5
  class TimeOff < API
6
6
  def self.balance(employee_id:, policy_type:, date:)
7
- response = get("timeoff/employees/#{employee_id}/balance", { policyType: policy_type, date: date })
7
+ response = get("timeoff/employees/#{employee_id}/balance", { policyType: policy_type, date: })
8
8
  BaseParser.new(response).fields
9
9
  end
10
10
  end
@@ -15,8 +15,7 @@ module Bob
15
15
  def self.update(employee_id, work_history_id, params)
16
16
  put(
17
17
  "people/#{employee_id}/work/#{work_history_id}",
18
- params,
19
- use_api_key: true
18
+ params
20
19
  )
21
20
  end
22
21
 
@@ -11,17 +11,43 @@ require_relative 'employee/lifecycle_history'
11
11
  require_relative 'employee/time_off'
12
12
  require_relative 'employee/employment_history'
13
13
  require_relative 'employee/custom_tables'
14
+ require_relative 'employee/payroll'
14
15
 
15
16
  module Bob
16
17
  class Employees < API
17
- def self.all(params = { includeHumanReadable: true })
18
- response = get('people', params)
19
- EmployeeParser.new(response).employees
18
+ DEFAULT_FIELDS = ['root.id', 'root.email', 'work.startDate', 'root.secondName', 'root.fullName', 'root.displayName',
19
+ 'work.title', 'home.privateEmail', 'work.reportsToIdInCompany', 'address.city', 'work.reportsTo.email',
20
+ 'work.manager', 'work.secondLevelManager', 'work.employeeIdInCompany', 'payroll.employment.type',
21
+ 'address.country', 'address.usaState', 'internal.lifecycleStatus', 'work.department',
22
+ 'about.socialData.linkedin'].freeze
23
+
24
+ def self.search(params = { humanReadable: 'replace' })
25
+ params[:fields] = DEFAULT_FIELDS unless params[:fields]
26
+
27
+ response = post('people/search', params)
28
+ EmployeeParser.new(JSON.parse(response)).employees
20
29
  end
21
30
 
22
- def self.all_leavers(start_date:, end_date:)
23
- all({ includeHumanReadable: true, showInactive: true }).select do |employee|
31
+ def self.find(employee_id_or_email, params = { humanReadable: 'replace' })
32
+ if params[:fields]
33
+ params[:fields] = (DEFAULT_FIELDS + params[:fields] + Bob.default_custom_fields.map do |dcf|
34
+ Bob.custom_fields[dcf][:api_field]
35
+ end).uniq
36
+ end
37
+ unless params[:fields]
38
+ params[:fields] = (DEFAULT_FIELDS + Bob.default_custom_fields.map do |dcf|
39
+ Bob.custom_fields[dcf][:api_field]
40
+ end)
41
+ end
24
42
 
43
+ response = post("people/#{employee_id_or_email}", params)
44
+ EmployeeParser.new(JSON.parse(response)).employee
45
+ end
46
+
47
+ def self.all_leavers(start_date:, end_date:)
48
+ fields = ['internal.terminationDate', 'internal.status', 'root.id', 'root.displayName', 'work.title',
49
+ 'work.reportsTo.email', 'root.email']
50
+ search({ humanReadable: 'replace', showInactive: true, fields: }).select do |employee|
25
51
  next unless employee.internal.status == 'Inactive' && employee.internal.termination_date.present?
26
52
 
27
53
  # Don't process employees that left before the period we are looking into
@@ -43,23 +69,35 @@ module Bob
43
69
  end
44
70
  end
45
71
 
46
- def self.all_people_managers(params = { includeHumanReadable: true })
47
- response = get('people', params)
48
- EmployeeParser.new(response).managers
49
- end
72
+ def self.starts_on(date = Date.current, params = { humanReadable: 'replace' })
73
+ if params[:fields]
74
+ params[:fields] = (DEFAULT_FIELDS + params[:fields] + Bob.default_custom_fields.map do |dcf|
75
+ Bob.custom_fields[dcf][:api_field]
76
+ end).uniq
77
+ end
78
+ unless params[:fields]
79
+ params[:fields] = (DEFAULT_FIELDS + Bob.default_custom_fields.map do |dcf|
80
+ Bob.custom_fields[dcf][:api_field]
81
+ end)
82
+ end
50
83
 
51
- def self.starts_on(date = Date.current.to_s, params = { includeHumanReadable: true })
52
- response = get('people', params)
53
- EmployeeParser.new(response).starters_on(date)
84
+ response = post('people/search', params)
85
+ EmployeeParser.new(JSON.parse(response)).starters_on(date)
54
86
  end
55
87
 
56
- def self.find(employee_id_or_email, params: { includeHumanReadable: true })
57
- response = get("people/#{employee_id_or_email}", params)
58
- EmployeeParser.new(response).employee
59
- end
88
+ def self.find_by(field:, value:, params: { humanReadable: 'replace' })
89
+ if params[:fields]
90
+ params[:fields] = (DEFAULT_FIELDS + params[:fields] + Bob.default_custom_fields.map do |dcf|
91
+ Bob.custom_fields[dcf][:api_field]
92
+ end).uniq
93
+ end
94
+ unless params[:fields]
95
+ params[:fields] = (DEFAULT_FIELDS + Bob.default_custom_fields.map do |dcf|
96
+ Bob.custom_fields[dcf][:api_field]
97
+ end)
98
+ end
60
99
 
61
- def self.find_by(field:, value:, params: { includeHumanReadable: true })
62
- all(params).find do |employee|
100
+ search(params).find do |employee|
63
101
  employee.send(field) == value
64
102
  end
65
103
  end
@@ -68,13 +106,22 @@ module Bob
68
106
  put("people/#{employee_id}", params)
69
107
  end
70
108
 
109
+ def self.update_custom_field(employee_id:, field:, value:)
110
+ temp_params = { Bob.custom_fields[field][:dig_path].reverse[0] => value }
111
+ Bob.custom_fields[field][:dig_path].reverse.drop(1).each do |field|
112
+ temp_params = { field => temp_params }
113
+ end
114
+
115
+ update(employee_id:, params: temp_params)
116
+ end
117
+
71
118
  # start date needs to be in ISO format
72
119
  def self.update_start_date(employee_id, start_date)
73
120
  post("employees/#{employee_id}", { startDate: start_date })
74
121
  end
75
122
 
76
123
  def self.update_email(employee_id, email)
77
- put("people/#{employee_id}/email", { email: email })
124
+ put("people/#{employee_id}/email", { email: })
78
125
  end
79
126
  end
80
127
  end
@@ -3,13 +3,13 @@
3
3
  module Bob
4
4
  module MetaData
5
5
  class CompanyLists < API
6
- def self.all
7
- response = get('company/named-lists')
6
+ def self.all(options = { includeArchived: false })
7
+ response = get('company/named-lists', options)
8
8
  CompanyListParser.new(response).lists
9
9
  end
10
10
 
11
- def self.find(list_name)
12
- response = get("company/named-lists/#{list_name}")
11
+ def self.find(list_name, options = { includeArchived: false })
12
+ response = get("company/named-lists/#{list_name}", options)
13
13
  CompanyListParser.new(response).list
14
14
  end
15
15
 
@@ -8,8 +8,14 @@ module Bob
8
8
  get('company/reports')
9
9
  end
10
10
 
11
- def self.read(report_id)
12
- get("company/reports/#{report_id}/download?format=csv", {}, csv_response: true)
11
+ def self.read(report_id, params = {})
12
+ params = { format: 'csv' }.merge(params)
13
+
14
+ get("company/reports/#{report_id}/download", params, csv_response: true)
15
+ end
16
+
17
+ def self.read_table_report(report_id)
18
+ get("people/custom-tables/metadata/#{report_id}")
13
19
  end
14
20
 
15
21
  def self.sftp_upload(sftp_details:, report_id:)
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bob
4
+ class Tasks < API
5
+ def self.all
6
+ get('tasks')
7
+ end
8
+ end
9
+ end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Bob
4
4
  class TimeOff < API
5
- def self.all_changed_since(since)
6
- response = get('timeoff/requests/changes', { since: since })['changes']
5
+ def self.all_changed_since(since, pending = false)
6
+ response = get('timeoff/requests/changes', { since:, pending: })['changes']
7
7
  TimeOffParser.new({ 'outs' => response }).events
8
8
  end
9
9
 
@@ -16,5 +16,10 @@ module Bob
16
16
  response = get("timeoff/employees/#{employee_id}/requests/#{request_id}")
17
17
  TimeOffParser.new(response).event
18
18
  end
19
+
20
+ def self.balance(employee_id, params)
21
+ response = get("timeoff/employees/#{employee_id}/balance", params)
22
+ TimeOffParser.new(response)
23
+ end
19
24
  end
20
25
  end
@@ -2,7 +2,8 @@
2
2
 
3
3
  module Bob
4
4
  module Configuration
5
- VALID_OPTIONS_KEYS = %i[access_token access_user_name api_version api_key use_sandbox].freeze
5
+ VALID_OPTIONS_KEYS = %i[access_token access_user_name api_version api_key use_sandbox custom_tables custom_fields
6
+ default_custom_fields].freeze
6
7
  attr_accessor(*VALID_OPTIONS_KEYS)
7
8
 
8
9
  # Sets all configuration options to their default values
@@ -24,10 +25,13 @@ module Bob
24
25
  # Resets all configuration options to the defaults.
25
26
  def reset
26
27
  self.api_version = 'v1'
27
- self.access_token = ENV['ACCESS_TOKEN']
28
- self.access_user_name = ENV['ACCESS_USER_NAME']
29
- self.api_key = ENV['API_KEY']
28
+ self.access_token = ENV.fetch('ACCESS_TOKEN', nil)
29
+ self.access_user_name = ENV.fetch('ACCESS_USER_NAME', nil)
30
+ self.api_key = ENV.fetch('API_KEY', nil)
30
31
  self.use_sandbox = false
32
+ self.custom_tables = {}
33
+ self.custom_fields = {}
34
+ self.default_custom_fields = []
31
35
  end
32
36
  end
33
37
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Models
4
4
  class Base
5
- def initialize(raw) # rubocop:disable Metrics/AbcSize
5
+ def initialize(raw)
6
6
  attributes = Bob::Util.underscorize_hash(raw)
7
7
 
8
8
  attributes.each do |k, v|
@@ -14,5 +14,12 @@ module Models
14
14
  next
15
15
  end
16
16
  end
17
+
18
+ def dig_custom_field(field)
19
+ Bob.custom_fields[field][:dig_path].reduce(self) { |response, sub_field| response.send(sub_field) }
20
+ rescue NoMethodError => e
21
+ Rails.logger.info("Error: #{e.message}")
22
+ nil
23
+ end
17
24
  end
18
25
  end
@@ -2,12 +2,24 @@
2
2
 
3
3
  module Models
4
4
  class Employee < Models::Base
5
+ def preferred_last_name
6
+ dig_custom_field('PREFERRED_LAST_NAME')
7
+ end
8
+
9
+ def preferred_first_name
10
+ dig_custom_field('PREFERRED_FIRST_NAME')
11
+ end
12
+
13
+ def preferred_full_name
14
+ "#{preferred_first_name} #{preferred_last_name}"
15
+ end
16
+
5
17
  def manager?
6
18
  work.is_manager
7
19
  end
8
20
 
9
21
  def job_title
10
- human_readable.work.title
22
+ work.title
11
23
  end
12
24
 
13
25
  def start_date
@@ -15,19 +27,19 @@ module Models
15
27
  end
16
28
 
17
29
  def department
18
- work.department
30
+ work.try(:department)
19
31
  end
20
32
 
21
33
  def division
22
- human_readable.work.custom_columns&.column_1629151319875
34
+ dig_custom_field('DIVISION')
23
35
  end
24
36
 
25
37
  def team
26
- human_readable.work.custom_columns&.column_1642024758438
38
+ dig_custom_field('SUB_DIVISION')
27
39
  end
28
40
 
29
41
  def entity
30
- human_readable.work.custom_columns&.column_1633980105047
42
+ dig_custom_field('EMPLOYER')
31
43
  end
32
44
 
33
45
  def city
@@ -35,11 +47,7 @@ module Models
35
47
  end
36
48
 
37
49
  def country
38
- address.country
39
- end
40
-
41
- def role_level
42
- human_readable.work.custom_columns.column_1629151373898
50
+ address&.country
43
51
  end
44
52
 
45
53
  def has_manager?
@@ -47,7 +55,13 @@ module Models
47
55
  end
48
56
 
49
57
  def manager
50
- work&.reports_to
58
+ return unless manager_email # has no manager, prob CEO
59
+
60
+ @manager ||= Bob::Employees.find(manager_email)
61
+ end
62
+
63
+ def manager_email
64
+ try(:work).try(:reports_to).try(:email)
51
65
  end
52
66
 
53
67
  def has_second_level_manager?
@@ -55,7 +69,9 @@ module Models
55
69
  end
56
70
 
57
71
  def second_level_manager
58
- @second_level_manager ||= Bob::Employees.find(work&.second_level_manager)
72
+ return nil unless manager.manager_email
73
+
74
+ @second_level_manager ||= Bob::Employees.find(manager.manager_email)
59
75
  end
60
76
 
61
77
  def has_third_level_manager?
@@ -63,7 +79,9 @@ module Models
63
79
  end
64
80
 
65
81
  def third_level_manager
66
- second_level_manager&.manager
82
+ return nil unless second_level_manager.manager_email
83
+
84
+ @third_level_manager ||= Bob::Employees.find(second_level_manager.manager_email)
67
85
  end
68
86
 
69
87
  def has_fourth_level_manager?
@@ -71,11 +89,13 @@ module Models
71
89
  end
72
90
 
73
91
  def fourth_level_manager
74
- second_level_manager&.second_level_manager
92
+ return nil unless third_level_manager.manager_email
93
+
94
+ Bob::Employees.find(third_level_manager.manager_email)
75
95
  end
76
96
 
77
97
  def cost_center
78
- human_readable.payroll&.custom&.field_1634476091511
98
+ dig_custom_field('COST_CENTER')
79
99
  end
80
100
 
81
101
  def personal_email
@@ -83,24 +103,45 @@ module Models
83
103
  end
84
104
 
85
105
  def linkedin_profile
86
- human_readable.about.social_data&.linkedin
106
+ about.social_data&.linkedin
87
107
  end
88
108
 
89
109
  def currency
90
- payroll.salary.payment.currency
110
+ return nil unless payroll.try(:salary).try(:payment)
111
+
112
+ payroll.salary.payment.split(/\d/).first
91
113
  end
92
114
 
93
115
  def base_pay
94
- payroll.salary.payment.value
116
+ return nil unless payroll.try(:salary).try(:payment)
117
+
118
+ # split on first occurence of a digit
119
+ payroll.salary.payment.sub(currency, '').to_f
95
120
  end
96
121
 
97
122
  def variable_pay
98
- # TODO: check if we handle all the types with this field
99
- payroll.variable.field_255298499.amount&.value || 0.0
123
+ return 0.0 unless payroll.try(:variable)&.field_255298499&.amount
124
+
125
+ payroll.variable.field_255298499.amount.sub(currency, '').to_f
126
+ end
127
+
128
+ def job_role_row
129
+ @job_role_row ||= Bob::Employee::CustomTables.rows(id,
130
+ 'category_1645574919835__table_1716392607454').max_by do |row|
131
+ Date.parse(row.column_1716392634939)
132
+ end
133
+ end
134
+
135
+ def job_grade
136
+ return nil if job_role_row.nil?
137
+
138
+ job_role_row.human_readable.column_1716393179800
100
139
  end
101
140
 
102
141
  def job_role_id
103
- human_readable.custom.category_1645574919835.field_1657052825123
142
+ return nil if job_role_row.nil?
143
+
144
+ job_role_row.human_readable.column_1716393584611
104
145
  end
105
146
  end
106
147
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Models
4
+ class Payroll < Models::Base
5
+ end
6
+ end
@@ -24,7 +24,7 @@ module Models
24
24
  end
25
25
 
26
26
  def total_days_off
27
- (start_date...end_date).count + 1
27
+ (parsed_start_date...parsed_end_date).count + 1
28
28
  end
29
29
 
30
30
  private
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Models
4
- class Salary < Models::Base
4
+ class Training < Models::Base
5
5
  end
6
6
  end
data/lib/bob/models.rb CHANGED
@@ -14,3 +14,4 @@ require_relative 'models/work_history'
14
14
  require_relative 'models/lifecycle_history'
15
15
  require_relative 'models/employment_history'
16
16
  require_relative 'models/table'
17
+ require_relative 'models/payroll'
@@ -17,7 +17,7 @@ class EmployeeParser < BaseParser
17
17
 
18
18
  def starters_on(date)
19
19
  json_response['employees']
20
- .select { |employee| employee['work']['startDate'] == date }
20
+ .select { |employee| Date.parse(employee['work']['startDate']) == date }
21
21
  .map { |attributes| Models::Employee.new(attributes) }
22
22
  end
23
23
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PayrollParser < BaseParser
4
+ def payroll_histories
5
+ json_response['employees'].map { |attributes| Models::Payroll.new(attributes) }
6
+ end
7
+ end
data/lib/bob/parsers.rb CHANGED
@@ -14,3 +14,4 @@ require_relative 'parsers/work_history_parser'
14
14
  require_relative 'parsers/lifecycle_history_parser'
15
15
  require_relative 'parsers/employment_history_parser'
16
16
  require_relative 'parsers/table_parser'
17
+ require_relative 'parsers/payroll_parser'
data/lib/bob/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bob
4
- VERSION = '0.5.33'
4
+ VERSION = '0.5.34'
5
5
  end
data/lib/bob/webhooks.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Bob
4
4
  class Webhooks
5
- def self.calculate_signature(body:, key: ENV['BOB_WEBHOOK_SECRET'])
5
+ def self.calculate_signature(body:, key: ENV.fetch('BOB_WEBHOOK_SECRET', nil))
6
6
  digest = OpenSSL::Digest.new('sha512')
7
7
  Base64.strict_encode64(OpenSSL::HMAC.digest(digest, key, body))
8
8
  end
data/lib/bob.rb CHANGED
@@ -12,6 +12,7 @@ require_relative 'bob/webhooks'
12
12
  require_relative 'bob/models'
13
13
  require_relative 'bob/parsers'
14
14
  require_relative 'bob/util'
15
+ require_relative 'bob/api/tasks'
15
16
 
16
17
  module Bob
17
18
  extend Configuration
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bobhr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.33
4
+ version: 0.5.34
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-07-28 00:00:00.000000000 Z
11
+ date: 2024-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -69,6 +69,7 @@ files:
69
69
  - lib/bob/api/employee/equity_grants.rb
70
70
  - lib/bob/api/employee/invites.rb
71
71
  - lib/bob/api/employee/lifecycle_history.rb
72
+ - lib/bob/api/employee/payroll.rb
72
73
  - lib/bob/api/employee/salaries.rb
73
74
  - lib/bob/api/employee/time_off.rb
74
75
  - lib/bob/api/employee/trainings.rb
@@ -81,6 +82,7 @@ files:
81
82
  - lib/bob/api/metadata/time_off_policies.rb
82
83
  - lib/bob/api/onboarding_wizards.rb
83
84
  - lib/bob/api/reports.rb
85
+ - lib/bob/api/tasks.rb
84
86
  - lib/bob/api/time_off.rb
85
87
  - lib/bob/configuration.rb
86
88
  - lib/bob/models.rb
@@ -92,6 +94,7 @@ files:
92
94
  - lib/bob/models/equity_grant.rb
93
95
  - lib/bob/models/lifecycle_history.rb
94
96
  - lib/bob/models/onboarding_wizard.rb
97
+ - lib/bob/models/payroll.rb
95
98
  - lib/bob/models/salary.rb
96
99
  - lib/bob/models/table.rb
97
100
  - lib/bob/models/time_off.rb
@@ -107,6 +110,7 @@ files:
107
110
  - lib/bob/parsers/equity_grant_parser.rb
108
111
  - lib/bob/parsers/lifecycle_history_parser.rb
109
112
  - lib/bob/parsers/onboarding_wizard_parser.rb
113
+ - lib/bob/parsers/payroll_parser.rb
110
114
  - lib/bob/parsers/salary_parser.rb
111
115
  - lib/bob/parsers/table_parser.rb
112
116
  - lib/bob/parsers/time_off_parser.rb
@@ -130,14 +134,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
134
  requirements:
131
135
  - - ">="
132
136
  - !ruby/object:Gem::Version
133
- version: '3.0'
137
+ version: '3.2'
134
138
  required_rubygems_version: !ruby/object:Gem::Requirement
135
139
  requirements:
136
140
  - - ">="
137
141
  - !ruby/object:Gem::Version
138
142
  version: '0'
139
143
  requirements: []
140
- rubygems_version: 3.3.26
144
+ rubygems_version: 3.5.18
141
145
  signing_key:
142
146
  specification_version: 4
143
147
  summary: Ruby gem for Bob API