budget/transaction.py
Luís Murta ca12d1846c
Automatic and manual categorization
reader.py is removed, with main.py becoming the main function where all
others are called from.
All categories added on categories.py, each with its own search function
and regex. The categorize function is also defined on the base class

The parsers have been cleaned to a more strimmed version. Each parser has
its own parse method and encoding and separator attributes.

The `Transaction` class has been incremented with all the comparator
methods. It also has the read and write from file methods.

The transactions.pickle is no longer used, since changes can be done
directly to the parsed data in the data_dir, making the file unused. A
manual categorization function has been created to help fill in the
gaps, interchangeable with directly editing the parsed .csv files. The
master record of data are the .csv present in the data_dir.
2020-08-04 20:42:29 +01:00

93 lines
2.6 KiB
Python

from csv import reader, writer
from datetime import date
from decimal import Decimal, InvalidOperation
class TransactionError(Exception):
pass
class Transaction:
date = None
description = ""
bank = ""
value = 0
category = ""
def __init__(self, *args):
arg = args[0] if len(args) == 1 else list(args)
try:
self.date = date.fromisoformat(arg[0])
self.description = " ".join(arg[1].split())
self.bank = arg[2]
self.value = Decimal(arg[3])
self.category = arg[4]
except IndexError:
pass
except InvalidOperation:
print(f"{args}")
raise TransactionError
def to_csv(self):
return [self.date, self.description, self.bank, self.value, self.category]
@staticmethod
def read_transactions(file, encoding="utf-8"):
with open(file, newline="", encoding=encoding) as f:
r = reader(f, delimiter="\t")
transactions = [Transaction(row) for row in r]
return transactions
@staticmethod
def write_transactions(file, transactions, append=False, encoding="utf-8"):
with open(file, "a" if append else "w", newline="", encoding=encoding) as f:
w = writer(f, delimiter="\t")
w.writerows([transaction.to_csv() for transaction in transactions])
@staticmethod
def get_repeated_transactions(transactions):
repeated, new = list(), list()
for t in transactions:
if t not in new:
new.append(t)
else:
repeated.append(t)
return repeated
@staticmethod
def sort_by_bank(transactions):
transactions.sort(key=lambda k: k.bank)
return transactions
def __eq__(self, other):
return (
self.date == other.date
and self.description == other.description
and self.bank == other.bank
and self.value == other.value
)
def __ne__(self, other):
return (
self.date != other.date
or self.description != other.description
or self.bank != other.bank
or self.value != other.value
)
def __lt__(self, other):
return self.date < other.date
def __le__(self, other):
return self.date <= other.date
def __gt__(self, other):
return self.date > other.date
def __ge__(self, other):
return self.date >= other.date
def __repr__(self):
return f"{self.date} {self.description} {self.value}€ from {self.bank} ({self.category})"