From 2f9fb31baf1c884764815becc08ce150be56ba78 Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Fri, 25 Mar 2022 18:46:08 +0000 Subject: [PATCH] Make Nordigen and TrueLayer compatible with Transactions --- handler/sinks/__init__.py | 7 ++++--- handler/sinks/nordigen.py | 29 ++++++++++++++++++++++++++++- handler/sinks/truelayer.py | 2 +- handler/transactions.py | 11 +++++------ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/handler/sinks/__init__.py b/handler/sinks/__init__.py index 81f5660..75d8795 100644 --- a/handler/sinks/__init__.py +++ b/handler/sinks/__init__.py @@ -33,12 +33,12 @@ class Sinks(util.Base): self.truelayer = sinks.truelayer.TrueLayer(self) # setattr(self.truelayer, "sinks", self) - def got_transactions(self, bank, account_id, transactions): + def got_transactions(self, subclass, account_id, transactions): if not transactions: return False transaction_ids = [x["transaction_id"] for x in transactions] - new_key_name = f"new.transactions.{bank}.{account_id}" - old_key_name = f"transactions.{bank}.{account_id}" + new_key_name = f"new.transactions.{subclass}.{account_id}" + old_key_name = f"transactions.{subclass}.{account_id}" # for transaction_id in transaction_ids: if not transaction_ids: return @@ -53,6 +53,7 @@ class Sinks(util.Base): # Rename the new key to the old key so we can run the diff again r.rename(new_key_name, old_key_name) for transaction in new_transactions: + transaction["subclass"] = subclass self.tx.transaction(transaction) def got_account_info(self, subclass, account_infos): diff --git a/handler/sinks/nordigen.py b/handler/sinks/nordigen.py index 1ebe03b..fc7624b 100644 --- a/handler/sinks/nordigen.py +++ b/handler/sinks/nordigen.py @@ -45,6 +45,14 @@ class Nordigen(util.Base): self.sinks.got_account_info("nordigen", account_infos) + self.lc_tx = LoopingCall(self.transaction_loop) + self.lc_tx.start(int(settings.Nordigen.RefreshSec)) + + def transaction_loop(self): + for account_id in self.banks: + transactions = self.get_transactions(account_id) + self.sinks.got_transactions("nordigen", account_id, transactions) + def get_access_token(self): """ Get an access token. @@ -246,6 +254,23 @@ class Nordigen(util.Base): to_return[req["institution_id"]] = [account_info] return to_return + def normalise_transactions(self, transactions): + for transaction in transactions: + # Rename ID + transaction["transaction_id"] = transaction["transactionId"] + del transaction["transactionId"] + + # Rename timestamp + transaction["timestamp"] = transaction["bookingDate"] + del transaction["bookingDate"] + + transaction["amount"] = float(transaction["transactionAmount"]["amount"]) + transaction["currency"] = transaction["transactionAmount"]["currency"] + del transaction["transactionAmount"] + + transaction["reference"] = transaction["remittanceInformationUnstructured"] + del transaction["remittanceInformationUnstructured"] + def get_transactions(self, account_id): """ Get all transactions for an account. @@ -257,4 +282,6 @@ class Nordigen(util.Base): path = f"{settings.Nordigen.Base}/accounts/{account_id}/transactions/" r = requests.get(path, headers=headers) obj = TXRoot.from_json(r.content) - return obj.to_dict()["transactions"]["booked"] + parsed = obj.to_dict()["transactions"]["booked"] + self.normalise_transactions(parsed) + return parsed diff --git a/handler/sinks/truelayer.py b/handler/sinks/truelayer.py index 4050444..6ed0d19 100644 --- a/handler/sinks/truelayer.py +++ b/handler/sinks/truelayer.py @@ -54,7 +54,7 @@ class TrueLayer(util.Base): for account_id in self.banks[bank]: # account_data = self.get_account(bank, account_id) transactions = self.get_transactions(bank, account_id) - self.sinks.got_transactions(bank, account_id, transactions) + self.sinks.got_transactions("truelayer", account_id, transactions) def add_refresh_token(self, refresh_token): """ diff --git a/handler/transactions.py b/handler/transactions.py index 1c5637b..7746737 100644 --- a/handler/transactions.py +++ b/handler/transactions.py @@ -77,7 +77,6 @@ class Transactions(util.Base): """ ts = data["timestamp"] txid = data["transaction_id"] - txtype = data["transaction_type"] if "amount" not in data: return if "currency" not in data: @@ -87,27 +86,27 @@ class Transactions(util.Base): self.log.info(f"Ignoring transaction with negative/zero amount: {txid}") return currency = data["currency"] - description = data["description"] if "meta" in data: if "provider_reference" in data["meta"]: reference = data["meta"]["provider_reference"] else: reference = "not_set" + elif "reference" in data: + reference = data["reference"] else: reference = "not_set" - + subclass = data["subclass"] to_store = { "trade_id": "", + "subclass": subclass, "ts": ts, "txid": txid, - "txtype": txtype, "reference": reference, "amount": amount, "currency": currency, - "description": description, } self.log.info(f"Transaction processed: {dumps(to_store, indent=2)}") - self.irc.sendmsg(f"AUTO Incoming transaction: {amount}{currency} ({reference}) - {description}") + self.irc.sendmsg(f"AUTO Incoming transaction on {subclass}: {amount}{currency} ({reference})") # Partial reference implementation # Account for silly people not removing the default string # Split the reference into parts