Adds new JSON parser and moves init to Manager
Adds a new abstract `Input` interface for the manager to use different input handlers with the same methods. The Nordigen class and a new JSON parser descend from it. The previous csv parser will also eventually. New converter for list input also added. Issue #19
This commit is contained in:
parent
c6cfd52b8b
commit
ad3fe02e4f
@ -2,8 +2,9 @@ from pathlib import Path
|
||||
import argparse
|
||||
import re
|
||||
|
||||
from pfbudget.core.manager import Manager
|
||||
from pfbudget.core.categories import categorize_data
|
||||
from pfbudget.core.manager import Manager
|
||||
from pfbudget.core.input.json import JsonParser
|
||||
from pfbudget.db.client import DatabaseClient
|
||||
import pfbudget.reporting.graph
|
||||
import pfbudget.reporting.report
|
||||
@ -74,7 +75,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_init.set_defaults(func=lambda args: DatabaseClient(args.database).init())
|
||||
p_init.set_defaults(func=lambda args: manager.init())
|
||||
|
||||
"""
|
||||
Exporting
|
||||
@ -155,10 +156,10 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
p_report.set_defaults(func=report)
|
||||
|
||||
"""
|
||||
Init Nordigen session: get new access token
|
||||
Nordigen API
|
||||
"""
|
||||
p_nordigen_access = subparsers.add_parser(
|
||||
"init",
|
||||
"token",
|
||||
description="Get new access token",
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@ -204,6 +205,20 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
p_nordigen_list.add_argument("country", nargs=1, type=str)
|
||||
p_nordigen_list.set_defaults(func=lambda args: Client().banks(args.country[0]))
|
||||
|
||||
"""
|
||||
Nordigen JSONs
|
||||
"""
|
||||
p_nordigen_json = subparsers.add_parser(
|
||||
"json",
|
||||
description="",
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_nordigen_json.add_argument("json", nargs=1, type=str)
|
||||
p_nordigen_json.add_argument("bank", nargs=1, type=str)
|
||||
p_nordigen_json.add_argument("--invert", action=argparse.BooleanOptionalAction)
|
||||
p_nordigen_json.set_defaults(func=lambda args: manager.parser(JsonParser(vars(args))))
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
@ -231,11 +246,17 @@ def graph(args):
|
||||
"""
|
||||
start, end = pfbudget.utils.parse_args_period(args)
|
||||
if args.option == "monthly":
|
||||
pfbudget.reporting.graph.monthly(DatabaseClient(args.database), vars(args), start, end)
|
||||
pfbudget.reporting.graph.monthly(
|
||||
DatabaseClient(args.database), vars(args), start, end
|
||||
)
|
||||
elif args.option == "discrete":
|
||||
pfbudget.reporting.graph.discrete(DatabaseClient(args.database), vars(args), start, end)
|
||||
pfbudget.reporting.graph.discrete(
|
||||
DatabaseClient(args.database), vars(args), start, end
|
||||
)
|
||||
elif args.option == "networth":
|
||||
pfbudget.reporting.graph.networth(DatabaseClient(args.database), vars(args), start, end)
|
||||
pfbudget.reporting.graph.networth(
|
||||
DatabaseClient(args.database), vars(args), start, end
|
||||
)
|
||||
|
||||
|
||||
def report(args):
|
||||
|
||||
13
pfbudget/core/input/input.py
Normal file
13
pfbudget/core/input/input.py
Normal file
@ -0,0 +1,13 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from pfbudget.core.transactions import Transactions
|
||||
|
||||
|
||||
class Input(ABC):
|
||||
@abstractmethod
|
||||
def __init__(self, options: dict):
|
||||
self.options = options
|
||||
|
||||
@abstractmethod
|
||||
def transactions(self) -> Transactions:
|
||||
return NotImplemented
|
||||
28
pfbudget/core/input/json.py
Normal file
28
pfbudget/core/input/json.py
Normal file
@ -0,0 +1,28 @@
|
||||
import json
|
||||
|
||||
from pfbudget.core.transactions import Transactions
|
||||
from pfbudget.utils.converters import convert
|
||||
from pfbudget.utils.utils import parse_decimal
|
||||
|
||||
from .input import Input
|
||||
|
||||
|
||||
class JsonParser(Input):
|
||||
def __init__(self, options):
|
||||
super().__init__(options)
|
||||
|
||||
def transactions(self) -> Transactions:
|
||||
with open(self.options["json"][0], "r") as f:
|
||||
return [
|
||||
convert(
|
||||
[
|
||||
t["bookingDate"],
|
||||
t["remittanceInformationUnstructured"],
|
||||
self.options["bank"][0],
|
||||
parse_decimal(t["transactionAmount"]["amount"])
|
||||
if not self.options["invert"]
|
||||
else -parse_decimal(t["transactionAmount"]["amount"]),
|
||||
],
|
||||
)
|
||||
for t in json.load(f)["transactions"]["booked"]
|
||||
]
|
||||
@ -1,15 +1,20 @@
|
||||
from dotenv import load_dotenv
|
||||
from json import dump
|
||||
from nordigen import NordigenClient
|
||||
from uuid import uuid4
|
||||
import os
|
||||
import webbrowser
|
||||
|
||||
from .input import Input
|
||||
from pfbudget.core.transactions import Transactions
|
||||
from pfbudget.utils.converters import convert
|
||||
from pfbudget.utils.utils import parse_decimal
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class Client:
|
||||
def __init__(self):
|
||||
class Client(Input):
|
||||
def __init__(self, options: dict):
|
||||
super().__init__(options)
|
||||
self._client = NordigenClient(
|
||||
secret_key=os.environ.get("SECRET_KEY"),
|
||||
secret_id=os.environ.get("SECRET_ID"),
|
||||
@ -17,6 +22,24 @@ class Client:
|
||||
|
||||
self._client.token = self.__token()
|
||||
|
||||
def transactions(self) -> Transactions:
|
||||
requisition = self._client.requisition.get_requisition_by_id(self.options["id"])
|
||||
|
||||
for acc in requisition["accounts"]:
|
||||
account = self._client.account_api(acc)
|
||||
d = account.get_transactions()["transactions"]
|
||||
return [
|
||||
convert(
|
||||
t["bookingDate"],
|
||||
t["remittanceInformationUnstructured"],
|
||||
self.options["bank"],
|
||||
parse_decimal(t["transactionAmount"]["amount"])
|
||||
if not self.options["invert"]
|
||||
else -parse_decimal(t["transactionAmount"]["amount"]),
|
||||
)
|
||||
for t in d["booked"]
|
||||
]
|
||||
|
||||
def token(self):
|
||||
token = self._client.generate_token()
|
||||
print(f"New access token: {token}")
|
||||
@ -32,19 +55,6 @@ class Client:
|
||||
else:
|
||||
print("you forgot the req id")
|
||||
|
||||
def transactions(self, id):
|
||||
requisition = self._client.requisition.get_requisition_by_id(id)
|
||||
|
||||
# transactions_list = []
|
||||
for acc in requisition["accounts"]:
|
||||
account = self._client.account_api(acc)
|
||||
print(account.get_metadata())
|
||||
with open("cetelem.json", "w") as f:
|
||||
dump(account.get_transactions(), f, indent=4)
|
||||
# print(dumps(account.get_transactions(), indent=4))
|
||||
|
||||
# print(transactions_list)
|
||||
|
||||
def banks(self, country: str):
|
||||
print(self._client.institution.get_institutions(country))
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from pfbudget.core.input.input import Input
|
||||
from pfbudget.core.input.parsers import parse_data
|
||||
from pfbudget.core.transactions import Transaction
|
||||
from pfbudget.db.client import DatabaseClient
|
||||
@ -8,13 +9,19 @@ class Manager:
|
||||
def __init__(self, db: str):
|
||||
self.__db = DatabaseClient(db)
|
||||
|
||||
def init(self):
|
||||
self.__db.init()
|
||||
|
||||
def parser(self, parser: Input):
|
||||
print(parser.transactions())
|
||||
|
||||
def parse(self, filename: str, args: dict):
|
||||
transactions = parse_data(filename, args)
|
||||
self.add_transactions(transactions)
|
||||
|
||||
def transactions() -> list[Transaction]:
|
||||
pass
|
||||
|
||||
def add_transactions(self, transactions: list[Transaction]):
|
||||
converted = convert(transactions)
|
||||
self.__db.insert_transactions(converted)
|
||||
|
||||
def parse(self, filename: str, args: dict):
|
||||
transactions = parse_data(filename, args)
|
||||
self.add_transactions(transactions)
|
||||
|
||||
@ -101,3 +101,6 @@ class Transaction:
|
||||
return "{} {} {}€ at {}".format(
|
||||
self.date.strftime("%d/%m/%y"), self.category, self.value, self.bank
|
||||
)
|
||||
|
||||
|
||||
Transactions = list[Transaction]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from functools import singledispatch
|
||||
|
||||
from pfbudget.core.transactions import Transaction
|
||||
from pfbudget.core.transactions import Transaction, TransactionError, Transactions
|
||||
|
||||
|
||||
@singledispatch
|
||||
@ -14,5 +14,15 @@ def _(t: Transaction) -> list:
|
||||
|
||||
|
||||
@convert.register
|
||||
def _(transactions: list) -> list[list]:
|
||||
def _(t: list) -> Transaction:
|
||||
try:
|
||||
return Transaction(t)
|
||||
except TransactionError:
|
||||
print(f"{t} is in the wrong format")
|
||||
|
||||
|
||||
def convert_transactions(transactions) -> list[list]:
|
||||
return [convert(c) for c in transactions]
|
||||
|
||||
|
||||
convert.register(type(Transactions), convert_transactions)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user