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:
parent
1f97a4635a
commit
2280b60159
@ -56,11 +56,10 @@ def categorize_data(db: DBManager):
|
|||||||
# 3rd) Classify all else based on regex
|
# 3rd) Classify all else based on regex
|
||||||
if transactions := db.get_uncategorized_transactions():
|
if transactions := db.get_uncategorized_transactions():
|
||||||
for transaction in transactions:
|
for transaction in transactions:
|
||||||
if not transaction.category:
|
for name, category in categories.items():
|
||||||
for name, category in categories.items():
|
if matches(transaction, category):
|
||||||
if matches(transaction, category):
|
transaction.category = name
|
||||||
transaction.category = name
|
break
|
||||||
break
|
|
||||||
db.update_categories(
|
db.update_categories(
|
||||||
[transaction for transaction in transactions if transaction.category]
|
[transaction for transaction in transactions if transaction.category]
|
||||||
)
|
)
|
||||||
@ -150,7 +149,10 @@ def nulls(db: DBManager) -> None:
|
|||||||
def matches(transaction: Transaction, category: Options):
|
def matches(transaction: Transaction, category: Options):
|
||||||
if not category.regex:
|
if not category.regex:
|
||||||
return False
|
return False
|
||||||
return any(
|
try:
|
||||||
re.compile(pattern).search(transaction.description.lower())
|
return any(
|
||||||
for pattern in category.regex
|
re.compile(pattern).search(transaction.description.lower())
|
||||||
)
|
for pattern in category.regex
|
||||||
|
)
|
||||||
|
except re.error as e:
|
||||||
|
print(f"{e}{transaction} {category}")
|
||||||
|
|||||||
@ -41,7 +41,7 @@ def monthly(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
plt.figure(figsize=(30, 10))
|
plt.figure(tight_layout=True)
|
||||||
plt.plot(
|
plt.plot(
|
||||||
list(rrule(MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1))),
|
list(rrule(MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1))),
|
||||||
[groups["income"] for _, groups in monthly_transactions],
|
[groups["income"] for _, groups in monthly_transactions],
|
||||||
@ -60,7 +60,6 @@ def monthly(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
plt.legend(loc="upper left")
|
plt.legend(loc="upper left")
|
||||||
plt.tight_layout()
|
|
||||||
if args["save"]:
|
if args["save"]:
|
||||||
plt.savefig("graph.png")
|
plt.savefig("graph.png")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -31,7 +31,20 @@ Options = namedtuple(
|
|||||||
"MasterCard",
|
"MasterCard",
|
||||||
"AmericanExpress",
|
"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))[
|
for line in list(open(self.filename, encoding=self.options.encoding))[
|
||||||
self.options.start - 1 : self.options.end
|
self.options.start - 1 : self.options.end
|
||||||
]
|
]
|
||||||
|
if len(line) > 2
|
||||||
]
|
]
|
||||||
return transactions
|
return transactions
|
||||||
|
|
||||||
@ -100,9 +114,10 @@ class Parser:
|
|||||||
elif line[options.credit.value]:
|
elif line[options.credit.value]:
|
||||||
index = options.credit
|
index = options.credit
|
||||||
elif options.debit.date != options.credit.date:
|
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
|
index = options.debit
|
||||||
elif line[options.credit.date]:
|
else:
|
||||||
index = options.credit
|
index = options.credit
|
||||||
elif options.debit.text != options.credit.text:
|
elif options.debit.text != options.credit.text:
|
||||||
if line[options.debit.text]:
|
if line[options.debit.text]:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal, InvalidOperation
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@ -21,15 +21,18 @@ def parse_decimal(s: str) -> Decimal:
|
|||||||
return Decimal(s)
|
return Decimal(s)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
s = s.strip().replace(u"\xa0", "").replace(" ", "")
|
try:
|
||||||
s = s.strip().replace("€", "").replace("+", "")
|
d = s.strip().replace("\xa0", "").replace(" ", "")
|
||||||
if s.rfind(",") > s.rfind("."):
|
d = d.replace("€", "").replace("+", "").replace("EUR", "").strip()
|
||||||
s = s.replace(".", "")
|
if d.rfind(",") > d.rfind("."):
|
||||||
i = s.rfind(",")
|
d = d.replace(".", "")
|
||||||
li = list(s)
|
i = d.rfind(",")
|
||||||
li[i] = "."
|
li = list(d)
|
||||||
s = "".join(li)
|
li[i] = "."
|
||||||
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):
|
def find_credit_institution(fn, banks, creditcards):
|
||||||
@ -47,10 +50,10 @@ def find_credit_institution(fn, banks, creditcards):
|
|||||||
if not bank:
|
if not bank:
|
||||||
raise WrongFilenameError
|
raise WrongFilenameError
|
||||||
|
|
||||||
if bank not in banks:
|
if bank.lower() not in [bank.lower() for bank in banks]:
|
||||||
raise BankNotAvailableError
|
raise BankNotAvailableError(f"{fn}: {banks}")
|
||||||
if cc and cc not in creditcards:
|
if cc and cc.lower() not in [cc.lower() for cc in creditcards]:
|
||||||
raise CreditCardNotAvailableError
|
raise CreditCardNotAvailableError(f"{fn}: {banks}")
|
||||||
|
|
||||||
return bank, cc
|
return bank, cc
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user