From a4844550ac96c2e6dedae0f7df654c776ede084e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Fri, 25 Oct 2024 09:52:46 +0200 Subject: [PATCH] feat: add transactions API to fetch last transactions and account info Fixes #34 Replaces #4 --- CHANGELOG.md | 3 +++ README.rst | 20 ++++++++++++++++++++ fiobank.py | 28 +++++++++++++++++++++++----- tests/test_fiobank.py | 17 +++++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 886ea98..bcdf561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Breaking * Dropped support for Python 3.6, 3.7 and 3.8 +### Features +* Added transactions API to fetch account info and transactions in one call + ### Fix * Added deprecation warning for decimal=False diff --git a/README.rst b/README.rst index 4a233d8..15f000c 100644 --- a/README.rst +++ b/README.rst @@ -59,6 +59,16 @@ Listing transactions within a period: 'transaction_id': 'XXXXXXXXXX' } +Getting transactions with account information in one request: + +.. code:: python + + >>> client.transaction('2013-01-20', '2013-03-20') + ( + {'currency': 'CZK', 'account_number_full': 'XXXXXXXXXX/2010', 'balance': 42.00, 'account_number': 'XXXXXXXXXX', 'bank_code': '2010'}, + 'transactions': + ) + Listing transactions from a single account statement: .. code:: python @@ -72,6 +82,16 @@ Listing the latest transactions: >>> client.last() # return transactions added from last listing >>> client.last(from_id='...') # sets cursor to given transaction_id and returns following transactions >>> client.last(from_date='2013-03-01') # sets cursor to given date and returns following transactions + +Getting the latest transactions with account information in one request: + +.. code:: python + + >>> client.last_transaction() + ( + {'currency': 'CZK', 'account_number_full': 'XXXXXXXXXX/2010', 'balance': 42.00, 'account_number': 'XXXXXXXXXX', 'bank_code': '2010'}, + 'transactions': + ) Conflict Error -------------- diff --git a/fiobank.py b/fiobank.py index 9004630..8dedb96 100644 --- a/fiobank.py +++ b/fiobank.py @@ -1,5 +1,8 @@ +from __future__ import annotations + from decimal import Decimal import re +from typing import Generator from datetime import datetime, date import warnings @@ -124,7 +127,7 @@ def _parse_info(self, data): # return data return info - def _parse_transactions(self, data): + def _parse_transactions(self, data: dict) -> Generator[dict]: schema = self.transaction_schema try: entries = data["accountStatement"]["transactionList"]["transaction"] # NOQA @@ -177,17 +180,24 @@ def info(self): data = self._request("periods", from_date=today, to_date=today) return self._parse_info(data) - def period(self, from_date, to_date): - data = self._request( + def _fetch_period(self, from_date: str | date | datetime, to_date: str | date | datetime) -> dict: + return self._request( "periods", from_date=coerce_date(from_date), to_date=coerce_date(to_date) ) + + def period(self, from_date: str | date | datetime, to_date: str | date | datetime) -> Generator[dict]: + data = self._fetch_period(from_date, to_date) return self._parse_transactions(data) + def transactions(self, from_date: str | date | datetime, to_date: str | date | datetime) -> tuple[dict, Generator[dict]]: + data = self._fetch_period(from_date, to_date) + return (self._parse_info(data), self._parse_transactions(data)) + def statement(self, year, number): data = self._request("by-id", year=year, number=number) return self._parse_transactions(data) - def last(self, from_id=None, from_date=None): + def _fetch_last(self, from_id: str | None=None, from_date : str | date | datetime | None=None) -> dict: if from_id and from_date: raise ValueError("Only one constraint is allowed.") @@ -196,4 +206,12 @@ def last(self, from_id=None, from_date=None): elif from_date: self._request("set-last-date", from_date=coerce_date(from_date)) - return self._parse_transactions(self._request("last")) + return self._request("last") + + + def last(self, from_id: str | None=None, from_date : str | date | datetime | None=None) -> Generator[dict]: + return self._parse_transactions(self._fetch_last(from_id, from_date)) + + def last_transactions(self, from_id: str | None=None, from_date : str | date | datetime | None=None) -> tuple[dict, Generator[dict]]: + data = self._fetch_last(from_id, from_date) + return (self._parse_info(data), self._parse_transactions(data)) diff --git a/tests/test_fiobank.py b/tests/test_fiobank.py index 13fa141..8768f1b 100644 --- a/tests/test_fiobank.py +++ b/tests/test_fiobank.py @@ -201,6 +201,23 @@ def test_transactions_integration(client_float, method, args, kwargs): assert count > 0 +@pytest.mark.parametrize( + "method,args,kwargs", + [ + ("transactions", [date(2016, 8, 4), date(2016, 8, 30)], {}), + ("transactions", ["2016-08-04", "2016-08-30"], {}), + ("last_transactions", [], {"from_id": 308}), + ("last_transactions", [], {"from_date": date(2016, 8, 4)}), + ("last_transactions", [], {"from_date": "2016-08-04"}), + ], +) +def test_transactions_api(client_decimal, method, args, kwargs): + info, transactions = getattr(client_decimal, method)(*args, **kwargs) + transaction = next(transactions) + assert transaction["amount"] == Decimal("-130.0") + assert info["balance"] == Decimal("2060.52") + + def test_period_coerces_date(transactions_json): client = FioBank("...")