2023-04-19 15:09:11 +02:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
2020-09-29 19:11:26 +02:00
|
|
|
class Category:
|
2023-04-19 15:09:11 +02:00
|
|
|
def __init__(self, category_name) -> None:
|
|
|
|
self.name = category_name
|
|
|
|
self.ledger = []
|
|
|
|
self.balance = 0
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
ledger = self.name.center(30, "*") + "\n"
|
|
|
|
for entry in self.ledger:
|
|
|
|
ledger += entry["description"][:23].ljust(23)
|
|
|
|
ledger += ("%0.2f" % entry["amount"]).rjust(7) + "\n"
|
|
|
|
ledger += "Total: "
|
|
|
|
ledger += "%0.2f"%self.balance
|
|
|
|
return ledger
|
|
|
|
|
|
|
|
def deposit(self, amount: float, description: str="") -> None:
|
|
|
|
self.ledger.append({"amount": amount, "description": description})
|
|
|
|
self.balance += amount
|
|
|
|
|
|
|
|
def check_funds(self, amount: float) -> bool:
|
|
|
|
return amount <= self.balance
|
|
|
|
|
|
|
|
def withdraw(self, amount: float, description: str="") -> bool:
|
|
|
|
if self.check_funds(amount):
|
|
|
|
self.ledger.append({"amount": -amount, "description": description})
|
|
|
|
self.balance -= amount
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def get_balance(self) -> float:
|
|
|
|
return self.balance
|
|
|
|
|
|
|
|
def transfer(self, amount: float, other: Category) -> bool:
|
|
|
|
if self.check_funds(amount):
|
|
|
|
self.ledger.append({"amount": -amount, "description": f'Transfer to {other.name}'})
|
|
|
|
self.balance -= amount
|
|
|
|
other.deposit(amount, f"Transfer from {self.name}")
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_spend_chart(categories: list[Category]) -> str:
|
|
|
|
chart = "Percentage spent by category\n"
|
|
|
|
total_spending: float = 0
|
|
|
|
category_wise_spending: dict[str, float] = {}
|
|
|
|
for category in categories:
|
|
|
|
category_wise_spending[category.name] = 0
|
|
|
|
for entry in category.ledger:
|
|
|
|
if entry["amount"] < 0 and not entry["description"].startswith("Transfer to "):
|
|
|
|
category_wise_spending[category.name] += entry["amount"]
|
|
|
|
|
|
|
|
for category in category_wise_spending:
|
|
|
|
total_spending += category_wise_spending[category]
|
|
|
|
|
|
|
|
category_wise_relative_spending: dict[str, float] = {}
|
2020-09-29 19:11:26 +02:00
|
|
|
|
2023-04-19 15:09:11 +02:00
|
|
|
for category in category_wise_spending:
|
|
|
|
# in multiple of 10 percent, rounded down to nearest 10
|
|
|
|
category_wise_relative_spending[category] = int((category_wise_spending[category]/total_spending)*10)
|
2020-09-29 19:11:26 +02:00
|
|
|
|
2023-04-19 15:09:11 +02:00
|
|
|
bars: list[int] = []
|
|
|
|
category_names: list[str] = []
|
|
|
|
for cat_name, bar_height in category_wise_relative_spending.items():
|
|
|
|
bars.append(bar_height)
|
|
|
|
category_names.append(cat_name)
|
2020-09-29 19:11:26 +02:00
|
|
|
|
2023-04-19 15:09:11 +02:00
|
|
|
for i in range(10, -1, -1):
|
|
|
|
chart += str(i*10).rjust(3) + "|"
|
|
|
|
part_chart: list[str] = []
|
|
|
|
for bar in bars:
|
|
|
|
part_chart.append( " " if bar < i else " o")
|
|
|
|
chart += " ".join(part_chart)
|
|
|
|
chart += " \n"
|
|
|
|
|
|
|
|
chart += " "*4 + "-"*(len(bars)*3+1)+"\n"
|
2020-09-29 19:11:26 +02:00
|
|
|
|
2023-04-19 15:09:11 +02:00
|
|
|
cat_name_loop = max([len(cat_name) for cat_name in category_names])
|
|
|
|
for i in range(cat_name_loop):
|
|
|
|
chart += " "*4
|
|
|
|
part_chart: list[str] = []
|
|
|
|
for cat_name in category_names:
|
|
|
|
part_chart.append(" "+cat_name[i] if len(cat_name) > i else " ")
|
|
|
|
chart += " ".join(part_chart)
|
|
|
|
chart += " \n"
|
2020-09-29 19:11:26 +02:00
|
|
|
|
2023-04-19 15:09:11 +02:00
|
|
|
return chart[:-1]
|