From 98f1730ac2762365662f0f5de28c559daa89a9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Murta?= Date: Sun, 9 Oct 2022 22:27:53 +0100 Subject: [PATCH] Add period option to transactions download The period will only apply after the transactions have been received, since if sent on the request, credit cards seem to use the value date instead of the booking date, rendering the feature useless. Also adds some robustness to the download of the transactions, by adding a retry in case of timeout. --- pfbudget/cli/runnable.py | 11 +++++++---- pfbudget/input/nordigen.py | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/pfbudget/cli/runnable.py b/pfbudget/cli/runnable.py index c228670..4883854 100644 --- a/pfbudget/cli/runnable.py +++ b/pfbudget/cli/runnable.py @@ -219,15 +219,13 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: p_nordigen_download = subparsers.add_parser( "download", description="Downloads transactions using Nordigen API", - parents=[help], + parents=[help, period], formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) p_nordigen_download.add_argument("--id", nargs="+", type=str) p_nordigen_download.add_argument("--name", nargs="+", type=str) p_nordigen_download.add_argument("--all", action="store_true") - p_nordigen_download.set_defaults( - func=lambda args: manager.parser(NordigenInput(manager, vars(args))) - ) + p_nordigen_download.set_defaults(func=lambda args: download(manager, args)) """ List available banks on Nordigen API @@ -315,6 +313,11 @@ def nordigen_banks(manager: Manager, args): input.list(vars(args)["country"][0]) +def download(manager: Manager, args): + start, end = pfbudget.utils.parse_args_period(args) + manager.parser(NordigenInput(manager, vars(args), start, end)) + + def run(): manager = Manager(DEFAULT_DB) args = argparser(manager).parse_args() diff --git a/pfbudget/input/nordigen.py b/pfbudget/input/nordigen.py index ddfe86b..541fce8 100644 --- a/pfbudget/input/nordigen.py +++ b/pfbudget/input/nordigen.py @@ -1,3 +1,6 @@ +from datetime import date +from time import sleep +from requests import ReadTimeout from dotenv import load_dotenv from nordigen import NordigenClient from uuid import uuid4 @@ -12,7 +15,7 @@ load_dotenv() class NordigenInput(Input): - def __init__(self, manager, options: dict = {}): + def __init__(self, manager, options: dict = {}, start=date.min, end=date.max): super().__init__(manager) self._client = NordigenClient( secret_key=os.environ.get("SECRET_KEY"), @@ -21,7 +24,7 @@ class NordigenInput(Input): self.client.token = self.__token() - print(options) + # print(options) if "all" in options and options["all"]: self.__banks = self.manager.get_banks() @@ -36,22 +39,45 @@ class NordigenInput(Input): else: self.__banks = None + self.__from = start + self.__to = end + def parse(self) -> Transactions: transactions = [] if not self.__banks: raise NoBankSelected for bank in self.__banks: + print(f"Downloading from {bank}...") requisition = self.client.requisition.get_requisition_by_id( bank.requisition_id ) for acc in requisition["accounts"]: account = self._client.account_api(acc) - d = account.get_transactions()["transactions"] + + retries = 0 + downloaded = {} + while retries < 3: + try: + downloaded = account.get_transactions() + break + except ReadTimeout: + retries += 1 + print(f"Request #{retries} timed-out, waiting 1s") + sleep(1) + + if not downloaded: + print(f"Couldn't download transactions for {account}") + continue + + converted = [ + convert(t, bank.name, bank.invert) + for t in downloaded["transactions"]["booked"] + ] transactions.extend( - [convert(t, bank.name, bank.invert) for t in d["booked"]] + [t for t in converted if self.__from <= t.date <= self.__to] ) return transactions