diff options
Diffstat (limited to 'harvester_submit_week_for_approval.py')
| -rw-r--r-- | harvester_submit_week_for_approval.py | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/harvester_submit_week_for_approval.py b/harvester_submit_week_for_approval.py index 6f9e047..b52f6c9 100644 --- a/harvester_submit_week_for_approval.py +++ b/harvester_submit_week_for_approval.py @@ -3,6 +3,7 @@ import argparse from datetime import datetime, timedelta import subprocess +import sys from selenium.webdriver import Firefox from selenium.webdriver.common.by import By @@ -11,6 +12,8 @@ from selenium.webdriver.firefox.options import Options from selenium.webdriver.support import expected_conditions as expected from selenium.webdriver.support.wait import WebDriverWait +import requests + def login(driver, wait, email, password): driver.get('https://id.getharvest.com/harvest/sign_in') @@ -89,6 +92,61 @@ def get_password(command): return str(result.stdout, 'utf-8').rstrip() +class WeekIsComplete(object): + + def __init__(self, account_id, api_token, friday): + self.account_id = account_id + self.api_token = api_token + self.friday = friday + self._monday = None + self.days = {} + + # Add `self.days['2018-01-31'] = 0` for all weekdays + for i in range(5): + self.days[(self.monday + timedelta(days=i)).strftime('%F')] = 0 + + def check(self): + time_entries = self._fetch_week() + days = self.days.keys() + + for entry in time_entries['time_entries']: + if entry['spent_date'] in days: + self.days[entry['spent_date']] += 1 + + for _, count in self.days.items(): + if count == 0: + raise IncompleteWeekError + + return True + + def _fetch_week(self): + r = requests.get( + 'https://api.harvestapp.com/api/v2/time_entries', + headers={ + 'Harvest-Account-ID': self.account_id, + 'Authorization': 'Bearer {}'.format(self.api_token), + 'User-Agent': 'harvester-submit-week-for-approval (TODO email address or link to app)', + 'Content-Type': 'application/json', + }, + params={ + 'from': self.monday.strftime('%F'), + 'to': self.friday.strftime('%F'), + }) + + return r.json() + + @property + def monday(self): + if not self._monday: + self._monday = self.friday - timedelta(days=4) + + return self._monday + + +class IncompleteWeekError(RuntimeError): + pass + + if __name__ == "__main__": parser = argparse.ArgumentParser( description='Submit the most recent Harvest timesheet for approval.') @@ -107,6 +165,19 @@ if __name__ == "__main__": args = parser.parse_args() + # Don't submit unless there is at least 1 time sheet logged for each day + # that week + try: + WeekIsComplete( + account_id='', + api_token='', + friday=most_recent_friday() + ).check() + except IncompleteWeekError: + print('Week was incomplete') + + sys.exit(1) + options = Options() options.add_argument('-headless') driver = Firefox( |
