Skip to content

Commit

Permalink
Merge pull request #3 from dnbasta/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
dnbasta authored Apr 26, 2024
2 parents 072204d + 1c906e8 commit d7fee85
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 14 deletions.
11 changes: 10 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,20 @@ def mock_original_transaction(request):
import_payee_name_original='ipno',
transaction_date=date(2024, 1, 1),
approved=False,
cleared='uncleared')
cleared='uncleared',
transfer_transaction_id=None)


@pytest.fixture
def mock_category_repo():
return CategoryRepo(categories=[
CategoryGroup(name='group1', categories=frozenset([Category(id='cid1', name='c_name')])),
CategoryGroup(name='group2', categories=frozenset([Category(id='cid2', name='c_name')]))])


@pytest.fixture
def mock_transaction_dict():
return dict(id='id', amount=1000, date='2024-01-01', category_name='category', category_id='categoryid',
payee_name='payee', payee_id='payeeid', flag_color=None, memo=None, subtransactions=[],
import_payee_name_original=None, import_payee_name=None, transfer_account_id='transfer_account_id',
approved=False, cleared='uncleared', transfer_transaction_id='transfer_transaction_id')
14 changes: 14 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from requests import Response

from ynabtransactionadjuster import Transaction
from ynabtransactionadjuster.client import Client
from ynabtransactionadjuster.models.payee import Payee

Expand Down Expand Up @@ -46,3 +47,16 @@ def test_fetch_payees(mock_get):
assert p_list[0].name == 'p_name'
assert p_list[0].id == 'p_id'
assert p_list[0].transfer_account_id == 't_id'


@patch('ynabtransactionadjuster.client.requests.get')
def test_fetch_transaction(mock_get, mock_transaction_dict):
# Arrange
resp = MagicMock(spec=Response)
resp.json.return_value = {'data': {'transaction': mock_transaction_dict}}
mock_get.return_value = resp
client = Client(token=MagicMock(), budget=MagicMock(), account=MagicMock())

# Act
t = client.fetch_transaction('transaction_id')
assert isinstance(t, Transaction)
12 changes: 3 additions & 9 deletions tests/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,21 @@
from ynabtransactionadjuster.models import Transaction, Category, Payee


@pytest.fixture
def mock_transaction_dict():
return dict(id='id', amount=1000, date='2024-01-01', category_name='category', category_id='categoryid',
payee_name='payee', payee_id='payeeid', flag_color=None, memo=None, subtransactions=[],
import_payee_name_original=None, import_payee_name=None, transfer_account_id=None,
approved=False, cleared='uncleared')


def test_from_dict(mock_transaction_dict):
o = Transaction.from_dict(mock_transaction_dict)
assert o.id == mock_transaction_dict['id']
assert o.amount == mock_transaction_dict['amount']
assert o.transaction_date == datetime.strptime(mock_transaction_dict['date'], '%Y-%m-%d').date()
assert o.category == Category(id=mock_transaction_dict['category_id'], name=mock_transaction_dict['category_name'])
assert o.payee == Payee(id=mock_transaction_dict['payee_id'], name=mock_transaction_dict['payee_name'])
assert o.payee == Payee(id=mock_transaction_dict['payee_id'], name=mock_transaction_dict['payee_name'],
transfer_account_id=mock_transaction_dict['transfer_account_id'])
assert o.flag_color == mock_transaction_dict['flag_color']
assert o.memo == mock_transaction_dict['memo']
assert o.import_payee_name_original == mock_transaction_dict['import_payee_name_original']
assert o.import_payee_name == mock_transaction_dict['import_payee_name']
assert o.approved == mock_transaction_dict['approved']
assert o.cleared == mock_transaction_dict['cleared']
assert o.transfer_transaction_id == mock_transaction_dict['transfer_transaction_id']
assert not o.subtransactions


Expand Down
14 changes: 11 additions & 3 deletions ynabtransactionadjuster/adjuster.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def dry_run(self, pretty_print: bool = False) -> List[ModifiedTransaction]:
:raises AdjustError: if there is any error during the adjust process
:raises HTTPError: if there is any error with the YNAB API (e.g. wrong credentials)
"""
self.check_signatures()
self._check_signatures()
filtered_transactions = self.filter(self.transactions)
s = Serializer(transactions=filtered_transactions, adjust_func=self.adjust, categories=self.categories)
modified_transactions = s.run()
Expand All @@ -92,7 +92,7 @@ def run(self) -> int:
:raises AdjustError: if there is any error during the adjust process
:raises HTTPError: if there is any error with the YNAB API (e.g. wrong credentials)
"""
self.check_signatures()
self._check_signatures()
filtered_transactions = self.filter(self.transactions)
s = Serializer(transactions=filtered_transactions, adjust_func=self.adjust, categories=self.categories)
modified_transactions = s.run()
Expand All @@ -102,6 +102,14 @@ def run(self) -> int:
return updated
return 0

def check_signatures(self):
def _check_signatures(self):
SignatureChecker(func=self.filter, parent_func=Adjuster.filter).check()
SignatureChecker(func=self.adjust, parent_func=Adjuster.adjust).check()

def fetch_transaction(self, transaction_id: str) -> Transaction:
"""Fetches an individual transaction from the YNAB account
:param transaction_id: Transaction ID of the transaction to be fetched
"""
client = Client.from_credentials(credentials=self.credentials)
return client.fetch_transaction(transaction_id=transaction_id)
5 changes: 5 additions & 0 deletions ynabtransactionadjuster/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ def fetch_transactions(self) -> List[Transaction]:
transactions = [Transaction.from_dict(t) for t in transaction_dicts]
return transactions

def fetch_transaction(self, transaction_id: str) -> Transaction:
r = requests.get(f'{YNAB_BASE_URL}/budgets/{self._budget}/transactions/{transaction_id}', headers=self._header)
r.raise_for_status()
return Transaction.from_dict(r.json()['data']['transaction'])

def update_transactions(self, transactions: List[ModifiedTransaction]) -> int:
"""Updates transactions in YNAB. The updates are done in bulk.
Expand Down
5 changes: 4 additions & 1 deletion ynabtransactionadjuster/models/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Transaction:
:ivar import_payee_name_original: The original payee or memo as recorded by the bank
:ivar approved: approval status of the original transaction
:ivar cleared: clearance state of the original transaction
:ivar transfer_transaction_id: id of the originating transaction if transaction is transfer
"""
id: str
transaction_date: date
Expand All @@ -35,6 +36,7 @@ class Transaction:
subtransactions: Tuple[SubTransaction, ...]
cleared: Literal['uncleared', 'cleared', 'reconciled']
approved: bool
transfer_transaction_id: Optional[str]

@classmethod
def from_dict(cls, t_dict: dict) -> 'Transaction':
Expand Down Expand Up @@ -64,7 +66,8 @@ def build_subtransaction(s_dict: dict) -> SubTransaction:
subtransactions=tuple([build_subtransaction(st) for st in t_dict['subtransactions']]),
amount=t_dict['amount'],
approved=t_dict['approved'],
cleared=t_dict['cleared'])
cleared=t_dict['cleared'],
transfer_transaction_id=t_dict['transfer_transaction_id'])

def as_dict(self) -> dict:
return asdict(self)
Expand Down

0 comments on commit d7fee85

Please sign in to comment.