Compare commits
6 Commits
e3756fa442
...
5f2cb6fcf5
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f2cb6fcf5 | |||
| 9345530f06 | |||
| a364d7b46d | |||
| 647db5e86f | |||
| c41bfb4bdf | |||
| a0d3af715e |
@ -194,19 +194,19 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
|||||||
p_nordigen_access.set_defaults(func=lambda args: NordigenInput(manager).token())
|
p_nordigen_access.set_defaults(func=lambda args: NordigenInput(manager).token())
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Access to Nordigen API
|
(Re)new bank requisition ID
|
||||||
"""
|
"""
|
||||||
p_nordigen_access = subparsers.add_parser(
|
p_nordigen_access = subparsers.add_parser(
|
||||||
"renew",
|
"renew",
|
||||||
description="Renew the requisition ID",
|
description="(Re)new the Bank requisition ID",
|
||||||
parents=[help],
|
parents=[help],
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||||
)
|
)
|
||||||
p_nordigen_access.add_argument("institution", nargs=1, type=str)
|
p_nordigen_access.add_argument("name", nargs=1, type=str)
|
||||||
p_nordigen_access.add_argument("country", nargs=1, type=str)
|
p_nordigen_access.add_argument("country", nargs=1, type=str)
|
||||||
p_nordigen_access.set_defaults(
|
p_nordigen_access.set_defaults(
|
||||||
func=lambda args: NordigenInput().requisition(
|
func=lambda args: NordigenInput(manager).requisition(
|
||||||
args.institution[0], args.country[0]
|
args.name[0], args.country[0]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class Transaction:
|
|||||||
self.description = " ".join(arg[1].split())
|
self.description = " ".join(arg[1].split())
|
||||||
self.bank = arg[2]
|
self.bank = arg[2]
|
||||||
if type(arg[3]) is float:
|
if type(arg[3]) is float:
|
||||||
self.value = arg[3]
|
self.value = Decimal(str(arg[3]))
|
||||||
else:
|
else:
|
||||||
self.value = Decimal(args[3])
|
self.value = Decimal(args[3])
|
||||||
self.category = arg[4]
|
self.category = arg[4]
|
||||||
@ -118,6 +118,7 @@ class Bank:
|
|||||||
bic: str
|
bic: str
|
||||||
requisition_id: str
|
requisition_id: str
|
||||||
invert: bool
|
invert: bool
|
||||||
|
offset: int
|
||||||
key: PrimaryKey = PrimaryKey.ID
|
key: PrimaryKey = PrimaryKey.ID
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,8 @@ CREATE TABLE IF NOT EXISTS banks (
|
|||||||
nordigen_id TEXT,
|
nordigen_id TEXT,
|
||||||
nordigen_name TEXT,
|
nordigen_name TEXT,
|
||||||
requisition_id TEXT,
|
requisition_id TEXT,
|
||||||
invert INTEGER
|
invert INTEGER,
|
||||||
|
offset INTEGER
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -62,7 +63,8 @@ class DbBank:
|
|||||||
nordigen_id: str
|
nordigen_id: str
|
||||||
nordigen_name: str
|
nordigen_name: str
|
||||||
requisition_id: str
|
requisition_id: str
|
||||||
invert: bool
|
invert: bool = False
|
||||||
|
offset: int = 0
|
||||||
|
|
||||||
def tuple(self):
|
def tuple(self):
|
||||||
return (
|
return (
|
||||||
@ -72,6 +74,7 @@ class DbBank:
|
|||||||
self.nordigen_name,
|
self.nordigen_name,
|
||||||
self.requisition_id,
|
self.requisition_id,
|
||||||
int(self.invert),
|
int(self.invert),
|
||||||
|
self.offset,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
from datetime import date
|
from datetime import date
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from requests import ReadTimeout
|
from requests import HTTPError, ReadTimeout
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from nordigen import NordigenClient
|
from nordigen import NordigenClient
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
@ -64,16 +65,22 @@ class NordigenInput(Input):
|
|||||||
break
|
break
|
||||||
except ReadTimeout:
|
except ReadTimeout:
|
||||||
retries += 1
|
retries += 1
|
||||||
print(f"Request #{retries} timed-out, waiting 1s")
|
print(f"Request #{retries} timed-out, retrying in 1s")
|
||||||
|
sleep(1)
|
||||||
|
except HTTPError as e:
|
||||||
|
retries += 1
|
||||||
|
print(f"Request #{retries} failed with {e}, retrying in 1s")
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
if not downloaded:
|
if not downloaded:
|
||||||
print(f"Couldn't download transactions for {account}")
|
print(f"Couldn't download transactions for {account}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
with open("json/" + bank.name + ".json", "w") as f:
|
||||||
|
json.dump(downloaded, f)
|
||||||
|
|
||||||
converted = [
|
converted = [
|
||||||
convert(t, bank.name, bank.invert)
|
convert(t, bank) for t in downloaded["transactions"]["booked"]
|
||||||
for t in downloaded["transactions"]["booked"]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
transactions.extend(
|
transactions.extend(
|
||||||
|
|||||||
@ -4,7 +4,7 @@ from importlib import import_module
|
|||||||
import datetime as dt
|
import datetime as dt
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from pfbudget.common.types import Transaction
|
from pfbudget.common.types import NoBankSelected, Transaction, Transactions
|
||||||
from pfbudget.utils import utils
|
from pfbudget.utils import utils
|
||||||
|
|
||||||
Index = namedtuple(
|
Index = namedtuple(
|
||||||
@ -43,7 +43,7 @@ Options = namedtuple(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_data(filename: str, args: dict) -> None:
|
def parse_data(filename: str, args: dict) -> Transactions:
|
||||||
cfg: dict = yaml.safe_load(open("parsers.yaml"))
|
cfg: dict = yaml.safe_load(open("parsers.yaml"))
|
||||||
assert (
|
assert (
|
||||||
"Banks" in cfg
|
"Banks" in cfg
|
||||||
@ -57,17 +57,25 @@ def parse_data(filename: str, args: dict) -> None:
|
|||||||
bank = args["bank"][0]
|
bank = args["bank"][0]
|
||||||
creditcard = None if not args["creditcard"] else args["creditcard"][0]
|
creditcard = None if not args["creditcard"] else args["creditcard"][0]
|
||||||
|
|
||||||
if not creditcard:
|
try:
|
||||||
options: dict = cfg[bank]
|
options: dict = cfg[bank]
|
||||||
else:
|
except KeyError as e:
|
||||||
options: dict = cfg[bank][creditcard]
|
banks = cfg["Banks"]
|
||||||
|
raise NoBankSelected(f"{e} not a valid bank, try one of {banks}")
|
||||||
|
|
||||||
|
if creditcard:
|
||||||
|
try:
|
||||||
|
options = options[creditcard]
|
||||||
|
except KeyError as e:
|
||||||
|
creditcards = cfg["CreditCards"]
|
||||||
|
raise NoBankSelected(f"{e} not a valid bank, try one of {creditcards}")
|
||||||
bank += creditcard
|
bank += creditcard
|
||||||
|
|
||||||
if args["category"]:
|
if args["category"]:
|
||||||
options["category"] = args["category"][0]
|
options["category"] = args["category"][0]
|
||||||
|
|
||||||
if options.get("additional_parser"):
|
if options.get("additional_parser"):
|
||||||
parser = getattr(import_module("pfbudget.parsers"), bank)
|
parser = getattr(import_module("pfbudget.input.parsers"), bank)
|
||||||
transactions = parser(filename, bank, options).parse()
|
transactions = parser(filename, bank, options).parse()
|
||||||
else:
|
else:
|
||||||
transactions = Parser(filename, bank, options).parse()
|
transactions = Parser(filename, bank, options).parse()
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
from datetime import timedelta
|
||||||
from functools import singledispatch
|
from functools import singledispatch
|
||||||
|
|
||||||
from pfbudget.common.types import Bank, Transaction, TransactionError
|
from pfbudget.common.types import Bank, Transaction, TransactionError
|
||||||
@ -13,7 +14,15 @@ def convert(t):
|
|||||||
|
|
||||||
@convert.register
|
@convert.register
|
||||||
def _(t: Transaction) -> DbTransaction:
|
def _(t: Transaction) -> DbTransaction:
|
||||||
return DbTransaction(t.date, t.description, t.bank, t.value, t.category, t.original, t.additional_comment)
|
return DbTransaction(
|
||||||
|
t.date,
|
||||||
|
t.description,
|
||||||
|
t.bank,
|
||||||
|
t.value,
|
||||||
|
t.category,
|
||||||
|
t.original,
|
||||||
|
t.additional_comment,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@convert.register
|
@convert.register
|
||||||
@ -26,23 +35,38 @@ def _(db: DbTransaction) -> Transaction:
|
|||||||
|
|
||||||
@convert.register
|
@convert.register
|
||||||
def _(db: DbBank, key: str = "") -> Bank:
|
def _(db: DbBank, key: str = "") -> Bank:
|
||||||
return Bank(db.name, db.bic, db.requisition_id, db.invert, key=key)
|
bank = Bank(db.name, db.bic, db.requisition_id, db.invert, db.offset, key=key)
|
||||||
|
if not bank.invert:
|
||||||
|
bank.invert = False
|
||||||
|
if not bank.offset:
|
||||||
|
bank.offset = 0
|
||||||
|
return bank
|
||||||
|
|
||||||
|
|
||||||
@convert.register
|
@convert.register
|
||||||
def _(bank: Bank, key: str = "") -> DbBank:
|
def _(bank: Bank) -> DbBank:
|
||||||
return DbBank(bank.name, bank.bic, "", "", bank.requisition_id, bank.invert)
|
bank = DbBank(
|
||||||
|
bank.name, bank.bic, "", "", bank.requisition_id, bank.invert, bank.offset
|
||||||
|
)
|
||||||
|
if not bank.invert:
|
||||||
|
bank.invert = False
|
||||||
|
if not bank.offset:
|
||||||
|
bank.offset = 0
|
||||||
|
return bank
|
||||||
|
|
||||||
|
|
||||||
@convert.register
|
@convert.register
|
||||||
def _(json: dict, bank: str, invert: bool) -> Transaction:
|
def _(json: dict, bank: Bank) -> Transaction:
|
||||||
i = -1 if invert else 1
|
i = -1 if bank.invert else 1
|
||||||
try:
|
try:
|
||||||
return Transaction(
|
transaction = Transaction(
|
||||||
json["bookingDate"],
|
json["bookingDate"],
|
||||||
json["remittanceInformationUnstructured"],
|
json["remittanceInformationUnstructured"],
|
||||||
bank,
|
bank.name,
|
||||||
i * parse_decimal(json["transactionAmount"]["amount"]),
|
i * parse_decimal(json["transactionAmount"]["amount"]),
|
||||||
)
|
)
|
||||||
|
transaction.date += timedelta(days=bank.offset)
|
||||||
|
return transaction
|
||||||
|
|
||||||
except TransactionError:
|
except TransactionError:
|
||||||
print(f"{json} is in the wrong format")
|
print(f"{json} is in the wrong format")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user