Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Add time off methods and fix xml tables #64

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 66 additions & 4 deletions PyBambooHR/PyBambooHR.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import datetime
import requests
import copy
from . import utils
from . import config
from .utils import make_field_xml
Expand Down Expand Up @@ -87,7 +88,7 @@ def __init__(self, subdomain='', api_key='', datatype='JSON', underscore_keys=Fa

# We are focusing on JSON for now.
if self.datatype == 'XML':
raise NotImplemented("Returning XML is not currently supported.")
raise NotImplementedError("Returning XML is not currently supported.")

if self.datatype == 'JSON':
self.headers.update({'Accept': 'application/json'})
Expand Down Expand Up @@ -181,7 +182,6 @@ def __init__(self, subdomain='', api_key='', datatype='JSON', underscore_keys=Fa
"commisionDate": ("date", ""),
"commissionAmount": ("currency", ""),
"commissionComment": ("text", ""),
"commissionComment": ("text", ""),
"benefitClassDate": ("date", ""),
"benefitClassClass": ("list", ""),
"benefitClassChangeReason": ("list", ""),
Expand Down Expand Up @@ -572,10 +572,15 @@ def get_tabular_data(self, table_name, employee_id='all'):
the values of the table's fields for a particular date, which is stored by key 'date' in the dictionary.
"""
url = self.base_url + 'employees/{}/tables/{}'.format(employee_id, table_name)
r = requests.get(url, timeout=self.timeout, headers=self.headers, auth=(self.api_key, ''))

#Make a copy of headers and replace JSON with XML
xmlheaders = copy.copy(self.headers)
xmlheaders.update({'Accept': 'application/xml'})

r = requests.get(url, timeout=self.timeout, headers=xmlheaders, auth=(self.api_key, ''))
r.raise_for_status()

return utils.transform_tabular_data(r.content)
return utils.transform_tabular_data(r.content, table_name)

def get_employee_changed_table(self, table_name='jobInfo', since=None):
"""
Expand Down Expand Up @@ -647,6 +652,31 @@ def get_time_off_requests(self, start_date=None, end_date=None, status=None, typ
return r.json()
# return utils.transform_time_off(r.content)

def get_time_off_policies(self, employee_id=None):

params = {}
if employee_id == None:
raise ValueError("Employee_id argument is required")
if not(employee_id.isdigit()):
raise ValueError("Employee_id must be a number")

r = self._query('employees/' + employee_id + '/time_off/policies', params, raw=True)
return r.json()

def get_time_off_calculations(self, employee_id=None, end_date=None):
end_date = utils.resolve_date_argument(end_date)

params = {}
if end_date:
params['end'] = end_date
if employee_id == None:
raise ValueError("Employee_id argument is required")
if not(employee_id.isdigit()):
raise ValueError("Employee_id must be a number")

r = self._query('employees/' + employee_id + '/time_off/calculator', params, raw=True)
return r.json()

def get_meta_fields(self):
"""
API method for returning a list of fields info.
Expand Down Expand Up @@ -712,6 +742,38 @@ def get_meta_users(self):

return r.json()

def get_meta_time_off_types(self):
"""
API method for returning a dictionary of time off types.
https://www.bamboohr.com/api/documentation/metadata.php#getTimeOffTypes
Success Response: 200
The HTTP Content-type header will be set with the mime type for the response.

@return: dictionary containing users information
"""

url = self.base_url + "meta/time_off/types/"
r = requests.get(url, timeout=self.timeout, headers=self.headers, auth=(self.api_key, ''))
r.raise_for_status()

return r.json()

def get_meta_time_off_policies(self):
"""
API method for returning a dictionary of time off policies.
https://www.bamboohr.com/api/documentation/metadata.php#getTimeOffPolicies
Success Response: 200
The HTTP Content-type header will be set with the mime type for the response.

@return: dictionary containing users information
"""

url = self.base_url + "meta/time_off/policies/"
r = requests.get(url, timeout=self.timeout, headers=self.headers, auth=(self.api_key, ''))
r.raise_for_status()

return r.json()

def _query(self, url, params, raw=False):
url = self.base_url + url
r = requests.get(url, timeout=self.timeout, params=params, headers=self.headers, auth=(self.api_key, ''))
Expand Down
4 changes: 3 additions & 1 deletion PyBambooHR/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def resolve_date_argument(arg):
return None
raise ValueError("Date argument {} must be either datetime, date, or string in form YYYY-MM-DD".format(arg))

def transform_tabular_data(xml_input):
def transform_tabular_data(xml_input, table_name):
"""
Converts table data (xml) from BambooHR into a dictionary with employee
id as key and a list of dictionaries.
Expand Down Expand Up @@ -105,6 +105,8 @@ def transform_tabular_data(xml_input):
rows = _extract(obj, 'table', 'row')
by_employee_id = {}
for row in rows:
if not('field' in row):
raise ValueError("User does not have access to the {} table".format(table_name))
eid = row['@employeeId']
field_list = row['field'] if type(row['field']) is list \
else [row['field']]
Expand Down
8 changes: 4 additions & 4 deletions tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def test_transform_tabular_data(self):
'321': [{
'customFieldA': '321 & Value A',
'row_id': '999'}]}
self.assertEqual(table, utils.transform_tabular_data(xml))
self.assertEqual(table, utils.transform_tabular_data(xml, 'test'))

def test_transform_tabular_data_single_row(self):
xml = """<?xml version="1.0"?>
Expand All @@ -114,13 +114,13 @@ def test_transform_tabular_data_single_row(self):
</row>
</table>"""
table = {'123': [{'customFieldA': '123 Value A', 'row_id': '321'}]}
self.assertEqual(table, utils.transform_tabular_data(xml))
self.assertEqual(table, utils.transform_tabular_data(xml, 'test'))

def test_transform_tabular_data_empty_table(self):
xml = """<?xml version="1.0"?>
<table/>"""
table = {}
self.assertEqual(table, utils.transform_tabular_data(xml))
self.assertEqual(table, utils.transform_tabular_data(xml, 'test'))

def test_transform_tabular_data_empty_field(self):
xml = """<?xml version="1.0"?>
Expand All @@ -139,4 +139,4 @@ def test_transform_tabular_data_empty_field(self):
'321': [{'customFieldB': '321 Value B',
'row_id': '999'}]}

self.assertEqual(table, utils.transform_tabular_data(xml))
self.assertEqual(table, utils.transform_tabular_data(xml, 'test'))