Add some support for datasync, and deleting times from Harvest
This commit is contained in:
parent
fe0daf00bc
commit
bdb8b22ef4
|
@ -26,7 +26,4 @@ Harvest integration data models
|
||||||
|
|
||||||
from .harvest import (HarvestCacheUser, HarvestCacheClient,
|
from .harvest import (HarvestCacheUser, HarvestCacheClient,
|
||||||
HarvestCacheProject, HarvestCacheTask,
|
HarvestCacheProject, HarvestCacheTask,
|
||||||
HarvestCacheTimeEntry,
|
HarvestCacheTimeEntry)
|
||||||
# TODO: deprecate / remove these
|
|
||||||
HarvestUser, HarvestClient, HarvestProject,
|
|
||||||
HarvestTask, HarvestTimeEntry)
|
|
||||||
|
|
|
@ -111,15 +111,6 @@ class HarvestCacheUser(model.Base):
|
||||||
return normalize_full_name(self.first_name, self.last_name)
|
return normalize_full_name(self.first_name, self.last_name)
|
||||||
|
|
||||||
|
|
||||||
class HarvestUser(HarvestCacheUser):
|
|
||||||
""" DEPRECATED """
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("HarvestUser class is deprecated; "
|
|
||||||
"please use HarvestCacheUser instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
|
|
||||||
class HarvestCacheClient(model.Base):
|
class HarvestCacheClient(model.Base):
|
||||||
"""
|
"""
|
||||||
Represents a client record in Harvest.
|
Represents a client record in Harvest.
|
||||||
|
@ -152,15 +143,6 @@ class HarvestCacheClient(model.Base):
|
||||||
return self.name or ''
|
return self.name or ''
|
||||||
|
|
||||||
|
|
||||||
class HarvestClient(HarvestCacheClient):
|
|
||||||
""" DEPRECATED """
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("HarvestClient class is deprecated; "
|
|
||||||
"please use HarvestCacheClient instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
|
|
||||||
class HarvestCacheProject(model.Base):
|
class HarvestCacheProject(model.Base):
|
||||||
"""
|
"""
|
||||||
Represents a project record in Harvest.
|
Represents a project record in Harvest.
|
||||||
|
@ -234,15 +216,6 @@ class HarvestCacheProject(model.Base):
|
||||||
return self.name or ''
|
return self.name or ''
|
||||||
|
|
||||||
|
|
||||||
class HarvestProject(HarvestCacheProject):
|
|
||||||
""" DEPRECATED """
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("HarvestProject class is deprecated; "
|
|
||||||
"please use HarvestCacheProject instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
|
|
||||||
class HarvestCacheTask(model.Base):
|
class HarvestCacheTask(model.Base):
|
||||||
"""
|
"""
|
||||||
Represents a task record in Harvest.
|
Represents a task record in Harvest.
|
||||||
|
@ -277,15 +250,6 @@ class HarvestCacheTask(model.Base):
|
||||||
return self.name or ''
|
return self.name or ''
|
||||||
|
|
||||||
|
|
||||||
class HarvestTask(HarvestCacheTask):
|
|
||||||
""" DEPRECATED """
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("HarvestTask class is deprecated; "
|
|
||||||
"please use HarvestCacheTask instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
|
|
||||||
class HarvestCacheTimeEntry(model.Base):
|
class HarvestCacheTimeEntry(model.Base):
|
||||||
"""
|
"""
|
||||||
Represents a time entry record in Harvest.
|
Represents a time entry record in Harvest.
|
||||||
|
@ -361,12 +325,3 @@ class HarvestCacheTimeEntry(model.Base):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.spent_date or '')
|
return str(self.spent_date or '')
|
||||||
|
|
||||||
|
|
||||||
class HarvestTimeEntry(HarvestCacheTimeEntry):
|
|
||||||
""" DEPRECATED """
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("HarvestTimeEntry class is deprecated; "
|
|
||||||
"please use HarvestCacheTimeEntry instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
|
@ -31,7 +31,14 @@ from rattail_harvest.harvest.webapi import make_harvest_webapi
|
||||||
class ToHarvest(importing.Importer):
|
class ToHarvest(importing.Importer):
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
super(ToHarvest, self).setup()
|
super().setup()
|
||||||
|
self.setup_webapi()
|
||||||
|
|
||||||
|
def datasync_setup(self):
|
||||||
|
super().datasync_setup()
|
||||||
|
self.setup_webapi()
|
||||||
|
|
||||||
|
def setup_webapi(self):
|
||||||
self.webapi = make_harvest_webapi(self.config)
|
self.webapi = make_harvest_webapi(self.config)
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,4 +165,5 @@ class TimeEntryImporter(ToHarvest):
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
raise NotImplementedError
|
self.webapi.delete_time_entry(entry['id'])
|
||||||
|
return True
|
||||||
|
|
|
@ -61,6 +61,9 @@ class HarvestWebAPI(object):
|
||||||
elif request_method == 'PATCH':
|
elif request_method == 'PATCH':
|
||||||
response = requests.patch('{}/{}'.format(self.base_url, api_method),
|
response = requests.patch('{}/{}'.format(self.base_url, api_method),
|
||||||
headers=headers, params=params)
|
headers=headers, params=params)
|
||||||
|
elif request_method == 'DELETE':
|
||||||
|
response = requests.delete('{}/{}'.format(self.base_url, api_method),
|
||||||
|
headers=headers, params=params)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("unknown request method: {}".format(
|
raise NotImplementedError("unknown request method: {}".format(
|
||||||
request_method))
|
request_method))
|
||||||
|
@ -85,6 +88,12 @@ class HarvestWebAPI(object):
|
||||||
"""
|
"""
|
||||||
return self._request('PATCH', api_method, params=params)
|
return self._request('PATCH', api_method, params=params)
|
||||||
|
|
||||||
|
def delete(self, api_method, params=None):
|
||||||
|
"""
|
||||||
|
Perform a DELETE request for the given API method, and return the response.
|
||||||
|
"""
|
||||||
|
return self._request('DELETE', api_method, params=params)
|
||||||
|
|
||||||
def get_company(self):
|
def get_company(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the company for the currently authenticated user.
|
Retrieves the company for the currently authenticated user.
|
||||||
|
@ -170,8 +179,13 @@ class HarvestWebAPI(object):
|
||||||
|
|
||||||
https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#retrieve-a-time-entry
|
https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#retrieve-a-time-entry
|
||||||
"""
|
"""
|
||||||
response = self.get('/time_entries/{}'.format(time_entry_id))
|
try:
|
||||||
return response.json()
|
response = self.get('/time_entries/{}'.format(time_entry_id))
|
||||||
|
except requests.exceptions.HTTPError as error:
|
||||||
|
if error.response.status_code != 404:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
return response.json()
|
||||||
|
|
||||||
def create_time_entry(self, **kwargs):
|
def create_time_entry(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -208,6 +222,14 @@ class HarvestWebAPI(object):
|
||||||
response = self.patch('/time_entries/{}'.format(time_entry_id), params=kwargs)
|
response = self.patch('/time_entries/{}'.format(time_entry_id), params=kwargs)
|
||||||
return response.json()
|
return response.json()
|
||||||
|
|
||||||
|
def delete_time_entry(self, time_entry_id, **kwargs):
|
||||||
|
"""
|
||||||
|
Delete a time entry.
|
||||||
|
|
||||||
|
https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#delete-a-time-entry
|
||||||
|
"""
|
||||||
|
self.delete('/time_entries/{}'.format(time_entry_id), params=kwargs)
|
||||||
|
|
||||||
|
|
||||||
def make_harvest_webapi(config):
|
def make_harvest_webapi(config):
|
||||||
access_token = config.require('harvest', 'api.access_token')
|
access_token = config.require('harvest', 'api.access_token')
|
||||||
|
|
Loading…
Reference in a new issue