Started implementation of new_transacion page and other minor changes
This commit is contained in:
Binary file not shown.
@@ -4,6 +4,7 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
import customtkinter
|
import customtkinter
|
||||||
from tkinter import ttk, messagebox
|
from tkinter import ttk, messagebox
|
||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
@@ -152,7 +153,16 @@ def save_details():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("Error", f"Could not update account details: {str(e)}")
|
messagebox.showerror("Error", f"Could not update account details: {str(e)}")
|
||||||
|
|
||||||
|
def open_transaction_window():
|
||||||
|
"""Opens a new window for creating a new transaction."""
|
||||||
|
try:
|
||||||
|
session = json.load(open('application\\session_data.json', 'r'))
|
||||||
|
command = f"python application\\new_transaction.py {session['client_id']}"
|
||||||
|
return_code = os.system(command)
|
||||||
|
if return_code != 0:
|
||||||
|
print(f"Error: The command failed with return code {return_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
|
||||||
##############
|
##############
|
||||||
### Layout ###
|
### Layout ###
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ def get_transactions(account_id):
|
|||||||
|
|
||||||
def get_account(account_id):
|
def get_account(account_id):
|
||||||
"""Retrieves the account details for the given account_id."""
|
"""Retrieves the account details for the given account_id."""
|
||||||
|
print(f"Getting account details for account_id: {account_id}")
|
||||||
try:
|
try:
|
||||||
with open('application\\session_data.json', 'r') as f:
|
with open('application\\session_data.json', 'r') as f:
|
||||||
session_data = json.load(f)
|
session_data = json.load(f)
|
||||||
|
|||||||
@@ -8,17 +8,12 @@ import os
|
|||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
from connection import logout_client, get_client, update_client, get_accounts, format_balance, generate_otp, change_password, new_transaction
|
from connection import logout_client, get_client, update_client, get_accounts, format_balance, generate_otp, change_password, new_transaction
|
||||||
|
|
||||||
|
|
||||||
# Global variables
|
|
||||||
email_entry = None
|
email_entry = None
|
||||||
phone_entry = None
|
phone_entry = None
|
||||||
address_entry = None
|
address_entry = None
|
||||||
otp_entry = None
|
otp_entry = None
|
||||||
frame = None
|
frame = None
|
||||||
|
|
||||||
fields = [('Name', 'name'), ('Client ID', 'client_id'), ('Email', 'email'), ('Phone', 'phone_number'),
|
|
||||||
('Address', 'address'), ('Account Opened', 'opening_timestamp')]
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
### Functions ###
|
### Functions ###
|
||||||
#################
|
#################
|
||||||
@@ -58,7 +53,6 @@ def display_client_info():
|
|||||||
else:
|
else:
|
||||||
frame = customtkinter.CTkFrame(root)
|
frame = customtkinter.CTkFrame(root)
|
||||||
frame.grid(row=1, column=0, padx=20, pady=20)
|
frame.grid(row=1, column=0, padx=20, pady=20)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open('application\\session_data.json', 'r') as f:
|
with open('application\\session_data.json', 'r') as f:
|
||||||
session_data = json.load(f)
|
session_data = json.load(f)
|
||||||
@@ -66,6 +60,8 @@ def display_client_info():
|
|||||||
client_info = get_client(client_id)
|
client_info = get_client(client_id)
|
||||||
if client_info.get('success'):
|
if client_info.get('success'):
|
||||||
client = client_info['data']
|
client = client_info['data']
|
||||||
|
fields = [('Name', 'name'), ('Client ID', 'client_id'), ('Email', 'email'), ('Phone', 'phone_number'),
|
||||||
|
('Address', 'address'), ('Account Opened', 'opening_timestamp')]
|
||||||
for i, (display_name, key) in enumerate(fields):
|
for i, (display_name, key) in enumerate(fields):
|
||||||
value = client.get(key, 'N/A')
|
value = client.get(key, 'N/A')
|
||||||
label_key = customtkinter.CTkLabel(frame, text=f"{display_name}: ", font=("Helvetica", 14))
|
label_key = customtkinter.CTkLabel(frame, text=f"{display_name}: ", font=("Helvetica", 14))
|
||||||
@@ -123,18 +119,14 @@ def save_details():
|
|||||||
new_phone = phone_entry.get() if phone_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
|
new_address = address_entry.get() if address_entry.get() != '' else None
|
||||||
otp_code = otp_entry.get()
|
otp_code = otp_entry.get()
|
||||||
|
|
||||||
if not otp_code:
|
if not otp_code:
|
||||||
messagebox.showerror("Error", "OTP code must be entered.")
|
messagebox.showerror("Error", "OTP code must be entered.")
|
||||||
return
|
return
|
||||||
|
|
||||||
with open('application\\session_data.json', 'r') as f:
|
with open('application\\session_data.json', 'r') as f:
|
||||||
session_data = json.load(f)
|
session_data = json.load(f)
|
||||||
client_id = session_data['client_id']
|
client_id = session_data['client_id']
|
||||||
|
|
||||||
if not messagebox.askyesno("Confirmation", "Are you sure you want to update the details?"):
|
if not messagebox.askyesno("Confirmation", "Are you sure you want to update the details?"):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = update_client(client_id, otp_code, new_email, new_phone, new_address)
|
result = update_client(client_id, otp_code, new_email, new_phone, new_address)
|
||||||
if result['success']:
|
if result['success']:
|
||||||
@@ -161,7 +153,6 @@ def populate_table():
|
|||||||
accounts = response.get('data', [])
|
accounts = response.get('data', [])
|
||||||
if not isinstance(accounts, list):
|
if not isinstance(accounts, list):
|
||||||
raise ValueError(f"Expected a list of accounts, but got {type(accounts)}")
|
raise ValueError(f"Expected a list of accounts, but got {type(accounts)}")
|
||||||
|
|
||||||
for account in accounts:
|
for account in accounts:
|
||||||
formatted_balance = format_balance(account['balance'])
|
formatted_balance = format_balance(account['balance'])
|
||||||
table.insert('', 'end', values=(account['description'], account['account_id'], formatted_balance, account['account_type']))
|
table.insert('', 'end', values=(account['description'], account['account_id'], formatted_balance, account['account_type']))
|
||||||
@@ -233,26 +224,20 @@ def change_password_save():
|
|||||||
new_password = password_entry.get()
|
new_password = password_entry.get()
|
||||||
confirm_password = confirm_password_entry.get()
|
confirm_password = confirm_password_entry.get()
|
||||||
otp_code = otp_entry.get()
|
otp_code = otp_entry.get()
|
||||||
|
|
||||||
if not otp_code:
|
if not otp_code:
|
||||||
messagebox.showerror("Error", "OTP code must be entered.")
|
messagebox.showerror("Error", "OTP code must be entered.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if not new_password or not confirm_password:
|
if not new_password or not confirm_password:
|
||||||
messagebox.showerror("Error", "New password and confirm password must be entered.")
|
messagebox.showerror("Error", "New password and confirm password must be entered.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if new_password != confirm_password:
|
if new_password != confirm_password:
|
||||||
messagebox.showerror("Error", "New password and confirm password do not match.")
|
messagebox.showerror("Error", "New password and confirm password do not match.")
|
||||||
return
|
return
|
||||||
|
|
||||||
with open('application\\session_data.json', 'r') as f:
|
with open('application\\session_data.json', 'r') as f:
|
||||||
session_data = json.load(f)
|
session_data = json.load(f)
|
||||||
client_id = session_data['client_id']
|
client_id = session_data['client_id']
|
||||||
|
|
||||||
if not messagebox.askyesno("Confirmation", "Are you sure you want to change the password?"):
|
if not messagebox.askyesno("Confirmation", "Are you sure you want to change the password?"):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = change_password(client_id, old_password, new_password, otp_code)
|
response = change_password(client_id, old_password, new_password, otp_code)
|
||||||
if response['success']:
|
if response['success']:
|
||||||
@@ -263,6 +248,17 @@ def change_password_save():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("Error", f"Could not change password: {str(e)}")
|
messagebox.showerror("Error", f"Could not change password: {str(e)}")
|
||||||
|
|
||||||
|
def open_transaction_window():
|
||||||
|
"""Opens a new window for creating a new transaction."""
|
||||||
|
try:
|
||||||
|
session = json.load(open('application\\session_data.json', 'r'))
|
||||||
|
command = f"python application\\new_transaction.py {session['client_id']}"
|
||||||
|
return_code = os.system(command)
|
||||||
|
if return_code != 0:
|
||||||
|
print(f"Error: The command failed with return code {return_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
|
||||||
##############
|
##############
|
||||||
### Layout ###
|
### Layout ###
|
||||||
##############
|
##############
|
||||||
@@ -288,7 +284,7 @@ otp_button = customtkinter.CTkButton(button_frame, text="Get OTP Code", command=
|
|||||||
otp_button.grid(row=0, column=0, padx=3)
|
otp_button.grid(row=0, column=0, padx=3)
|
||||||
|
|
||||||
# Create the new transaction button
|
# Create the new transaction button
|
||||||
transaction_button = customtkinter.CTkButton(button_frame, text="New Transaction", command=new_transaction, width=100)
|
transaction_button = customtkinter.CTkButton(button_frame, text="New Transaction", command=open_transaction_window, width=100)
|
||||||
transaction_button.grid(row=0, column=1, padx=3)
|
transaction_button.grid(row=0, column=1, padx=3)
|
||||||
|
|
||||||
# Create the edit client Details button
|
# Create the edit client Details button
|
||||||
|
|||||||
@@ -5,21 +5,84 @@ import tkinter as tk
|
|||||||
from tkinter import ttk, messagebox
|
from tkinter import ttk, messagebox
|
||||||
import customtkinter
|
import customtkinter
|
||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
from connection import format_balance, get_account, new_transaction, generate_otp
|
from connection import new_transaction, generate_otp, get_account, get_accounts
|
||||||
import sys
|
import sys
|
||||||
|
import requests
|
||||||
|
|
||||||
|
account_id = None
|
||||||
|
recipient_id = None
|
||||||
|
|
||||||
#################
|
#################
|
||||||
### Functions ###
|
### Functions ###
|
||||||
#################
|
#################
|
||||||
|
|
||||||
if len(sys.argv) > 3: # Check if the account description is provided as a command line argument
|
if len(sys.argv) > 1: # Check if the account description is provided as a command line argument
|
||||||
account_id = sys.argv[1]
|
client_id = sys.argv[1]
|
||||||
account_description = sys.argv[3] # This is passed so that the window can be titled appopriately
|
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Error", "Account ID and description were not provided by the server.")
|
messagebox.showerror("Error", "Account ID and description were not provided by the server.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
def submit_transaction():
|
||||||
|
"""Submit a new transaction to the server."""
|
||||||
|
global account_id, recipient_id
|
||||||
|
account_id = account_combobox.get()
|
||||||
|
recipient_id = recipient_text.get()
|
||||||
|
amount = amount_text.get() if amount_text.get() != "" else None
|
||||||
|
description = description_text.get() if description_text.get() != "" else None
|
||||||
|
if not description or not amount or not recipient_id or not account_id:
|
||||||
|
messagebox.showerror("Error", "Please fill in all fields.")
|
||||||
|
return
|
||||||
|
account_verification = verify_accounts(account_id, recipient_id)
|
||||||
|
if account_verification is False:
|
||||||
|
messagebox.showerror("Error", "Could not verify account IDs.")
|
||||||
|
return
|
||||||
|
response = new_transaction(account_id, description, amount, recipient_id)
|
||||||
|
if response is None or "data" not in response:
|
||||||
|
messagebox.showerror("Error", "Could not submit transaction.")
|
||||||
|
return
|
||||||
|
transaction_id = response["data"]
|
||||||
|
otp = generate_otp(account_id, transaction_id)
|
||||||
|
if otp is None or "data" not in otp:
|
||||||
|
messagebox.showerror("Error", "Could not generate OTP.")
|
||||||
|
return
|
||||||
|
messagebox.showinfo("Success", f"Transaction submitted successfully. OTP: {otp['data']}")
|
||||||
|
|
||||||
|
def verify_accounts():
|
||||||
|
"""Verify that the account IDs are valid."""
|
||||||
|
try:
|
||||||
|
account = get_account(account_id)
|
||||||
|
recipient_account = get_account(recipient_id)
|
||||||
|
print(account)
|
||||||
|
print(recipient_account)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
messagebox.showerror("Error", f"Failed to get account details: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if account is None or recipient_account is None or "data" not in account or "data" not in recipient_account:
|
||||||
|
messagebox.showerror("Error", "Server did not return the expected response.")
|
||||||
|
return False
|
||||||
|
if "account_id" not in account["data"]:
|
||||||
|
messagebox.showerror("Error", "Account ID not found.")
|
||||||
|
return False
|
||||||
|
if "account_id" not in recipient_account["data"]:
|
||||||
|
messagebox.showerror("Error", "Recipient Account ID not found.")
|
||||||
|
return False
|
||||||
|
#check balance
|
||||||
|
if account["data"]["balance"] < float(amount_text.get("1.0", "end-1c")):
|
||||||
|
messagebox.showerror("Error", "Insufficient funds.")
|
||||||
|
return False
|
||||||
|
submit_button.configure(state=tk.NORMAL) # Enable the submit button if the accounts are valid
|
||||||
|
messagebox.showinfo("Success", "Accounts verified successfully.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def populate_accounts(client_id):
|
||||||
|
"""Populate the account combobox with accounts for the given client ID."""
|
||||||
|
accounts = get_accounts(client_id)
|
||||||
|
if accounts is None or "data" not in accounts:
|
||||||
|
messagebox.showerror("Error", "Could not retrieve accounts.")
|
||||||
|
return
|
||||||
|
account_ids = [account["account_id"] for account in accounts["data"]]
|
||||||
|
account_combobox['values'] = account_ids
|
||||||
|
|
||||||
##############
|
##############
|
||||||
### Layout ###
|
### Layout ###
|
||||||
@@ -27,9 +90,9 @@ else:
|
|||||||
|
|
||||||
# Initialise the main window
|
# Initialise the main window
|
||||||
root = customtkinter.CTk()
|
root = customtkinter.CTk()
|
||||||
root.title(f"Transactions: {transaction_description}")
|
root.title("New Transaction")
|
||||||
root.iconbitmap("application/luxbank.ico")
|
root.iconbitmap("application/luxbank.ico")
|
||||||
root.geometry("800x400")
|
root.geometry("400x600")
|
||||||
|
|
||||||
if CONFIG["preferences"]["dark_theme"] == "dark": # Check if dark mode is enabled
|
if CONFIG["preferences"]["dark_theme"] == "dark": # Check if dark mode is enabled
|
||||||
customtkinter.set_appearance_mode("dark") # Set the style for dark mode
|
customtkinter.set_appearance_mode("dark") # Set the style for dark mode
|
||||||
@@ -37,7 +100,57 @@ else:
|
|||||||
customtkinter.set_appearance_mode("light") # Set the style for light mode
|
customtkinter.set_appearance_mode("light") # Set the style for light mode
|
||||||
|
|
||||||
# Display main window title
|
# Display main window title
|
||||||
welcome_label = customtkinter.CTkLabel(root, text=f"Transactions for: {account_description}", font=("Helvetica", 24))
|
welcome_label = customtkinter.CTkLabel(root, text="New Transaction", font=("Helvetica", 24))
|
||||||
welcome_label.pack(pady=10)
|
welcome_label.pack(pady=20)
|
||||||
|
|
||||||
|
# Create a close button at the top of the window
|
||||||
|
close_button = customtkinter.CTkButton(root, text="Cancel and Close", command=root.destroy)
|
||||||
|
close_button.pack(side="top", anchor="e", padx=10, pady=10)
|
||||||
|
|
||||||
|
# Create the account ID label and combobox
|
||||||
|
account_label = customtkinter.CTkLabel(root, text="Account ID:", font=("Helvetica", 14))
|
||||||
|
account_label.pack(pady=5)
|
||||||
|
account_combobox = ttk.Combobox(root, height=1, width=250)
|
||||||
|
account_combobox.pack(pady=5)
|
||||||
|
|
||||||
|
# Create the recipient ID label and text box
|
||||||
|
recipient_label = customtkinter.CTkLabel(root, text="Recipient ID:", font=("Helvetica", 14))
|
||||||
|
recipient_label.pack(pady=5)
|
||||||
|
recipient_text = customtkinter.CTkTextbox(root, height=2, width=250)
|
||||||
|
recipient_text.pack(pady=5)
|
||||||
|
|
||||||
|
# Create the verify buttons
|
||||||
|
verify_button = customtkinter.CTkButton(root, text="Verify Accounts", command=verify_accounts)
|
||||||
|
verify_button.pack(pady=10)
|
||||||
|
|
||||||
|
# Create the transaction description label and text box
|
||||||
|
description_label = customtkinter.CTkLabel(root, text="Description:", font=("Helvetica", 14))
|
||||||
|
description_label.pack(pady=5)
|
||||||
|
description_text = customtkinter.CTkTextbox(root, height=4, width=250)
|
||||||
|
description_text.pack(pady=5)
|
||||||
|
|
||||||
|
# Create the transaction amount label and text box
|
||||||
|
amount_label = customtkinter.CTkLabel(root, text="Amount:", font=("Helvetica", 14))
|
||||||
|
amount_label.pack(pady=5)
|
||||||
|
amount_text = customtkinter.CTkTextbox(root, height=2, width=250)
|
||||||
|
amount_text.pack(pady=5)
|
||||||
|
|
||||||
|
# Create the OTP button
|
||||||
|
otp_button = customtkinter.CTkButton(root, text="Request OTP", command=generate_otp)
|
||||||
|
otp_button.pack(pady=10)
|
||||||
|
|
||||||
|
# Create the OTP label and text box
|
||||||
|
otp_label = customtkinter.CTkLabel(root, text="OTP:", font=("Helvetica", 14))
|
||||||
|
otp_label.pack(pady=5)
|
||||||
|
otp_text = customtkinter.CTkTextbox(root, height=2, width=250)
|
||||||
|
otp_text.pack(pady=5)
|
||||||
|
|
||||||
|
# Create the submit button
|
||||||
|
submit_button = customtkinter.CTkButton(root, text="Submit", command=submit_transaction, state=tk.DISABLED)
|
||||||
|
submit_button.pack(pady=5)
|
||||||
|
|
||||||
|
# Populate accounts combobox with the given client_id
|
||||||
|
populate_accounts(client_id)
|
||||||
|
|
||||||
|
# Display the main window
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"session_cookie": {"session": "9pRNUPAL2SDrVihKeZcAAb_uw6GzpPm2uTHqrE8urjE"}, "client_id": "9755c18f"}
|
{"session_cookie": {"session": "rVrt6XfG-HNcgZwJHJGmwEg8boBPPRljoCFcrRfQ-ss"}, "client_id": "9755c18f"}
|
||||||
@@ -162,7 +162,7 @@ def generate_otp(client_id: str):
|
|||||||
otps[client_id] = (password, time.time()) # Store the OTP and the current time
|
otps[client_id] = (password, time.time()) # Store the OTP and the current time
|
||||||
return format_response(True, "OTP generated and sent successfully."), 200
|
return format_response(True, "OTP generated and sent successfully."), 200
|
||||||
except EmailSendingError as e:
|
except EmailSendingError as e:
|
||||||
print(f"Error sending email: {e}")
|
log_event(f"Error sending email: {str(e)}")
|
||||||
error_message = "Error sending email. Please try again later."
|
error_message = "Error sending email. Please try again later."
|
||||||
if e.original_error:
|
if e.original_error:
|
||||||
error_message += f" Original error: {str(e.original_error)}"
|
error_message += f" Original error: {str(e.original_error)}"
|
||||||
@@ -251,6 +251,8 @@ def get_accounts(client_id: str):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def get_account(account_id:str):
|
def get_account(account_id:str):
|
||||||
|
"""Returns a specific account in the database. If the account is not found, returns an error message."""
|
||||||
|
print(account_id)
|
||||||
current_client_id, is_admin = get_current_client()
|
current_client_id, is_admin = get_current_client()
|
||||||
account_owner = session.query(Account).filter_by(account_id=account_id).one_or_none().client_id
|
account_owner = session.query(Account).filter_by(account_id=account_id).one_or_none().client_id
|
||||||
if not is_admin and account_owner != current_client_id:
|
if not is_admin and account_owner != current_client_id:
|
||||||
|
|||||||
Reference in New Issue
Block a user