Skip to content

Commit

Permalink
implemented logic to account for multiple or no accounts in requisition
Browse files Browse the repository at this point in the history
  • Loading branch information
daabel committed Feb 8, 2024
1 parent b1f4f70 commit bdf8d83
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 26 deletions.
43 changes: 43 additions & 0 deletions ynabapiimport/accountfetcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import List

from nordigen import NordigenClient
from requests import HTTPError

from ynabapiimport.models.exceptions import NoActiveAccountError, MultipleActiveAccountsError, NoRequisitionError


class AccountFetcher:

def __init__(self, client: NordigenClient, reference: str):
self._client = client
self._reference = reference

@staticmethod
def fetch_by_resource_id(resource_id: str, active_accounts: List[dict]) -> str:
try:
return next(a['id'] for a in active_accounts if a['resourceId'] == resource_id)
except StopIteration:
raise NoActiveAccountError(f"No active account with resource_id. Available accounts: {active_accounts}")

def fetch(self, resource_id: str = None) -> str:
req = self.fetch_requisition()

account_dicts = [{**self._client.account_api(id=a).get_details()['account'],
**{'id': a}} for a in req['accounts']]
active_accounts = [a for a in account_dicts if a['status'] == 'enabled']

if len(active_accounts) == 0:
raise NoActiveAccountError('No active accounts available in active requisition')
if resource_id:
return self.fetch_by_resource_id(resource_id=resource_id, active_accounts=active_accounts)
if len(active_accounts) > 1:
raise MultipleActiveAccountsError(f"There are multiple active accounts available in active requisition. "
f"Please provide resourceId in import_transaction() call. Available accounts: {active_accounts}")
return next(a['id'] for a in active_accounts)

def fetch_requisition(self) -> dict:
try:
results = self._client.requisition.get_requisitions()['results']
return next(r for r in results if r['status'] == 'LN' and r['reference'].split('::')[0] == self._reference)
except (HTTPError, StopIteration):
raise NoRequisitionError()
12 changes: 9 additions & 3 deletions ynabapiimport/gocardlessclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@

from nordigen import NordigenClient

from ynabapiimport.accountfetcher import AccountFetcher
from ynabapiimport.models.transaction import Transaction
from ynabapiimport.requisitionfetcher import RequisitionFetcher


class GocardlessClient:
def __init__(self, secret_id: str, secret_key: str):
self._client = NordigenClient(secret_key=secret_key, secret_id=secret_id)
self._client.generate_token()

def fetch_transactions(self, reference: str) -> List[Transaction]:
account_id = RequisitionFetcher(client=self._client).fetch(reference=reference)
def fetch_transactions(self, reference: str, resource_id: str) -> List[Transaction]:
af = AccountFetcher(client=self._client, reference=reference)

if resource_id:
account_id = af.fetch(resource_id=resource_id)
else:
account_id = af.fetch()

account = self._client.account_api(id=account_id)
transaction_dicts = account.get_transactions()['transactions']['booked']
transactions = [Transaction.from_dict(t) for t in transaction_dicts]
Expand Down
8 changes: 8 additions & 0 deletions ynabapiimport/models/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@

class NoRequisitionError(Exception):
pass


class NoActiveAccountError(Exception):
pass


class MultipleActiveAccountsError(Exception):
pass
21 changes: 0 additions & 21 deletions ynabapiimport/requisitionfetcher.py

This file was deleted.

4 changes: 2 additions & 2 deletions ynabapiimport/ynabapiimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def from_yaml(cls, path: str):
secret_key=config_dict['secret_key'],
token=config_dict['token'])

def import_transactions(self, reference: str, budget_id: str, account_id: str):
transactions = self._gocardless_client.fetch_transactions(reference=reference)
def import_transactions(self, reference: str, budget_id: str, account_id: str, resource_id: str = None):
transactions = self._gocardless_client.fetch_transactions(reference=reference, resource_id=resource_id)
i = self._ynab_client.insert(transactions, account_id=account_id, budget_id=budget_id)
print(f"inserted {i} transactions for {reference} into account {account_id}")

Expand Down

0 comments on commit bdf8d83

Please sign in to comment.