Add some support for datasync, and deleting times from Harvest

This commit is contained in:
Lance Edgar 2023-10-08 20:38:25 -05:00
parent fe0daf00bc
commit bdb8b22ef4
4 changed files with 35 additions and 53 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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,7 +179,12 @@ 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
""" """
try:
response = self.get('/time_entries/{}'.format(time_entry_id)) 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() 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')