2024-10-09 17:02:48 +00:00
from enum import Enum
from abc import ABC
2024-10-09 17:02:47 +00:00
CONFIRMATION_VALIDATOR = lambda x : x . lower ( ) not in [ ' yes ' , ' y ' , ' no ' , ' n ' ]
2024-10-09 17:02:48 +00:00
class AccountTypes ( Enum ) :
Current = 1
Savings = 2
class Account ( ABC ) :
2024-10-09 17:02:47 +00:00
def __init__ ( self ) :
self . __balance = 0
def getBalance ( self ) :
return self . __balance
def setBalance ( self , newBalance ) :
self . __balance = newBalance
2024-10-09 17:02:48 +00:00
class CurrentAccount ( Account ) :
pass
class SavingsAccount ( Account ) :
INTEREST_RATE = 0.02
def __init__ ( self ) :
super ( ) . __init__ ( )
def calculateInterest ( self ) :
return self . getBalance ( ) * SavingsAccount . INTEREST_RATE
def setBalance ( self , newBalance ) :
if newBalance < 0 :
raise ValueError ( ' You can not have a negative balance! ' )
return super ( ) . setBalance ( newBalance )
2024-10-09 17:02:47 +00:00
class Controller :
OVERDRAWN_FEE = 5
def __init__ ( self , account ) :
self . __account = account
def __overdrawnFee ( self ) :
balance = self . fetchBalance ( )
if balance < 0 :
self . __account . setBalance ( balance - Controller . OVERDRAWN_FEE )
return balance < 0
def fetchBalance ( self ) :
return self . __account . getBalance ( )
def formatBalance ( self ) :
balance = self . fetchBalance ( )
sign = ' ' if balance > = 0 else ' - '
return f ' { sign } £ { abs ( balance ) : .2f } '
def payIn ( self , amount ) :
self . __account . setBalance ( self . fetchBalance ( ) + amount )
def withdraw ( self , amount ) :
fee = self . __overdrawnFee ( )
self . __account . setBalance ( self . fetchBalance ( ) - amount )
return fee
2024-10-09 17:02:48 +00:00
def accountType ( self ) :
if isinstance ( self . __account , CurrentAccount ) :
return AccountTypes . Current
elif isinstance ( self . __account , SavingsAccount ) :
return AccountTypes . Savings
def addInterest ( self ) :
if isinstance ( self . __account , SavingsAccount ) :
interest = self . __account . calculateInterest ( )
self . __account . setBalance ( self . fetchBalance ( ) + interest )
return interest
else :
return 0
2024-10-09 17:02:47 +00:00
def fetchValue ( caster , typeName , prompt , validator = None , validatorFailMessage = None ) :
while True :
try :
value = caster ( input ( prompt ) )
if validator :
if validator ( value ) :
raise ValueError ( ' validator ' )
return value
except ValueError as e :
if str ( e ) == ' validator ' and validatorFailMessage :
print ( validatorFailMessage )
else :
print ( f ' Please make sure you input a valid { typeName } . ' )
def displayBalance ( ) :
print ( f ' You currently have a balance of { controller . formatBalance ( ) } ! ' )
def menu ( ) :
2024-10-09 17:02:48 +00:00
print ( f """ Welcome to the bank! What would you like to do?
2024-10-09 17:02:47 +00:00
1 ) View your current balance
2 ) Pay in money
2024-10-09 17:02:48 +00:00
3 ) Withdraw money """ + ( """
4 ) Add interest """ if controller.accountType() == AccountTypes.Savings else " " ))
2024-10-09 17:02:47 +00:00
2024-10-09 17:02:48 +00:00
choice = fetchValue ( int , ' integer ' , ' Please make your selection: ' , lambda x : ( x > 5 or x < = 0 ) )
2024-10-09 17:02:47 +00:00
if choice == 1 :
displayBalance ( )
elif choice == 2 :
value = fetchValue ( float , ' float ' , ' Please enter the amount of money you would like to pay in: ' )
controller . payIn ( value )
displayBalance ( )
elif choice == 3 :
value = fetchValue ( float , ' float ' , ' Please enter the amount of money you would like to withdraw: ' )
chargedFee = controller . withdraw ( value )
if chargedFee :
print ( f ' You are currently overdrawn! If you go through with this transaction, you will have to pay a fee of £ { Controller . OVERDRAWN_FEE : .2f } , and your balance will become { controller . formatBalance ( ) } . ' )
confirm = fetchValue ( str , ' input ' , ' Would you like to proceed? (y/n) ' , CONFIRMATION_VALIDATOR )
if confirm in [ ' n ' , ' no ' ] :
controller . payIn ( value + Controller . OVERDRAWN_FEE )
print ( ' Your transaction has been cancelled! ' )
else :
displayBalance ( )
else :
displayBalance ( )
2024-10-09 17:02:48 +00:00
elif accountType == AccountTypes . Savings and choice == 4 :
interest = controller . addInterest ( )
print ( f ' Added £ { interest : .2f } worth of interest! ' )
displayBalance ( )
2024-10-09 17:02:47 +00:00
if __name__ == ' __main__ ' :
2024-10-09 17:02:48 +00:00
print ( """ Please choose an account type:
1 ) Current Account
2 ) Savings Account """ )
accountType = AccountTypes . Savings if fetchValue ( int , ' account type ' , ' Please select an account type (1-2): ' , lambda x : ( x < 1 or x > 2 ) ) == 2 else AccountTypes . Current
account = CurrentAccount ( ) if accountType == AccountTypes . Current else SavingsAccount ( )
controller = Controller ( account )
2024-10-09 17:02:47 +00:00
while True :
menu ( )
again = fetchValue ( str , ' input ' , ' Would you like to go again? (y/n) ' , CONFIRMATION_VALIDATOR )
if again in [ ' n ' , ' no ' ] :
break