diff --git a/.gitignore b/.gitignore index b699a0b..57a8b05 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ .DS_Store +# apicheck +apitest.py + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..988937c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "/usr/local/bin/python3" +} \ No newline at end of file diff --git a/apitest.py b/apitest.py new file mode 100644 index 0000000..99beeec --- /dev/null +++ b/apitest.py @@ -0,0 +1,24 @@ +""" +Use to figure out if the issue with YNAB component is related to the +component itself or the package it uses to interact with YNAB + +To run, you must have python3 and ynab-sdk installed on the machine +Install using pip3 install ynab-sdk + +Replace API_KEY_HERE with your API key +Run the file using python3 apitest.py + +If everything works, you should see a summary of your budgets +Otherwise you will see an error +""" + +from ynab_sdk import YNAB + +try: + api_key = "API_KEY_HERE" + apicheck = YNAB(api_key) + # print(apicheck.budgets.get_budgets()) + # data = apicheck.budgets.get_budget("BUDGET_ID") + # print(data.data.budget.id) +except Exception: + raise diff --git a/custom_components/ynab/__init__.py b/custom_components/ynab/__init__.py index 00cddbb..e436a28 100644 --- a/custom_components/ynab/__init__.py +++ b/custom_components/ynab/__init__.py @@ -66,7 +66,7 @@ async def async_setup(hass, config): # get global config budget = config[DOMAIN].get("budget") - _LOGGER.debug("Using budget - %s", budget) + _LOGGER.debug("YAML configured budget - %s", budget) if config[DOMAIN].get("categories") is not None: categories = config[DOMAIN].get("categories") @@ -101,112 +101,110 @@ def __init__(self, hass, config): @Throttle(MIN_TIME_BETWEEN_UPDATES) async def update_data(self): """Update data.""" - try: - # setup YNAB API - self.ynab = YNAB(self.api_key) - self.raw_budget = await self.hass.async_add_executor_job( - self.ynab.budgets.get_budget, self.budget - ) - self.get_data = self.raw_budget.data.budget - # get to be budgeted data - self.hass.data[DOMAIN_DATA]["to_be_budgeted"] = ( - self.get_data.months[0].to_be_budgeted / 1000 - ) - _LOGGER.debug( - "Recieved data for: to be budgeted: %s", - (self.get_data.months[0].to_be_budgeted / 1000), - ) - - # get unapproved transactions - unapproved_transactions = len( - [t.amount for t in self.get_data.transactions if t.approved is not True] - ) - self.hass.data[DOMAIN_DATA]["need_approval"] = unapproved_transactions - _LOGGER.debug( - "Recieved data for: unapproved transactions: %s", - unapproved_transactions, - ) - - # get number of uncleared transactions - uncleared_transactions = len( - [ - t.amount - for t in self.get_data.transactions - if t.cleared == "uncleared" - ] - ) - self.hass.data[DOMAIN_DATA][ - "uncleared_transactions" - ] = uncleared_transactions - _LOGGER.debug( - "Recieved data for: uncleared transactions: %s", uncleared_transactions - ) - - total_balance = 0 - # get account data - for a in self.get_data.accounts: - if a.on_budget: - total_balance += a.balance - - # get to be budgeted data - self.hass.data[DOMAIN_DATA]["total_balance"] = total_balance / 1000 - _LOGGER.debug( - "Recieved data for: total balance: %s", - (self.hass.data[DOMAIN_DATA]["total_balance"]), - ) + # setup YNAB API + self.ynab = YNAB(self.api_key) + self.all_budgets = await self.hass.async_add_executor_job( + self.ynab.budgets.get_budgets + ) + self.raw_budget = await self.hass.async_add_executor_job( + self.ynab.budgets.get_budget, self.budget + ) - # get current month data - for m in self.get_data.months: - if m.month != date.today().strftime("%Y-%m-01"): - continue - else: - # budgeted - self.hass.data[DOMAIN_DATA]["budgeted_this_month"] = ( - m.budgeted / 1000 - ) - _LOGGER.debug( - "Recieved data for: budgeted this month: %s", - self.hass.data[DOMAIN_DATA]["budgeted_this_month"], - ) + # get budget summary + self.get_all_budgets = self.all_budgets.data.budgets + if self.get_all_budgets: + _LOGGER.debug("Found %s budgets", len(self.get_all_budgets)) + for budget in self.get_all_budgets: + _LOGGER.debug("Budget name: %s - id: %s", budget.name, budget.id) + else: + _LOGGER.errors("Unable to retrieve budgets summary") + + self.get_data = self.raw_budget.data.budget + _LOGGER.debug("Retrieving data from budget id: %s", self.get_data.id) + + # get to be budgeted data + self.hass.data[DOMAIN_DATA]["to_be_budgeted"] = ( + self.get_data.months[0].to_be_budgeted / 1000 + ) + _LOGGER.debug( + "Received data for: to be budgeted: %s", + (self.get_data.months[0].to_be_budgeted / 1000), + ) - # activity - self.hass.data[DOMAIN_DATA]["activity_this_month"] = ( - m.activity / 1000 - ) - _LOGGER.debug( - "Recieved data for: activity this month: %s", - self.hass.data[DOMAIN_DATA]["activity_this_month"], - ) + # get unapproved transactions + unapproved_transactions = len( + [t.amount for t in self.get_data.transactions if t.approved is not True] + ) + self.hass.data[DOMAIN_DATA]["need_approval"] = unapproved_transactions + _LOGGER.debug( + "Received data for: unapproved transactions: %s", + unapproved_transactions, + ) - # get number of overspend categories - overspent_categories = len( - [c.balance for c in m.categories if c.balance < 0] - ) - self.hass.data[DOMAIN_DATA][ - "overspent_categories" - ] = overspent_categories - _LOGGER.debug( - "Recieved data for: overspent categories: %s", - overspent_categories, - ) + # get number of uncleared transactions + uncleared_transactions = len( + [t.amount for t in self.get_data.transactions if t.cleared == "uncleared"] + ) + self.hass.data[DOMAIN_DATA]["uncleared_transactions"] = uncleared_transactions + _LOGGER.debug( + "Received data for: uncleared transactions: %s", uncleared_transactions + ) - # get remaining category balances - for c in m.categories: - if c.name not in self.categories: - continue - else: - self.hass.data[DOMAIN_DATA].update( - [(c.name, c.balance / 1000)] - ) - _LOGGER.debug( - "Recieved data for categories: %s", - [c.name, c.balance / 1000], - ) + total_balance = 0 + # get account data + for a in self.get_data.accounts: + if a.on_budget: + total_balance += a.balance + + # get to be budgeted data + self.hass.data[DOMAIN_DATA]["total_balance"] = total_balance / 1000 + _LOGGER.debug( + "Received data for: total balance: %s", + (self.hass.data[DOMAIN_DATA]["total_balance"]), + ) - # print(self.hass.data[DOMAIN_DATA]) - except Exception as error: - _LOGGER.error("Could not retrieve data - verify API key %s", error) + # get current month data + for m in self.get_data.months: + if m.month != date.today().strftime("%Y-%m-01"): + continue + else: + # budgeted + self.hass.data[DOMAIN_DATA]["budgeted_this_month"] = m.budgeted / 1000 + _LOGGER.debug( + "Received data for: budgeted this month: %s", + self.hass.data[DOMAIN_DATA]["budgeted_this_month"], + ) + + # activity + self.hass.data[DOMAIN_DATA]["activity_this_month"] = m.activity / 1000 + _LOGGER.debug( + "Received data for: activity this month: %s", + self.hass.data[DOMAIN_DATA]["activity_this_month"], + ) + + # get number of overspend categories + overspent_categories = len( + [c.balance for c in m.categories if c.balance < 0] + ) + self.hass.data[DOMAIN_DATA][ + "overspent_categories" + ] = overspent_categories + _LOGGER.debug( + "Received data for: overspent categories: %s", + overspent_categories, + ) + + # get remaining category balances + for c in m.categories: + if c.name not in self.categories: + continue + else: + self.hass.data[DOMAIN_DATA].update([(c.name, c.balance / 1000)]) + _LOGGER.debug( + "Received data for categories: %s", + [c.name, c.balance / 1000], + ) async def check_files(hass): @@ -236,9 +234,15 @@ async def check_url(): try: async with aiohttp.ClientSession() as session: async with session.get(url) as response: - if response.status: + if response.status == 200: _LOGGER.debug("Connection with YNAB established") result = True + else: + _LOGGER.debug( + "Connection with YNAB established, " + "but wasnt able to communicate with API endpoint" + ) + result = False except Exception as error: _LOGGER.debug("Unable to establish connection with YNAB - %s", error) result = False diff --git a/custom_components/ynab/const.py b/custom_components/ynab/const.py index 46f6786..c6eaf7b 100644 --- a/custom_components/ynab/const.py +++ b/custom_components/ynab/const.py @@ -4,7 +4,7 @@ PLATFORMS = ["sensor"] REQUIRED_FILES = ["const.py", "manifest.json", "sensor.py"] -VERSION = "0.1.8" +VERSION = "0.1.9" ISSUE_URL = "https://github.com/wxt9861/ynab/issues" STARTUP = """ diff --git a/custom_components/ynab/manifest.json b/custom_components/ynab/manifest.json index 75612a8..1bc2944 100644 --- a/custom_components/ynab/manifest.json +++ b/custom_components/ynab/manifest.json @@ -5,6 +5,6 @@ "issue_tracker": "https://github.com/wxt9861/ynab/issues", "dependencies": [], "codeowners": ["@wxt9861"], - "requirements": ["ynab-sdk==0.2.3"], - "version": "0.1.8" + "requirements": ["ynab-sdk==0.2.4"], + "version": "0.1.9" }