The `CategorySelector` was possibly added to be incremented with other attributes. However, since none other that the selector enum is used at the moment, it is only adding unnecessary cluter. The category selector value is moved to the parent `TransactionCategory`.
119 lines
3.6 KiB
Python
119 lines
3.6 KiB
Python
import decimal
|
|
|
|
from ..core.manager import Manager
|
|
from ..db.model import (
|
|
Category,
|
|
Note,
|
|
CategorySelector,
|
|
SplitTransaction,
|
|
Tag,
|
|
Transaction,
|
|
TransactionCategory,
|
|
TransactionTag,
|
|
)
|
|
|
|
|
|
class Interactive:
|
|
help = "category(:tag)/split/note:/skip/quit"
|
|
selector = CategorySelector.manual
|
|
|
|
def __init__(self, manager: Manager) -> None:
|
|
self.manager = manager
|
|
|
|
with self.manager.db.session() as session:
|
|
self.categories = session.get(Category)
|
|
self.tags = session.get(Tag)
|
|
session.expunge_all()
|
|
|
|
def intro(self) -> None:
|
|
print(
|
|
f"Welcome! Available categories are {[c.name for c in self.categories]} and"
|
|
f" currently existing tags are {[t.name for t in self.tags]}"
|
|
)
|
|
|
|
def start(self) -> None:
|
|
self.intro()
|
|
|
|
with self.manager.db.session() as session:
|
|
uncategorized = session.uncategorized()
|
|
n = len(uncategorized)
|
|
print(f"{n} left to categorize")
|
|
|
|
i = 0
|
|
new = []
|
|
next = uncategorized[i]
|
|
print(next)
|
|
while (command := input("$ ")) != "quit":
|
|
match command:
|
|
case "help":
|
|
print(self.help)
|
|
|
|
case "skip":
|
|
i += 1
|
|
|
|
case "quit":
|
|
break
|
|
|
|
case "split":
|
|
new = self.split(next)
|
|
session.insert(new)
|
|
|
|
case other:
|
|
if not other:
|
|
print(self.help)
|
|
continue
|
|
|
|
if other.startswith("note:"):
|
|
# TODO adding notes to a splitted transaction won't allow
|
|
# categorization
|
|
next.note = Note(other[len("note:") :].strip())
|
|
else:
|
|
ct = other.split(":")
|
|
if (category := ct[0]) not in [
|
|
c.name for c in self.categories
|
|
]:
|
|
print(self.help, self.categories)
|
|
|
|
tags = []
|
|
if len(ct) > 1:
|
|
tags = ct[1:]
|
|
|
|
next.category = TransactionCategory(category, self.selector)
|
|
for tag in tags:
|
|
if tag not in [t.name for t in self.tags]:
|
|
session.insert([Tag(tag)])
|
|
self.tags = session.get(Tag)
|
|
|
|
next.tags.add(TransactionTag(tag))
|
|
|
|
i += 1
|
|
|
|
session.commit()
|
|
|
|
next = uncategorized[i] if len(new) == 0 else new.pop()
|
|
print(next)
|
|
|
|
def split(self, original: Transaction) -> list[SplitTransaction]:
|
|
total = original.amount
|
|
new = []
|
|
|
|
done = False
|
|
while not done:
|
|
if abs(sum(t.amount for t in new)) > abs(total):
|
|
print("Overflow, try again")
|
|
new.clear()
|
|
continue
|
|
|
|
if sum(t.amount for t in new) == total:
|
|
done = True
|
|
break
|
|
|
|
amount = decimal.Decimal(input("amount: "))
|
|
new.append(
|
|
SplitTransaction(
|
|
original.date, original.description, amount, original.id
|
|
)
|
|
)
|
|
|
|
return new
|