Today I continued my banking system exercise from yesterday. I admit I had to use a lot of ChatGPT (and started using GitHub Copilot) to build this and it sort of grew over my head, even tho I was able to make it work.
Doesn’t feel like I mastered classes yet, so I’ll probably do some smaller exercise with them in the coming days. Suggestions would always be welcome :)
Anyways here is my working banking system:
"""
Exercise: Simple Banking System 2 - This is a continuation of the previous days exercise.
Create a basic banking system.
Allow users to create a new account, deposit money, withdraw money, and check their balance. With a master password one can also check all balances.
Account details are stored in JSON file, so they are continuous even after the program is closed.
Use classes to represent users and accounts.
"""
import json
import logging
logging.basicConfig(level=logging.INFO)
class Account:
def __init__(self, account_id, holder_name, initial_balance=0):
self.account_id = account_id
self.holder_name = holder_name
self.balance = initial_balance
def deposit(self, amount):
if amount > 0:
self.balance += amount
logging.info(f"Deposited {amount}. New balance of {self.holder_name}: {self.balance}")
else:
logging.warning("Invalid deposit amount.")
def withdraw(self, amount):
if 0 < amount <= self.balance:
self.balance -= amount
logging.info(f"Withdrew {amount}. New balance of {self.holder_name}: {self.balance}")
else:
logging.warning("Invalid withdrawal amount or insufficient funds.")
def get_balance(self):
return self.balance
class Bank:
def __init__(self):
self.accounts = {}
self.used_ids = set()
self.load_accounts()
def save_accounts(self):
if not self.accounts:
logging.warning("No accounts to save.")
return
with open('accounts.json', 'w') as file:
data = {account_id: {'holder_name': account.holder_name, 'balance': account.balance} for account_id, account in self.accounts.items()}
json.dump(data, file)
logging.debug(f"Saved accounts: {data}")
def load_accounts(self):
try:
with open('accounts.json', 'r') as file:
data = json.load(file)
if not data:
logging.warning("JSON file is empty.")
return
for account_id, account_info in data.items():
account_id = int(account_id) # Convert to int since JSON keys are always strings
self.accounts[account_id] = Account(account_id, account_info['holder_name'], account_info['balance'])
self.used_ids.add(account_id)
logging.debug(f"Loaded accounts: {self.accounts.keys()}")
logging.debug(f"Used IDs after loading: {self.used_ids}")
except (FileNotFoundError, json.JSONDecodeError) as e:
logging.warning(f"Error loading account data: {e}")
logging.info("No existing account data found or file is empty. Starting fresh.")
def create_account(self, holder_name, initial_balance=0):
account_id = self.generate_account_id()
new_account = Account(account_id, holder_name, initial_balance)
self.accounts[account_id] = new_account
self.used_ids.add(account_id)
logging.info(f"Account created with ID: {account_id}")
return account_id
def generate_account_id(self):
# Find the lowest unused ID
current_id = 1
while current_id in self.used_ids:
current_id += 1
return current_id
def get_account(self, account_id):
return self.accounts.get(account_id, None)
def main():
bank = Bank()
try:
while True:
user_input = input('What would you like to do? Options: n = new account, d = deposit money, w = withdraw money, c = check balance, l = list all accounts, e = exit\\n')
if user_input == 'n':
holder_name = input('Enter your name: ')
initial_balance = float(input('Enter initial deposit: '))
account_id = bank.create_account(holder_name, initial_balance)
bank.save_accounts()
elif user_input == 'd' or user_input == 'w' or user_input == 'c':
try:
while True:
account_id = int(input('Enter account ID: '))
if account_id in bank.used_ids:
break
else:
logging.warning("Invalid account ID.")
account = bank.get_account(account_id)
if user_input == 'd':
amount = float(input('Enter deposit amount: '))
account.deposit(amount)
bank.save_accounts()
elif user_input == 'w':
amount = float(input('Enter withdrawal amount: '))
account.withdraw(amount)
bank.save_accounts()
elif user_input == 'c':
print(f"Current balance: {account.get_balance()}")
except ValueError:
logging.warning("Invalid account ID.")
elif user_input == 'l':
master_password = input('Enter master password: ')
if master_password == '42':
if not bank.accounts: # Check if the bank's accounts dictionary is empty
print("No accounts.")
else:
print("Accounts:")
for account_id, account in bank.accounts.items():
print(f"{account_id}: {account.holder_name} - {account.balance}")
else:
logging.warning("Invalid master password.")
elif user_input == 'e':
break
else:
logging.info("Invalid option selected.")
except KeyboardInterrupt:
logging.error('KeyboardInterrupt')
except ValueError:
logging.error("Invalid input. Please enter a number.")
logging.debug('main() end')
if __name__ == '__main__':
main()