Multiple fixes and cleanups

- Remove unnecessary category null check after db select
- Adds multiple try-catch block for misbehaving parsing
- matplotlib.plt tight_layout moved to figure method
- Fixes debit/credit index with different dates
- Check for existing banks transformed to lower chars, to avoid
capitilization problem
This commit is contained in:
Luís Murta 2021-07-30 20:19:48 +01:00
parent 1f97a4635a
commit 2280b60159
Signed by: satprog
GPG Key ID: DDF2EFC6179009DC
4 changed files with 47 additions and 28 deletions

View File

@ -56,7 +56,6 @@ def categorize_data(db: DBManager):
# 3rd) Classify all else based on regex
if transactions := db.get_uncategorized_transactions():
for transaction in transactions:
if not transaction.category:
for name, category in categories.items():
if matches(transaction, category):
transaction.category = name
@ -150,7 +149,10 @@ def nulls(db: DBManager) -> None:
def matches(transaction: Transaction, category: Options):
if not category.regex:
return False
try:
return any(
re.compile(pattern).search(transaction.description.lower())
for pattern in category.regex
)
except re.error as e:
print(f"{e}{transaction} {category}")

View File

@ -41,7 +41,7 @@ def monthly(
]
)
plt.figure(figsize=(30, 10))
plt.figure(tight_layout=True)
plt.plot(
list(rrule(MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1))),
[groups["income"] for _, groups in monthly_transactions],
@ -60,7 +60,6 @@ def monthly(
],
)
plt.legend(loc="upper left")
plt.tight_layout()
if args["save"]:
plt.savefig("graph.png")
else:

View File

@ -31,7 +31,20 @@ Options = namedtuple(
"MasterCard",
"AmericanExpress",
],
defaults=["", "", "", 1, None, Index(), Index(), False, None, None, None, None],
defaults=[
"",
"",
"",
1,
None,
Index(),
Index(),
False,
None,
None,
None,
None,
],
)
@ -88,6 +101,7 @@ class Parser:
for line in list(open(self.filename, encoding=self.options.encoding))[
self.options.start - 1 : self.options.end
]
if len(line) > 2
]
return transactions
@ -100,9 +114,10 @@ class Parser:
elif line[options.credit.value]:
index = options.credit
elif options.debit.date != options.credit.date:
if line[options.debit.date]:
negate = 1 if (options.debit.negate or options.credit.negate) else -1
if (negate * utils.parse_decimal(line[options.debit.value])) < 0:
index = options.debit
elif line[options.credit.date]:
else:
index = options.credit
elif options.debit.text != options.credit.text:
if line[options.debit.text]:

View File

@ -1,5 +1,5 @@
from datetime import date, datetime, timedelta
from decimal import Decimal
from decimal import Decimal, InvalidOperation
from pathlib import Path
@ -21,15 +21,18 @@ def parse_decimal(s: str) -> Decimal:
return Decimal(s)
except ValueError:
pass
s = s.strip().replace(u"\xa0", "").replace(" ", "")
s = s.strip().replace("", "").replace("+", "")
if s.rfind(",") > s.rfind("."):
s = s.replace(".", "")
i = s.rfind(",")
li = list(s)
try:
d = s.strip().replace("\xa0", "").replace(" ", "")
d = d.replace("", "").replace("+", "").replace("EUR", "").strip()
if d.rfind(",") > d.rfind("."):
d = d.replace(".", "")
i = d.rfind(",")
li = list(d)
li[i] = "."
s = "".join(li)
return Decimal(s.replace(",", ""))
d = "".join(li)
return Decimal(d.replace(",", ""))
except InvalidOperation:
raise InvalidOperation(f"{s} -> {d}")
def find_credit_institution(fn, banks, creditcards):
@ -47,10 +50,10 @@ def find_credit_institution(fn, banks, creditcards):
if not bank:
raise WrongFilenameError
if bank not in banks:
raise BankNotAvailableError
if cc and cc not in creditcards:
raise CreditCardNotAvailableError
if bank.lower() not in [bank.lower() for bank in banks]:
raise BankNotAvailableError(f"{fn}: {banks}")
if cc and cc.lower() not in [cc.lower() for cc in creditcards]:
raise CreditCardNotAvailableError(f"{fn}: {banks}")
return bank, cc