diff --git a/main.py b/main.py index d25b52a..c5f8983 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,5 @@ -from pfbudget import run +from pfbudget import Manager, run if __name__ == "__main__": - run() + command, args = run() + Manager(command).start(args) diff --git a/pfbudget/__init__.py b/pfbudget/__init__.py index 80ed96e..8b5a5fa 100644 --- a/pfbudget/__init__.py +++ b/pfbudget/__init__.py @@ -3,5 +3,6 @@ __author__ = "Luís Murta" __version__ = "0.1" from pfbudget.core.categories import categorize_data +from pfbudget.core.manager import Manager from pfbudget.cli.runnable import run from pfbudget.input.parsers import parse_data diff --git a/pfbudget/cli/runnable.py b/pfbudget/cli/runnable.py index b980a1c..d5b1a0e 100644 --- a/pfbudget/cli/runnable.py +++ b/pfbudget/cli/runnable.py @@ -2,8 +2,8 @@ from pathlib import Path import argparse import re +from pfbudget.common.types import Command from pfbudget.core.categories import categorize_data -from pfbudget.core.manager import Manager from pfbudget.input.json import JsonParser from pfbudget.input.nordigen import NordigenInput from pfbudget.db.sqlite import DatabaseClient @@ -27,7 +27,7 @@ class DataFileMissing(Exception): pass -def argparser(manager: Manager) -> argparse.ArgumentParser: +def argparser() -> argparse.ArgumentParser: help = argparse.ArgumentParser(add_help=False) help.add_argument( @@ -74,7 +74,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: parents=[help], formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) - p_init.set_defaults(func=lambda args: manager.init()) + p_init.set_defaults(command=Command.Init) """ Exporting @@ -100,7 +100,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: p_parse.add_argument("--bank", nargs=1, type=str) p_parse.add_argument("--creditcard", nargs=1, type=str) p_parse.add_argument("--category", nargs=1, type=int) - p_parse.set_defaults(func=lambda args: parse(manager, args)) + p_parse.set_defaults(command=Command.Parse) """ Categorizing @@ -111,9 +111,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: parents=[help], formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) - p_categorize.set_defaults( - func=lambda args: manager.categorize(vars(args)) - ) + p_categorize.set_defaults(command=Command.Categorize) """ Graph @@ -168,7 +166,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: "--requisition", type=str, nargs=1, help="requisition option help" ) p_register.add_argument("--invert", action="store_true") - p_register.set_defaults(func=lambda args: manager.register(vars(args))) + p_register.set_defaults(command=Command.Register) """ Unregister bank @@ -180,7 +178,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) p_register.add_argument("bank", type=str, nargs=1, help="bank option help") - p_register.set_defaults(func=lambda args: manager.unregister(vars(args))) + p_register.set_defaults(command=Command.Unregister) """ Nordigen API @@ -191,7 +189,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: parents=[help], formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) - p_nordigen_access.set_defaults(func=lambda args: NordigenInput(manager).token()) + p_nordigen_access.set_defaults(command=Command.Token) """ (Re)new bank requisition ID @@ -204,11 +202,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: ) p_nordigen_access.add_argument("name", nargs=1, type=str) p_nordigen_access.add_argument("country", nargs=1, type=str) - p_nordigen_access.set_defaults( - func=lambda args: NordigenInput(manager).requisition( - args.name[0], args.country[0] - ) - ) + p_nordigen_access.set_defaults(command=Command.Renew) """ Downloading through Nordigen API @@ -222,40 +216,40 @@ def argparser(manager: Manager) -> argparse.ArgumentParser: 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: download(manager, args)) + p_nordigen_download.set_defaults(command=Command.Download) - """ - List available banks on Nordigen API - """ - p_nordigen_list = subparsers.add_parser( - "list", - description="Lists banks in {country}", - parents=[help], - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - p_nordigen_list.add_argument("country", nargs=1, type=str) - p_nordigen_list.set_defaults(func=lambda args: nordigen_banks(manager, args)) + # """ + # List available banks on Nordigen API + # """ + # p_nordigen_list = subparsers.add_parser( + # "list", + # description="Lists banks in {country}", + # parents=[help], + # formatter_class=argparse.ArgumentDefaultsHelpFormatter, + # ) + # p_nordigen_list.add_argument("country", nargs=1, type=str) + # p_nordigen_list.set_defaults(func=lambda args: nordigen_banks(manager, args)) - """ - 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))) - ) + # """ + # 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 -def parse(manager: Manager, args): +def parse(manager, args): """Parses the contents of the path in args to the selected database. Args: @@ -305,17 +299,17 @@ def report(args): pfbudget.reporting.report.detailed(DatabaseClient(args.database), start, end) -def nordigen_banks(manager: Manager, args): - input = NordigenInput(manager) - input.list(vars(args)["country"][0]) +# def nordigen_banks(manager: Manager, args): +# input = NordigenInput(manager) +# input.list(vars(args)["country"][0]) -def download(manager: Manager, args): +def download(manager, args: dict): start, end = pfbudget.utils.parse_args_period(args) - manager.parser(NordigenInput(manager, vars(args), start, end)) + manager.parser(NordigenInput(manager, args, start, end)) def run(): - manager = Manager(DEFAULT_DB) - args = argparser(manager).parse_args() - args.func(args) + args = vars(argparser().parse_args()) + assert "command" in args, "No command selected" + return args["command"], args diff --git a/pfbudget/common/types.py b/pfbudget/common/types.py index 54c4fe3..c7602c5 100644 --- a/pfbudget/common/types.py +++ b/pfbudget/common/types.py @@ -4,6 +4,17 @@ from decimal import Decimal, InvalidOperation from enum import Enum, auto +class Command(Enum): + Init = auto() + Parse = auto() + Download = auto() + Categorize = auto() + Register = auto() + Unregister = auto() + Token = auto() + Renew = auto() + + class TransactionError(Exception): pass diff --git a/pfbudget/core/categorizer.py b/pfbudget/core/categorizer.py index f15d349..7b4f8e2 100644 --- a/pfbudget/core/categorizer.py +++ b/pfbudget/core/categorizer.py @@ -6,7 +6,7 @@ from datetime import timedelta class Categorizer: options = {} - def __init__(self, args: dict): + def __init__(self): self.options["null_days"] = 4 def categorize(self, transactions: list[Transaction]): @@ -21,6 +21,7 @@ class Categorizer: self._nullify(transactions) def _nullify(self, transactions: list[Transaction]): + count = 0 matching = [] for transaction in transactions: for cancel in ( @@ -40,4 +41,7 @@ class Categorizer: transaction.category = TransactionCategory(name="null") cancel.category = TransactionCategory(name="null") matching.extend([transaction, cancel]) + count += 2 break + + print(f"Nullified {count} transactions") diff --git a/pfbudget/core/manager.py b/pfbudget/core/manager.py index 071324a..a56342e 100644 --- a/pfbudget/core/manager.py +++ b/pfbudget/core/manager.py @@ -1,13 +1,62 @@ from pfbudget.input.input import Input +from pfbudget.input.nordigen import NordigenClient from pfbudget.input.parsers import parse_data from pfbudget.db.client import DbClient +from pfbudget.common.types import Command from pfbudget.core.categorizer import Categorizer from pfbudget.utils import convert +from pfbudget.cli.runnable import download, parse + class Manager: - def __init__(self, url: str): - self._db = DbClient(url) + def __init__(self, command: Command): + self.__command = command + match (command): + case Command.Init: + pass + case Command.Parse: + pass + case Command.Download: + pass + case Command.Categorize: + pass + case Command.Register: + pass + case Command.Unregister: + pass + case Command.Token: + pass + case Command.Renew: + pass + + def start(self, args): + match (self.__command): + case Command.Init: + pass + case Command.Parse: + # TODO this is a monstrosity, remove when possible + self._db = DbClient(args["database"]) + parse(self, args) + case Command.Download: + # TODO this is a monstrosity, remove when possible + self._db = DbClient(args["database"]) + download(self, args) + case Command.Categorize: + self._db = DbClient(args["database"]) + self.categorize(args) + case Command.Register: + # self._db = DbClient(args["database"]) + # self.register(args) + pass + case Command.Unregister: + # self._db = DbClient(args["database"]) + # self.unregister(args) + pass + case Command.Token: + NordigenClient(self).token() + case Command.Renew: + NordigenClient(self).requisition(args["name"], args["country"]) # def init(self): # client = DatabaseClient(self.__db) diff --git a/pfbudget/utils/utils.py b/pfbudget/utils/utils.py index 7e692f6..6cacab6 100644 --- a/pfbudget/utils/utils.py +++ b/pfbudget/utils/utils.py @@ -59,21 +59,22 @@ def find_credit_institution(fn, banks, creditcards): return bank, cc -def parse_args_period(args): +def parse_args_period(args: dict): start, end = date.min, date.max - if args.start: - start = datetime.strptime(args.start[0], "%Y/%m/%d").date() + print(args) + if args["start"]: + start = datetime.strptime(args["start"][0], "%Y/%m/%d").date() - if args.end: - end = datetime.strptime(args.end[0], "%Y/%m/%d").date() + if args["end"]: + end = datetime.strptime(args["end"][0], "%Y/%m/%d").date() - if args.interval: - start = datetime.strptime(args.interval[0], "%Y/%m/%d").date() - end = datetime.strptime(args.interval[1], "%Y/%m/%d").date() + if args["interval"]: + start = datetime.strptime(args["interval"][0], "%Y/%m/%d").date() + end = datetime.strptime(args["interval"][1], "%Y/%m/%d").date() - if args.year: - start = datetime.strptime(args.year[0], "%Y").date() - end = datetime.strptime(str(int(args.year[0]) + 1), "%Y").date() - timedelta( + if args["year"]: + start = datetime.strptime(args["year"][0], "%Y").date() + end = datetime.strptime(str(int(args["year"][0]) + 1), "%Y").date() - timedelta( days=1 )