Class: PeopleGroup::Connectors::Bamboo

Inherits:
Object
  • Object
show all
Defined in:
lib/peoplegroup/connectors/bamboo.rb

Constant Summary collapse

EmployeeNotFoundError =
Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(use_report: false) ⇒ Bamboo

Returns a new instance of Bamboo.



12
13
14
15
# File 'lib/peoplegroup/connectors/bamboo.rb', line 12

def initialize(use_report: false)
  @use_report = use_report
  @client = Bamboozled.client(subdomain: 'gitlab', api_key: ENV['BAMBOO_API_KEY'])
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



8
9
10
# File 'lib/peoplegroup/connectors/bamboo.rb', line 8

def client
  @client
end

Instance Method Details

#accrued_days(employee_number) ⇒ Object



197
198
199
200
201
202
# File 'lib/peoplegroup/connectors/bamboo.rb', line 197

def accrued_days(employee_number)
  employee_accruals_type = time_off_type('Employee Accruals')
  total_accruals = time_off_estimate(employee_number).find { |type| type['timeOffType'] == employee_accruals_type['id'] }

  total_accruals['balance'].to_f
end

#active_and_current_employeesObject Also known as: active_and_current_team_members



153
154
155
156
157
158
# File 'lib/peoplegroup/connectors/bamboo.rb', line 153

def active_and_current_employees
  today = Date.current
  employees.select do |employee|
    employee['status'] == 'Active' && Date.parse(employee['hireDate']) <= today
  end
end

#active_employeesObject Also known as: active_team_members



148
149
150
# File 'lib/peoplegroup/connectors/bamboo.rb', line 148

def active_employees
  employees.select { |employee| employee['status'] == 'Active' }
end

#add_additional_data(employee_number, data) ⇒ Object



277
278
279
280
# File 'lib/peoplegroup/connectors/bamboo.rb', line 277

def add_additional_data(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'customAdditionalInformation1', data) }
end

#add_bonus(employee_number, comment) ⇒ Object



287
288
289
290
291
292
293
294
295
296
297
# File 'lib/peoplegroup/connectors/bamboo.rb', line 287

def add_bonus(employee_number, comment)
  team_member = search_employee_by_field(field: 'employeeNumber', value: employee_number)
  data = {
    customBonusdate: Date.today.to_s,
    customBonusamount: { value: 1_000, currency: 'USD' },
    customBonustype: 'Discretionary Bonus',
    customBonuscomments: comment
    # customNominatedBy: 'TODO'
  }
  retry_on_error { @client.employee.add_table_row(team_member['id'], 'customBonus', data) }
end

#add_compensation_details(employee_number, data) ⇒ Object



178
179
180
181
# File 'lib/peoplegroup/connectors/bamboo.rb', line 178

def add_compensation_details(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'compensation', data) }
end

#add_currency_conversion(employee_number, data) ⇒ Object



257
258
259
260
# File 'lib/peoplegroup/connectors/bamboo.rb', line 257

def add_currency_conversion(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'customCurrencyConversion', data) }
end

#add_employment_status(employee_number, data) ⇒ Object



252
253
254
255
# File 'lib/peoplegroup/connectors/bamboo.rb', line 252

def add_employment_status(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'employmentStatus', data) }
end

#add_family_member(employee_number, data) ⇒ Object



272
273
274
275
# File 'lib/peoplegroup/connectors/bamboo.rb', line 272

def add_family_member(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'customFamilyMember', data) }
end

#add_file(employee_number, file_name, file, folder_id) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
# File 'lib/peoplegroup/connectors/bamboo.rb', line 240

def add_file(employee_number, file_name, file, folder_id)
  id = bamboo_id!(employee_number)

  options = {
    category: folder_id,
    fileName: file_name,
    share: 'yes',
    file: file
  }
  retry_on_error { @client.employee.add_file(id, options) }
end

#add_job_details(employee_number, data) ⇒ Object



166
167
168
169
# File 'lib/peoplegroup/connectors/bamboo.rb', line 166

def add_job_details(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'jobInfo', data) }
end

#add_on_target_earnings(employee_number, data) ⇒ Object



262
263
264
265
# File 'lib/peoplegroup/connectors/bamboo.rb', line 262

def add_on_target_earnings(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'customOnTargetEarnings', data) }
end

#add_signing_bonus(employee_number, data) ⇒ Object



267
268
269
270
# File 'lib/peoplegroup/connectors/bamboo.rb', line 267

def add_signing_bonus(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'customBonus', data) }
end

#add_stock_options(employee_number, data) ⇒ Object



161
162
163
164
# File 'lib/peoplegroup/connectors/bamboo.rb', line 161

def add_stock_options(employee_number, data)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.add_table_row(id, 'customEquity', data) }
end

#add_time_off_policy(employee_number, time_off_policy_id, accrual_start_date) ⇒ Object



214
215
216
217
218
219
# File 'lib/peoplegroup/connectors/bamboo.rb', line 214

def add_time_off_policy(employee_number, time_off_policy_id, accrual_start_date)
  policies = [{ timeOffPolicyId: time_off_policy_id, accrualStartDate: accrual_start_date }]
  id = bamboo_id!(employee_number)

  retry_on_error { @client.employee.add_time_off_policies(id, policies) }
end

#additional_data(employee_number) ⇒ Object



282
283
284
285
# File 'lib/peoplegroup/connectors/bamboo.rb', line 282

def additional_data(employee_number)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.table_data(id, 'employmentStatus') }
end

#bamboo_id!(employee_number) ⇒ Object



30
31
32
# File 'lib/peoplegroup/connectors/bamboo.rb', line 30

def bamboo_id!(employee_number)
  get_team_member_details!(employee_number)['id']
end

#contract_folder_id(employee_number) ⇒ Object



236
237
238
# File 'lib/peoplegroup/connectors/bamboo.rb', line 236

def contract_folder_id(employee_number)
  @contract_folder_id ||= files(employee_number)['categories'].find { |folder| folder['name'] == 'Contracts & Changes' }['id']
end

#create_employee(employee_details_hash) ⇒ Object Also known as: create_team_member



115
116
117
118
# File 'lib/peoplegroup/connectors/bamboo.rb', line 115

def create_employee(employee_details_hash)
  invalidate_cache
  retry_on_error { @client.employee.add(employee_details_hash) }
end

#employee_time_off_policies(employee_number) ⇒ Object Also known as: team_member_time_off_policies



208
209
210
211
# File 'lib/peoplegroup/connectors/bamboo.rb', line 208

def employee_time_off_policies(employee_number)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.time_off_policies(id) }
end

#employeesObject Also known as: team_members



132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/peoplegroup/connectors/bamboo.rb', line 132

def employees
  return @employees unless @employees.nil?

  report = retry_on_error do
    if @use_report
      @client.report.find(@use_report, 'JSON', true)
    else
      @client.report.custom(fields, 'JSON')
    end
  end

  filtered = report.reject { |team_member| team_member['lastName'] == 'Test-Gitlab' }
  @employees = filtered.map { |team_member| format_team_member(team_member) }
end

#employment_statuses(employee_number) ⇒ Object



183
184
185
186
# File 'lib/peoplegroup/connectors/bamboo.rb', line 183

def employment_statuses(employee_number)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.table_data(id, 'employmentStatus') }
end

#fetch_manager(team_member) ⇒ Object



93
94
95
# File 'lib/peoplegroup/connectors/bamboo.rb', line 93

def fetch_manager(team_member)
  active_team_members.find { |tm| tm['employeeNumber'] == team_member['supervisorId'] }
end

#fetch_manager!(team_member) ⇒ Object



97
98
99
100
101
102
# File 'lib/peoplegroup/connectors/bamboo.rb', line 97

def fetch_manager!(team_member)
  manager = fetch_manager(team_member)
  raise EmployeeNotFoundError, "Manager not found for employee #{team_member['employeeNumber']}" if manager.nil?

  manager
end

#fetch_second_level_manager(team_member) ⇒ Object



104
105
106
# File 'lib/peoplegroup/connectors/bamboo.rb', line 104

def fetch_second_level_manager(team_member)
  fetch_manager(fetch_manager(team_member))
end

#fetch_second_level_manager!(team_member) ⇒ Object



108
109
110
111
112
113
# File 'lib/peoplegroup/connectors/bamboo.rb', line 108

def fetch_second_level_manager!(team_member)
  manager = fetch_second_level_manager(team_member)
  raise EmployeeNotFoundError, "No second level manager found for employee #{team_member['employeeNumber']}" if manager.nil?

  manager
end

#get_employee_details(id) ⇒ Object Also known as: get_team_member_details



17
18
19
# File 'lib/peoplegroup/connectors/bamboo.rb', line 17

def get_employee_details(id)
  employees.find { |emp| emp['employeeNumber'] == id.to_s }
end

#get_employee_details!(id) ⇒ Object Also known as: get_team_member_details!



22
23
24
25
26
27
# File 'lib/peoplegroup/connectors/bamboo.rb', line 22

def get_employee_details!(id)
  employee_details = get_employee_details(id)
  raise EmployeeNotFoundError, "No team member found with employee number #{id}" if employee_details.nil?

  employee_details
end

#job_details(employee_number) ⇒ Object



227
228
229
230
# File 'lib/peoplegroup/connectors/bamboo.rb', line 227

def job_details(employee_number)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.table_data(id, 'jobInfo') }
end

#locationsObject



128
129
130
# File 'lib/peoplegroup/connectors/bamboo.rb', line 128

def locations
  meta_fields.detect { |res| res['name'] == 'Location' }['options'].each_with_object([]) { |option, array| array << option['name'] if option['archived'] == 'no' } || []
end

#remove_time_off_policy(employee_number, time_off_policy_id) ⇒ Object



221
222
223
224
225
# File 'lib/peoplegroup/connectors/bamboo.rb', line 221

def remove_time_off_policy(employee_number, time_off_policy_id)
  # A nil accrual start date removes a policy assignment
  # Reference: https://documentation.bamboohr.com/reference#time-off-assign-time-off-policies-for-an-employee
  add_time_off_policy(employee_number, time_off_policy_id, nil)
end

#resumes_folder_id(employee_number) ⇒ Object



232
233
234
# File 'lib/peoplegroup/connectors/bamboo.rb', line 232

def resumes_folder_id(employee_number)
  @resumes_folder_id ||= files(employee_number)['categories'].find { |folder| folder['name'] == 'Resumes and Applications' }['id']
end

#search_employee(name) ⇒ Object Also known as: search_team_member



34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/peoplegroup/connectors/bamboo.rb', line 34

def search_employee(name)
  return if name.empty?

  employees.find do |emp|
    [
      emp['displayName']&.downcase,
      "#{emp['firstName']&.downcase} #{emp['lastName']&.downcase}",
      "#{emp['preferredName']&.downcase} #{emp['lastName']&.downcase}",
      "#{emp['firstName']&.downcase} #{emp['customPreferredLastName']&.downcase}",
      "#{emp['preferredName']&.downcase} #{emp['customPreferredLastName']&.downcase}",
      emp['fullName5']&.downcase # this is firstName middleName lastName
    ].include?(name.downcase)
  end
end

#search_employee!(name) ⇒ Object Also known as: search_team_member!



50
51
52
53
54
55
# File 'lib/peoplegroup/connectors/bamboo.rb', line 50

def search_employee!(name)
  employee = search_employee(name)
  raise EmployeeNotFoundError, "No employee found with name #{name}" if employee.nil?

  employee
end

#search_employee_by_field(field:, value:) ⇒ Object Also known as: search_team_member_by_field



58
59
60
# File 'lib/peoplegroup/connectors/bamboo.rb', line 58

def search_employee_by_field(field:, value:)
  employees.find { |employee| employee[field] == value.to_s }
end

#search_employee_by_field!(field:, value:) ⇒ Object Also known as: search_team_member_by_field!



63
64
65
66
67
68
# File 'lib/peoplegroup/connectors/bamboo.rb', line 63

def search_employee_by_field!(field:, value:)
  employee = search_employee_by_field(field: field, value: value)
  raise EmployeeNotFoundError, "No employee found with #{field}: #{value}" if employee.nil?

  employee
end

#search_team_member_by_email(email) ⇒ Object Also known as: slack_email_lookup_with_fallback

Find the associated team member without checking case on the ‘workEmail’ field.



72
73
74
# File 'lib/peoplegroup/connectors/bamboo.rb', line 72

def search_team_member_by_email(email)
  team_members.find { |team_member| team_member['workEmail']&.downcase == email&.downcase }
end

#search_team_member_by_email!(email) ⇒ Object Also known as: slack_email_lookup_with_fallback!



77
78
79
80
81
82
# File 'lib/peoplegroup/connectors/bamboo.rb', line 77

def search_team_member_by_email!(email)
  team_member = search_team_member_by_email(email)
  raise EmployeeNotFoundError, "No team member found with email #{email}." unless team_member

  team_member
end

#team_members_by_department(department) ⇒ Object



85
86
87
# File 'lib/peoplegroup/connectors/bamboo.rb', line 85

def team_members_by_department(department)
  active_and_current_team_members.select { |team_member| team_member['department'] == department }
end

#team_members_by_division(division) ⇒ Object



89
90
91
# File 'lib/peoplegroup/connectors/bamboo.rb', line 89

def team_members_by_division(division)
  active_and_current_team_members.select { |team_member| team_member['division'] == division }
end

#time_off_adjustment(employee_number, options) ⇒ Object



192
193
194
195
# File 'lib/peoplegroup/connectors/bamboo.rb', line 192

def time_off_adjustment(employee_number, options)
  id = bamboo_id!(employee_number)
  retry_on_error { @client.employee.time_off_balance_adjustment(id, options) }
end

#time_off_policiesObject



204
205
206
# File 'lib/peoplegroup/connectors/bamboo.rb', line 204

def time_off_policies
  @time_off_policies ||= retry_on_error { @client.meta.time_off_policies }
end

#time_off_type(name) ⇒ Object



188
189
190
# File 'lib/peoplegroup/connectors/bamboo.rb', line 188

def time_off_type(name)
  time_off_types['timeOffTypes'].find { |type| type['name'] == name }
end

#update_employee(employee_number, employee_details_hash) ⇒ Object Also known as: update_team_member



121
122
123
124
125
# File 'lib/peoplegroup/connectors/bamboo.rb', line 121

def update_employee(employee_number, employee_details_hash)
  id = bamboo_id!(employee_number)
  invalidate_cache
  retry_on_error { @client.employee.update(id, employee_details_hash) }
end

#update_job_details(employee_number, data) ⇒ Object



171
172
173
174
175
176
# File 'lib/peoplegroup/connectors/bamboo.rb', line 171

def update_job_details(employee_number, data)
  id = bamboo_id!(employee_number)
  current_data = job_details(employee_number) # it should only be one row as we just created this user
  row_id = current_data.first['id']
  retry_on_error { @client.employee.update_table_row(id, 'jobInfo', row_id, data) }
end