diff --git a/application/account.py b/application/account.py new file mode 100644 index 0000000..6a5cc0e --- /dev/null +++ b/application/account.py @@ -0,0 +1,116 @@ +# Lucas Mathews - Fontys Student ID: 5023572 +# Banking System Account Page + +import tkinter as tk +from tkinter import messagebox, ttk +import customtkinter +import json +from config import CONFIG +from connection import get_transactions, format_balance, get_account +import sys + +################# +### Functions ### +################# + +if len(sys.argv) > 3: # Check if the account description is provided as a command line argument + account_description = sys.argv[3] +else: + print("Error: Account description not provided.") + +def open_account_page(account): + account_window = tk.Toplevel() + + # Display the account details + account_label = tk.Label(account_window, text=f"Account ID: {account['account_id']} | Account Type: {account['account_type']} | Balance: {format_balance(account['balance'])}") + account_label.pack() + + # Create buttons for making a new transaction and editing the account details + new_transaction_button = tk.Button(account_window, text="New Transaction", command=lambda: new_transaction(account)) + new_transaction_button.pack() + + edit_account_button = tk.Button(account_window, text="Edit Account", command=lambda: edit_account(account)) + edit_account_button.pack() + + transactions_frame = tk.Frame(account_window) # Create a frame for the transactions table + transactions_frame.pack(side='bottom', fill='both', expand=True) + + # Create a table for the transactions + transactions_table = ttk.Treeview(transactions_frame, columns=("Transaction ID", "Amount", "Date", "Description"), show="headings") + transactions_table.heading("Transaction ID", text="Transaction ID") + transactions_table.heading("Amount", text="Amount") + transactions_table.heading("Date", text="Date") + transactions_table.heading("Description", text="Description") + transactions_table.pack(fill='both', expand=True) + populate_transactions_table(transactions_table, account) # Populate the transactions table + + +def populate_transactions_table(table, account): + with open('application\\session_data.json', 'r') as f: + session_data = json.load(f) + client_id = session_data['client_id'] + account_id = account['account_id'] + response = get_transactions(account_id) + if response is None or 'data' not in response: # Check if the response is valid + print(f"Error: Unable to fetch transactions for account {account_id}") + return + transactions = response['data'] + if not isinstance(transactions, list): # Check if transactions is a list + print(f"Error: Expected a list of transactions for account {account_id}, but got {type(transactions)}") + return + for transaction in transactions: # Populate the table with the transactions + table.insert('', 'end', values=(transaction['transaction_id'], format_balance(transaction['amount']), transaction['date'], transaction['description'])) + open_account_button = tk.Button(root, text="Open Account", command=lambda: open_account_page(get_selected_account())) + open_account_button.pack() + def get_selected_account(): # Implement this function to return the selected account + selected_item = table.selection()[0] # Get the selected item + account_id = table.item(selected_item)["values"][1] # Get the account ID from the selected item + return get_account(account_id) # Fetch the account details and return them + +############## +### Layout ### +############## + +root = customtkinter.CTk() + +root.title(account_description) +root.iconbitmap("application/luxbank.ico") +root.geometry("800x400") + +if CONFIG["preferences"]["dark_theme"] == "dark": # Check if dark mode is enabled + customtkinter.set_appearance_mode("dark") # Set the style for dark mode +else: + customtkinter.set_appearance_mode("light") # Set the style for light mode + +welcome_label = customtkinter.CTkLabel(root, text=f"Transactions for: {account_description}", font=("Helvetica", 24)) +welcome_label.pack(pady=20) + +frame = customtkinter.CTkFrame(root) + +table = ttk.Treeview(frame, columns=("Description", "Account ID", "Balance", "Account Type"), show="headings") +table.heading("Description", text="Description") +table.heading("Account ID", text="Account ID") +table.heading("Balance", text="Balance") +table.heading("Account Type", text="Account Type") +table.pack() + +table.column("Description", width=200) +table.column("Account ID", width=100) +table.column("Balance", width=100) +table.column("Account Type", width=100) + +# Bind the double-click event to the table +table.bind("", lambda event: open_account_page(get_selected_account())) + + +def get_selected_account(): + selected_items = table.selection() # Get the selected items + if selected_items: # Check if any items are selected + selected_item = selected_items[0] # Get the first selected item + account_id = table.item(selected_item)["values"][1] # Get the account ID from the selected item + return get_account(account_id) # Fetch the account details and return them + else: + messagebox.showinfo("No selection", "Please select an account first.") + return None + +root.mainloop() \ No newline at end of file diff --git a/application/app.ini b/application/app.ini index a2afe2a..30c7758 100644 --- a/application/app.ini +++ b/application/app.ini @@ -8,3 +8,7 @@ dark_theme=dark # Modes: light, dark theme=dark-blue # Themes: blue, dark-blue, green + +[client] +default_id=31d90aad +default_password=Happymeal1 diff --git a/application/connection.py b/application/connection.py index 7cf54fd..48e39c9 100644 --- a/application/connection.py +++ b/application/connection.py @@ -110,3 +110,42 @@ def get_transactions(account_id): print(f"RequestException: {e}") return {'success': False, 'message': "Could not connect to the server. Please try again later."} +def get_account(account_id): + try: + with open('application\\session_data.json', 'r') as f: + session_data = json.load(f) + + response = requests.get( + CONFIG["server"]["url"] + "/Account", + cookies=session_data['session_cookie'], + params={'account_id': account_id} + ) + response.raise_for_status() # Raise an exception if the request failed + return response.json() + except requests.exceptions.RequestException as e: + print(f"RequestException: {e}") + return {'success': False, 'message': "Could not connect to the server. Please try again later."} + +def update_account(account_id, description=None, notes=None): + try: + with open('application\\session_data.json', 'r') as f: + session_data = json.load(f) + + # Create a dictionary of parameters to update + params = {'account_id': account_id} + if description is not None: + params['description'] = description + if notes is not None: + params['notes'] = notes + + response = requests.put( + CONFIG["server"]["url"] + "/Account", + cookies=session_data['session_cookie'], + params=params + ) + response.raise_for_status() # Raise an exception if the request failed + return response.json() + except requests.exceptions.RequestException as e: + print(f"RequestException: {e}") + return {'success': False, 'message': "Could not connect to the server. Please try again later."} + diff --git a/application/dashboard.py b/application/dashboard.py index 3d20ebc..bab5f21 100644 --- a/application/dashboard.py +++ b/application/dashboard.py @@ -6,19 +6,14 @@ from tkinter import messagebox, ttk import customtkinter import json from config import CONFIG - - +import os from connection import logout_client, get_client, update_client, get_accounts, format_balance - email_entry = None phone_entry = None address_entry = None frame = None - - - ################# ### Functions ### ################# @@ -98,54 +93,38 @@ def save_details(): new_email = email_entry.get() if email_entry.get() != '' else None new_phone = phone_entry.get() if phone_entry.get() != '' else None new_address = address_entry.get() if address_entry.get() != '' else None - - # Get the client_id from the session data with open('application\\session_data.json', 'r') as f: session_data = json.load(f) client_id = session_data['client_id'] - - # Display a confirmation dialog box if not messagebox.askyesno("Confirmation", "Are you sure you want to update the details?"): return # If the user clicked 'No', exit the function - - # Update the client details result = update_client(client_id, new_email, new_phone, new_address) - # If the request was successful, update the client info displayed in the main window if result['success']: display_client_info() - - # Destroy the window after updating the client info - edit_window.destroy() + edit_window.destroy() def populate_table(): - # Get the client_id from the session data - with open('application\\session_data.json', 'r') as f: + with open('application\\session_data.json', 'r') as f: # Get the client_id from the session data session_data = json.load(f) client_id = session_data['client_id'] - - # Get the accounts for the client - response = get_accounts(client_id) + response = get_accounts(client_id) # Get the accounts for the client accounts = response['data'] if 'data' in response else [] - - # Check if accounts is a list - if not isinstance(accounts, list): + if not isinstance(accounts, list): # Check if accounts is a list print(f"Error: Expected a list of accounts, but got {type(accounts)}") return - - # Populate the table with the accounts - for account in accounts: + for account in accounts: # Populate the table with the accounts formatted_balance = format_balance(account['balance']) table.insert('', 'end', values=(account['description'], account['account_id'], formatted_balance, account['account_type'])) def on_account_double_click(event): - # Get the selected account - selected_account = table.item(table.selection()) + try: + selected_account = table.item(table.selection()) # Get the selected account + session = json.load(open('application\\session_data.json', 'r')) # Get the session data + account_description = selected_account['values'][0] + os.system(f"python application\\account.py {selected_account['values'][1]} {session['client_id']} \"{account_description}\"") + except Exception as e: + print(f"Error: {e}") - # Open a new window - account_window = tk.Toplevel(root) - - # Display the account details - display_account_details(account_window, selected_account) ############## ### Layout ### @@ -157,13 +136,10 @@ root.title("Luxbank Dashboard") root.iconbitmap("application/luxbank.ico") root.geometry("800x350") -# Check if dark mode is enabled -if CONFIG["preferences"]["dark_theme"] == "dark": - # Set the style for dark mode - customtkinter.set_appearance_mode("dark") +if CONFIG["preferences"]["dark_theme"] == "dark": # Check if dark mode is enabled + customtkinter.set_appearance_mode("dark") # Set the style for dark mode else: - # Set the style for light mode - customtkinter.set_appearance_mode("light") + customtkinter.set_appearance_mode("light") # Set the style for light mode # Create a label for the title welcome_label = customtkinter.CTkLabel(root, text="Welcome to the Luxbank Dashboard!", font=("Helvetica", 24)) @@ -179,14 +155,14 @@ table_frame = ttk.Frame(root) table_frame.pack(side='right', fill='both', expand=True) # Create the table -table = ttk.Treeview(table_frame, columns=('Description', 'Account ID', 'Balance', 'Account Type'), show='headings') -table.heading('Description', text='Description') +table = ttk.Treeview(table_frame, columns=('Name', 'Account ID', 'Balance', 'Account Type'), show='headings') +table.heading('Name', text='Name') table.heading('Account ID', text='Account ID') table.heading('Balance', text='Balance') table.heading('Account Type', text='Account Type') # Set the column widths -table.column('Description', width=200) +table.column('Name', width=200) table.column('Account ID', width=100) table.column('Balance', width=100) table.column('Account Type', width=100) diff --git a/application/login.py b/application/login.py index f00d5e0..cad844a 100644 --- a/application/login.py +++ b/application/login.py @@ -14,8 +14,8 @@ from config import CONFIG ################# def login(): - client_id = entry_username.get() - client_password = entry_password.get() + client_id = entry_username.get() if entry_username.get() else CONFIG["client"]["default_id"] + client_password = entry_password.get() if entry_password.get() else CONFIG["client"]["default_password"] try: response = authenticate_client(client_id, client_password) # Authenticate the client json_response = response.json() # Convert the response content to JSON @@ -37,8 +37,10 @@ def login(): ### Layout ### ############## -customtkinter.set_appearance_mode((CONFIG["preferences"]["dark_theme"])) # Modes: system (default), light, dark -customtkinter.set_default_color_theme((CONFIG["preferences"]["theme"])) # Themes: blue (default), dark-blue, green +if CONFIG["preferences"]["dark_theme"] == "dark": # Check if dark mode is enabled + customtkinter.set_appearance_mode("dark") # Set the style for dark mode +else: + customtkinter.set_appearance_mode("light") # Set the style for light mode root = customtkinter.CTk() diff --git a/application/session_data.json b/application/session_data.json index 93dd9c7..c4f9573 100644 --- a/application/session_data.json +++ b/application/session_data.json @@ -1 +1 @@ -{"session_cookie": {"session": "xC02SzGKn_a4_R2fhKuj8qNWFk1MIx9zjatqzyzpRBM"}, "client_id": "31d90aad"} \ No newline at end of file +{"session_cookie": {"session": "a7Gs_67Dz2cXT6kbk0IMxupSkpxND5x7PIdiPK4RJgA"}, "client_id": "31d90aad"} \ No newline at end of file