Files
kuehlschrank/ui/cli.py
T
2026-06-02 15:11:00 +02:00

601 lines
19 KiB
Python

from config import ADMIN_PASSWORD
class CLI:
def __init__(self, tracker) -> None:
self.tracker = tracker
self.current_user = None
def run(self):
while True:
self._clear_screen()
self._show_main_menu()
def _clear_screen(self):
import subprocess
import os
subprocess.run("cls" if os.name == "nt" else "clear")
def _show_main_menu(self):
print("=" * 50)
print("DEBT TRACKER")
print("=" * 50)
if self.current_user:
user = self.tracker.get_user_by_id(self.current_user)
debt = self.tracker.get_user_debt(self.current_user)
print(f"\nLogged in as: {user.name}")
print(f"Current Debt: ${debt:.2f}\n")
print("1. Select user")
print("2. View all debts")
print("3. Admin panel")
print("4. Exit")
print()
choice = input("Choose Option: ").strip()
if choice == "1":
self._select_user()
elif choice == "2":
self._view_all_debts()
elif choice == "3":
self._admin_panel()
elif choice == "4":
print("\nGoodbye!")
exit()
else:
self._invalid_choice()
def _select_user(self):
self._clear_screen()
print("=" * 50)
print("SELECT USER")
print("=" * 50)
print()
users = self.tracker.get_all_users()
user_list = list(users.items())
for i, (user_id, user) in enumerate(user_list, 1):
debt = self.tracker.get_user_debt(user_id)
print(f"{i}. {user.name} (Debt: ${debt:.2f})")
print(f"{len(user_list) + 1}. Back to main menu")
print()
try:
choice = int(input("Choose user: ").strip())
if choice == len(user_list) + 1:
return
if 1 <= choice <= len(user_list):
self.current_user = user_list[choice - 1][0]
self._user_menu()
else:
self._invalid_choice()
except ValueError:
self._invalid_choice()
def _user_menu(self):
while True:
self._clear_screen()
user = self.tracker.get_user_by_id(self.current_user)
debt = self.tracker.get_user_debt(self.current_user)
print("=" * 50)
print(f"USER MENU - {user.name}")
print("=" * 50)
print(f"Current debt: ${debt:.2f}\n")
print("1. Add purchase")
print("2. View my debt")
print("3. Logout")
print()
choice = input("Choose option: ").strip()
if choice == "1":
self._add_purchase()
elif choice == "2":
self._view_user_debt()
elif choice == "3":
self.current_user = None
break
else:
self._invalid_choice()
def _add_purchase(self):
self._clear_screen()
print("=" * 50)
print("ADD PURCHASE")
print("=" * 50)
print()
menu_items = self.tracker.get_items()
item_list = list(menu_items.items())
for i, (_item_id, item) in enumerate(item_list, 1):
print(f"{i}. {item.name} - ${item.price:.2f}")
print(f"{len(item_list) + 1}. Cancel")
print()
try:
choice = int(input("Choose item: ").strip())
if choice == len(item_list) + 1:
return
if 1 <= choice <= len(item_list):
selected_item_id = item_list[choice - 1][0]
self._confirm_purchase(selected_item_id)
else:
self._invalid_choice()
except ValueError:
self._invalid_choice()
def _confirm_purchase(self, item_id):
self._clear_screen()
user = self.tracker.get_user_by_id(self.current_user)
item = self.tracker.get_items()[item_id]
print("=" * 50)
print("CONFIRM PURCHASE")
print("=" * 50)
print()
print(f"User: {user.name}")
print(f"Item: {item.name}")
print(f"Price: ${item.price:.2f}")
print()
confirm = input("Add to debt? (y/n): ").strip().lower()
if confirm == "y":
result = self.tracker.add_purchase(self.current_user, item_id)
self._clear_screen()
print("=" * 50)
print("PURCHASE ADDED")
print("=" * 50)
print()
print(f"✓ {result['message']}")
print(f"New debt: ${result['new_debt']:.2f}")
print()
input("Press Enter to continue...")
else:
print("Purchase cancelled.")
input("Press Enter to continue...")
def _view_user_debt(self):
self._clear_screen()
user = self.tracker.get_user_by_id(self.current_user)
debt = self.tracker.get_user_debt(self.current_user)
print("=" * 50)
print(f"DEBT - {user.name}")
print("=" * 50)
print()
print(f"Amount owed: ${debt:.2f}")
print()
input("Press Enter to continue...")
def _view_all_debts(self):
self._clear_screen()
print("=" * 50)
print("ALL DEBTS")
print("=" * 50)
print()
all_debts = self.tracker.get_all_debts()
if not all_debts:
print("No users with debt.")
else:
total = 0
for _user_id, debt_info in all_debts.items():
amount = debt_info["debt"]
print(f"{debt_info['name']:.<30} ${amount:>7.2f}")
total += amount
print("-" * 50)
print(f"{'TOTAL':.<30} ${total:>7.2f}")
print()
input("Press Enter to continue...")
def _admin_panel(self):
self._clear_screen()
print("=" * 50)
print("ADMIN PANEL")
print("=" * 50)
print()
password = input("Enter admin password: ").strip()
if password != ADMIN_PASSWORD:
print("Invalid password!")
input("Press Enter to continue...")
return
while True:
self._clear_screen()
print("=" * 50)
print("ADMIN PANEL")
print("=" * 50)
print()
print("1. View all debts")
print("2. Adjust user debt")
print("3. Clear user debt")
print("4. View transaction history")
print("5. Manage users")
print("6. Manage items")
print("7. Logout")
print()
choice = input("Choose option: ").strip()
if choice == "1":
self._view_all_debts()
elif choice == "2":
self._adjust_debt()
elif choice == "3":
self._clear_user_debt()
elif choice == "4":
self._view_transaction_history()
elif choice == "5":
self._manage_users()
elif choice == "6":
self._manage_items()
elif choice == "7":
break
else:
self._invalid_choice()
def _adjust_debt(self):
self._clear_screen()
print("=" * 50)
print("ADJUST DEBT")
print("=" * 50)
print()
users = self.tracker.get_all_users()
user_list = list(users.items())
for i, (user_id, user) in enumerate(user_list, 1):
debt = self.tracker.get_user_debt(user_id)
print(f"{i}. {user.name} - ${debt:.2f}")
print()
try:
choice = int(input("Choose user: ").strip())
if 1 <= choice <= len(user_list):
user_id = user_list[choice - 1][0]
amount_str = input("Amount paid: $").strip()
amount = float(amount_str)
result = self.tracker.adjust_debt(user_id, amount, ADMIN_PASSWORD)
self._clear_screen()
print("=" * 50)
print("DEBT ADJUSTED")
print("=" * 50)
print()
print(f"{result['message']}")
print(f"New debt: ${result['new_debt']:.2f}")
print()
input("Press Enter to continue...")
else:
self._invalid_choice()
except ValueError:
print("Invalid input!")
input("Press Enter to continue...")
def _clear_user_debt(self):
self._clear_screen()
print("=" * 50)
print("CLEAR USER DEBT")
print("=" * 50)
print()
users = self.tracker.get_all_users()
user_list = list(users.items())
for i, (user_id, user) in enumerate(user_list, 1):
debt = self.tracker.get_user_debt(user_id)
print(f"{i}. {user.name} - ${debt:.2f}")
print()
try:
choice = int(input("Choose user: ").strip())
if 1 <= choice <= len(user_list):
user_id = user_list[choice - 1][0]
debt_amount = self.tracker.get_user_debt(user_id)
confirm = input(f"Clear ${debt_amount:.2f}? (y/n): ").strip().lower()
if confirm == "y":
_result = self.tracker.adjust_debt(
user_id, debt_amount, ADMIN_PASSWORD
)
self._clear_screen()
print("=" * 50)
print("DEBT CLEARED")
print("=" * 50)
print()
print(
f"Debt cleared for {self.tracker.get_user_by_id(user_id).name}"
)
print()
input("Press Enter to continue...")
else:
self._invalid_choice()
except ValueError:
print("Invalid input!")
input("Press Enter to continue...")
def _view_transaction_history(self):
self._clear_screen()
print("=" * 50)
print("TRANSACTION HISTORY")
print("=" * 50)
print()
transactions = self.tracker.transactions
if not transactions:
print("No transactions yet.")
else:
for t in sorted(transactions, key=lambda x: x.timestamp, reverse=True):
user = self.tracker.get_user_by_id(t.user_id)
item = self.tracker.get_items().get(t.item_id)
item_name = item.name if item else ("Adjustment" if t.item_id == "adjustment" else "Deleted Item")
print(
f"{t.timestamp[:10]} | {user.name:.<20} {item_name:.<15} ${t.amount:.2f}"
)
print()
input("Press Enter to continue...")
def _invalid_choice(self):
print("Invalid choice. Please try again.")
input("Press Enter to continue...")
def _manage_users(self):
while True:
self._clear_screen()
print("=" * 50)
print("MANAGE USERS")
print("=" * 50)
print()
print("1. Add user")
print("2. Edit user")
print("3. Remove user")
print("4. Back to admin panel")
print()
choice = input("Choose option: ").strip()
if choice == "1":
self._cli_add_user()
elif choice == "2":
self._cli_edit_user()
elif choice == "3":
self._cli_remove_user()
elif choice == "4":
break
else:
self._invalid_choice()
def _cli_add_user(self):
self._clear_screen()
print("=" * 50)
print("ADD USER")
print("=" * 50)
print()
name = input("Enter new user's name: ").strip()
if not name:
print("Name cannot be empty!")
input("Press Enter to continue...")
return
import uuid
user_id = f"user_{uuid.uuid4().hex[:8]}"
res = self.tracker.add_user(user_id, name)
print(res["message"])
input("Press Enter to continue...")
def _cli_edit_user(self):
self._clear_screen()
print("=" * 50)
print("EDIT USER")
print("=" * 50)
print()
users = self.tracker.get_all_users()
user_list = list(users.items())
for i, (user_id, user) in enumerate(user_list, 1):
print(f"{i}. {user.name} (PIN: {user.pin})")
print(f"{len(user_list) + 1}. Cancel")
print()
try:
choice = int(input("Choose user to edit: ").strip())
if choice == len(user_list) + 1:
return
if 1 <= choice <= len(user_list):
user_id = user_list[choice - 1][0]
user = users[user_id]
new_name = input(f"Enter new name (leave empty to keep '{user.name}'): ").strip()
new_pin = input(f"Enter new PIN (leave empty to keep '{user.pin}'): ").strip()
name = new_name if new_name else user.name
pin = new_pin if new_pin else user.pin
if len(pin) < 4:
print("PIN must be at least 4 digits!")
input("Press Enter to continue...")
return
res = self.tracker.edit_user(user_id, name, pin)
print(res["message"])
input("Press Enter to continue...")
else:
self._invalid_choice()
except ValueError:
self._invalid_choice()
def _cli_remove_user(self):
self._clear_screen()
print("=" * 50)
print("REMOVE USER")
print("=" * 50)
print()
users = self.tracker.get_all_users()
user_list = list(users.items())
for i, (user_id, user) in enumerate(user_list, 1):
print(f"{i}. {user.name}")
print(f"{len(user_list) + 1}. Cancel")
print()
try:
choice = int(input("Choose user to remove: ").strip())
if choice == len(user_list) + 1:
return
if 1 <= choice <= len(user_list):
user_id = user_list[choice - 1][0]
confirm = input(f"Are you sure you want to delete {users[user_id].name}? (y/n): ").strip().lower()
if confirm == "y":
res = self.tracker.remove_user(user_id)
print(res["message"])
input("Press Enter to continue...")
else:
self._invalid_choice()
except ValueError:
self._invalid_choice()
def _manage_items(self):
while True:
self._clear_screen()
print("=" * 50)
print("MANAGE ITEMS")
print("=" * 50)
print()
print("1. Add item")
print("2. Edit item")
print("3. Remove item")
print("4. Back to admin panel")
print()
choice = input("Choose option: ").strip()
if choice == "1":
self._cli_add_item()
elif choice == "2":
self._cli_edit_item()
elif choice == "3":
self._cli_remove_item()
elif choice == "4":
break
else:
self._invalid_choice()
def _cli_add_item(self):
self._clear_screen()
print("=" * 50)
print("ADD ITEM")
print("=" * 50)
print()
name = input("Enter item name: ").strip()
if not name:
print("Name cannot be empty!")
input("Press Enter to continue...")
return
price_str = input("Enter price ($): ").strip()
try:
price = float(price_str)
if price < 0:
raise ValueError
except ValueError:
print("Invalid price!")
input("Press Enter to continue...")
return
import uuid
item_id = f"item_{uuid.uuid4().hex[:8]}"
res = self.tracker.add_item(item_id, name, price)
print(res["message"])
input("Press Enter to continue...")
def _cli_edit_item(self):
self._clear_screen()
print("=" * 50)
print("EDIT ITEM")
print("=" * 50)
print()
items = self.tracker.get_items()
item_list = list(items.items())
for i, (item_id, item) in enumerate(item_list, 1):
print(f"{i}. {item.name} (${item.price:.2f})")
print(f"{len(item_list) + 1}. Cancel")
print()
try:
choice = int(input("Choose item to edit: ").strip())
if choice == len(item_list) + 1:
return
if 1 <= choice <= len(item_list):
item_id = item_list[choice - 1][0]
item = items[item_id]
new_name = input(f"Enter new name (leave empty to keep '{item.name}'): ").strip()
new_price_str = input(f"Enter new price (leave empty to keep '${item.price:.2f}'): ").strip()
name = new_name if new_name else item.name
price = item.price
if new_price_str:
try:
price = float(new_price_str)
if price < 0:
raise ValueError
except ValueError:
print("Invalid price!")
input("Press Enter to continue...")
return
res = self.tracker.edit_item(item_id, name, price)
print(res["message"])
input("Press Enter to continue...")
else:
self._invalid_choice()
except ValueError:
self._invalid_choice()
def _cli_remove_item(self):
self._clear_screen()
print("=" * 50)
print("REMOVE ITEM")
print("=" * 50)
print()
items = self.tracker.get_items()
item_list = list(items.items())
for i, (item_id, item) in enumerate(item_list, 1):
print(f"{i}. {item.name} (${item.price:.2f})")
print(f"{len(item_list) + 1}. Cancel")
print()
try:
choice = int(input("Choose item to remove: ").strip())
if choice == len(item_list) + 1:
return
if 1 <= choice <= len(item_list):
item_id = item_list[choice - 1][0]
confirm = input(f"Are you sure you want to delete {items[item_id].name}? (y/n): ").strip().lower()
if confirm == "y":
res = self.tracker.remove_item(item_id)
print(res["message"])
input("Press Enter to continue...")
else:
self._invalid_choice()
except ValueError:
self._invalid_choice()