From 706a4dd47d8c4f6f8c68fe9a449a37ef29a063ab Mon Sep 17 00:00:00 2001 From: schn33fuchs Date: Tue, 2 Jun 2026 14:04:14 +0200 Subject: [PATCH] CLI interface CLI interface added --- main.py | 23 ++-- ui/cli.py | 370 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 384 insertions(+), 9 deletions(-) create mode 100644 ui/cli.py diff --git a/main.py b/main.py index 57ab78a..7b18323 100644 --- a/main.py +++ b/main.py @@ -1,29 +1,34 @@ from core.tracker import Tracker from storage.data_manager import DataManager from config import REGISTERED_USERS, MENU_ITEMS +from ui.cli import CLI -def main(): - data_manager = DataManager("data") - tracker = Tracker(data_manager) +def init_data(tracker, data_manager): + from core.user import User + from core.item import Item if not tracker.users: - from core.user import User - from core.item import Item - for user_id, name in REGISTERED_USERS.items(): tracker.users[user_id] = User(user_id, name) data_manager.save_users(tracker.users) + if not tracker.items: for item_id, item_data in MENU_ITEMS.items(): tracker.items[item_id] = Item( item_id, item_data["name"], item_data["price"] ) data_manager.save_items(tracker.items) - print("DebtTracker initialized successfully!") - print(f"Users: {[u.name for u in tracker.users.values()]}") - print(f"Menu items: {[m.name for m in tracker.items.values()]}") + +def main(): + dm = DataManager("data") + tracker = Tracker(dm) + + init_data(tracker, dm) + + cli = CLI(tracker) + cli.run() if __name__ == "__main__": diff --git a/ui/cli.py b/ui/cli.py new file mode 100644 index 0000000..019ba63 --- /dev/null +++ b/ui/cli.py @@ -0,0 +1,370 @@ +from core.tracker import Tracker +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 os + + os.system("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. 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": + 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()[t.item_id] + 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...")