Need Help on Design Patterns for my OOP bank account program in python 3
$begingroup$
Python beginner here. Building an OOP bank account program with sqlite and starting to struggle a bit with its design. From a design standpoint I have a file (bank) which calls ATM. ATM simulates an ATM, and is the file which then calls bank_account or credit_card depending on the account data passed in from bank.
To initially setup an account I decided to put this into a different file, for example bank_account_setup or for credit_card, credit_card_setup. These would create_account, help setup pin etc so that the account is created and ready to use. Then the actual bank_account or credit_card contains other functions, like, deposit, withdraw, get_balance etc. Also send_email is in another file
My question is basically around my design, is there a way to structure this better? How about my setup files to create bank or credit card accts? Is that a good or bad idea? Also - another issue I am having is that when I run bank I pass in account type to ATM. In ATM I then had to know what class I am using in advance and instantiate that inside ATM. Could I handle that dynamically?
(Also - the code does work - just concerned with bad design)
Thanks in advance. Code samples below
Heres my calling file bank:
import atm
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
if __name__ == '__main__':
obj1 = atm.ATM.main_menu( "Frank Smith", 135063522, 5544, 850, 'credit_card', 4400110022004400)
Heres ATM, which calls the other files:
import sqlite3, smtplib
import bank_account
import secrets
import send_email
import credit_card
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class ATM:
def get_pin(account_number, acctype, user_pin):
with conn:
db_pin = c.execute("SELECT pin from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
db_pin = c.fetchone()
if db_pin is not None:
return(db_pin[0])
else:
print("db pin is None")
pass
def set_pin(account_number, acctype, input_code):
with conn:
get_code = ATM.get_user_code(account_number, acctype)
if get_code is None:
pass
print("You need to request an authorization code first before you set your pin")
else:
if get_code !=input_code:
print("Authorization code not valid")
else:
pin = input("Please set your 4 digit pin: ")
if len(pin) < 4 or len(pin) >4 or len(pin) == 4 and pin.isdigit()==False:
print("This is not a 4 digit pin")
else:
print("pin accepted")
c.execute("""UPDATE {} SET pin=:pin
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'pin':pin})
print("Pin for account has been updated")
def main_menu(name, social, account_number, balance, acctype, card_no=None):
# obj1 = bank_account.BankAccount(name, social, account_number, balance, acctype)
# obj1 = credit_card.CreditCard(name, social, account_number, balance, acctype, card_no)
user_pin = int(input("nATM Home Screen. Please enter your pin code: "))
db_pin = ATM.get_pin(account_number, acctype, user_pin)
if user_pin != db_pin and db_pin != '':
print("No pin match")
elif db_pin is '':
print("Pin has not been set")
print("First request an authorization code and use that to set the pin")
else:
user_pin == db_pin
print("nPin accepted continue n ")
print("""""""ATM Menu, choose an option""""""")
print("n1 - Deposit funds")
print("2 - Withdraw funds")
print("3 - Check balance")
print("4 - Reset Pin")
print("5 - Exit")
while True:
try:
choice = int(input("Please enter a number: "))
except ValueError:
print("This is not a number")
if choice >= 1 and choice <=5:
if choice == 1:
amount = input("nPlease enter the deposit amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.deposit( account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice == 2:
amount = input("Please enter the withdrawl amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.withdraw(account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice ==3:
obj1.get_balance(account_number, acctype)
elif choice ==4:
new_pin = input("Please enter a new 4 digit pin: ")
if new_pin != '' and new_pin.isdigit():
int(new_pin)
obj1.set_reset_pin(account_number, acctype, new_pin)
elif choice ==5:
break
else:
print("Not a valid number")
A piece of bank_account_setup:
import sqlite3
import secrets
import getpass
import smtplib, sqlite3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
""" create different accounts based on account type passed in """
def create_account(self, name, social, account_number, balance, acctype, card_no=None, credit_score=None, credit_limit=None):
self.rate = None
with conn:
# account_found = BankAccount.get_account(self, account_number, acctype)
# if not account_found:
if acctype == 'bank_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :pin)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'pin':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'savings_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :rate)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'rate':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'credit_card':
c.execute("INSERT INTO credit_card VALUES (:name, :social, :account_number, :balance, :card_no,:credit_score, :credit_limit, :pin)",
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'card_no'
:card_no, 'credit_score':credit_score, 'credit_limit':credit_limit, 'pin':'' })
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
conn.commit()
Piece of bank_account:
import sqlite3
import secrets
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
def get_balance(self, account_number, acctype):
with conn:
balance = c.execute("SELECT balance from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
balance = c.fetchone()
print("The balance for account number: {} is ${}".format(account_number, balance[0]))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_balance = notif_set[4]
name = notif_set[0]
if notif_balance == 1:
notify = send_email.send_email(account_number, acctype, 'Balance', balance, balance, name)
return(balance[0])
""" Deposit funds into the account number + acctype for the account passed in """
def deposit(self, account_number, acctype, amount):
with conn:
""" Check acct exists before making deposit """
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
existing_bal = account_found[3]
c.execute("""UPDATE {} SET balance=balance +:amount
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'amount':amount})
new_bal = existing_bal + (int(amount))
print("${} has been deposited to account {} and the new balance is ${}".format(amount, account_number, existing_bal + (int(amount))))
# Check email configurations are turned on for deposits
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_deposits = notif_set[5]
name = notif_set[0]
if notif_deposits == 1:
notify = send_email.send_email(account_number, acctype, 'Deposit', amount, new_bal, name)
Piece of credit_card:
from bank_account import BankAccount
import sqlite3
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class CreditCard(BankAccount):
def __init__(self, name, social, account_number, balance, acctype, card_no, credit_score=None, credit_limit=None):
super().__init__(name, social, account_number, balance, acctype)
self.card_no = card_no
self.credit_score = credit_score
self.credit_limit = credit_limit
""" set credit limit, check if acct exists, then call get credit limit """
def set_credit_limit(self, account_number, acctype, credit_score):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
credit_limit = CreditCard.set_credit_limit_helper(self, account_number, credit_score)
if credit_limit:
c.execute("""UPDATE credit_card SET credit_limit=:credit_limit
WHERE account_number =:account_number """,
{'account_number':account_number, 'credit_limit':credit_limit})
print("Account number {} credit limit is set to {}".format(account_number, credit_limit))
conn.commit()
def withdraw(self, account_number, acctype, amount):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
balance = account_found[3]
credit_limit = CreditCard.get_credit_limit(self, account_number)
amount_left = credit_limit - (int(balance))
if balance - (int(amount)) < credit_limit:
print("Your balance is: {}, and your credit limit is: {}".format(balance, credit_limit))
print("The max you can withdraw is {}".format(amount_left))
else:
existing_bal = account_found[3]
c.execute("""UPDATE credit_card SET balance=balance -:amount
WHERE account_number =:account_number""",
{'account_number':account_number, 'amount':amount})
print("${} has been withdrawn from account {} and the new balance is ${}".format(amount, account_number, existing_bal - (int(amount))))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications have been set for this acct")
else:
notif_withdraw = notif_set[7]
if notif_withdraw == 1:
notify = BankAccount.send_email(self,account_number, acctype, 'Withdraw', amount, existing_bal - amount)
conn.commit()
object-oriented design-patterns
New contributor
$endgroup$
add a comment |
$begingroup$
Python beginner here. Building an OOP bank account program with sqlite and starting to struggle a bit with its design. From a design standpoint I have a file (bank) which calls ATM. ATM simulates an ATM, and is the file which then calls bank_account or credit_card depending on the account data passed in from bank.
To initially setup an account I decided to put this into a different file, for example bank_account_setup or for credit_card, credit_card_setup. These would create_account, help setup pin etc so that the account is created and ready to use. Then the actual bank_account or credit_card contains other functions, like, deposit, withdraw, get_balance etc. Also send_email is in another file
My question is basically around my design, is there a way to structure this better? How about my setup files to create bank or credit card accts? Is that a good or bad idea? Also - another issue I am having is that when I run bank I pass in account type to ATM. In ATM I then had to know what class I am using in advance and instantiate that inside ATM. Could I handle that dynamically?
(Also - the code does work - just concerned with bad design)
Thanks in advance. Code samples below
Heres my calling file bank:
import atm
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
if __name__ == '__main__':
obj1 = atm.ATM.main_menu( "Frank Smith", 135063522, 5544, 850, 'credit_card', 4400110022004400)
Heres ATM, which calls the other files:
import sqlite3, smtplib
import bank_account
import secrets
import send_email
import credit_card
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class ATM:
def get_pin(account_number, acctype, user_pin):
with conn:
db_pin = c.execute("SELECT pin from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
db_pin = c.fetchone()
if db_pin is not None:
return(db_pin[0])
else:
print("db pin is None")
pass
def set_pin(account_number, acctype, input_code):
with conn:
get_code = ATM.get_user_code(account_number, acctype)
if get_code is None:
pass
print("You need to request an authorization code first before you set your pin")
else:
if get_code !=input_code:
print("Authorization code not valid")
else:
pin = input("Please set your 4 digit pin: ")
if len(pin) < 4 or len(pin) >4 or len(pin) == 4 and pin.isdigit()==False:
print("This is not a 4 digit pin")
else:
print("pin accepted")
c.execute("""UPDATE {} SET pin=:pin
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'pin':pin})
print("Pin for account has been updated")
def main_menu(name, social, account_number, balance, acctype, card_no=None):
# obj1 = bank_account.BankAccount(name, social, account_number, balance, acctype)
# obj1 = credit_card.CreditCard(name, social, account_number, balance, acctype, card_no)
user_pin = int(input("nATM Home Screen. Please enter your pin code: "))
db_pin = ATM.get_pin(account_number, acctype, user_pin)
if user_pin != db_pin and db_pin != '':
print("No pin match")
elif db_pin is '':
print("Pin has not been set")
print("First request an authorization code and use that to set the pin")
else:
user_pin == db_pin
print("nPin accepted continue n ")
print("""""""ATM Menu, choose an option""""""")
print("n1 - Deposit funds")
print("2 - Withdraw funds")
print("3 - Check balance")
print("4 - Reset Pin")
print("5 - Exit")
while True:
try:
choice = int(input("Please enter a number: "))
except ValueError:
print("This is not a number")
if choice >= 1 and choice <=5:
if choice == 1:
amount = input("nPlease enter the deposit amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.deposit( account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice == 2:
amount = input("Please enter the withdrawl amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.withdraw(account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice ==3:
obj1.get_balance(account_number, acctype)
elif choice ==4:
new_pin = input("Please enter a new 4 digit pin: ")
if new_pin != '' and new_pin.isdigit():
int(new_pin)
obj1.set_reset_pin(account_number, acctype, new_pin)
elif choice ==5:
break
else:
print("Not a valid number")
A piece of bank_account_setup:
import sqlite3
import secrets
import getpass
import smtplib, sqlite3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
""" create different accounts based on account type passed in """
def create_account(self, name, social, account_number, balance, acctype, card_no=None, credit_score=None, credit_limit=None):
self.rate = None
with conn:
# account_found = BankAccount.get_account(self, account_number, acctype)
# if not account_found:
if acctype == 'bank_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :pin)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'pin':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'savings_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :rate)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'rate':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'credit_card':
c.execute("INSERT INTO credit_card VALUES (:name, :social, :account_number, :balance, :card_no,:credit_score, :credit_limit, :pin)",
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'card_no'
:card_no, 'credit_score':credit_score, 'credit_limit':credit_limit, 'pin':'' })
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
conn.commit()
Piece of bank_account:
import sqlite3
import secrets
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
def get_balance(self, account_number, acctype):
with conn:
balance = c.execute("SELECT balance from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
balance = c.fetchone()
print("The balance for account number: {} is ${}".format(account_number, balance[0]))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_balance = notif_set[4]
name = notif_set[0]
if notif_balance == 1:
notify = send_email.send_email(account_number, acctype, 'Balance', balance, balance, name)
return(balance[0])
""" Deposit funds into the account number + acctype for the account passed in """
def deposit(self, account_number, acctype, amount):
with conn:
""" Check acct exists before making deposit """
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
existing_bal = account_found[3]
c.execute("""UPDATE {} SET balance=balance +:amount
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'amount':amount})
new_bal = existing_bal + (int(amount))
print("${} has been deposited to account {} and the new balance is ${}".format(amount, account_number, existing_bal + (int(amount))))
# Check email configurations are turned on for deposits
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_deposits = notif_set[5]
name = notif_set[0]
if notif_deposits == 1:
notify = send_email.send_email(account_number, acctype, 'Deposit', amount, new_bal, name)
Piece of credit_card:
from bank_account import BankAccount
import sqlite3
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class CreditCard(BankAccount):
def __init__(self, name, social, account_number, balance, acctype, card_no, credit_score=None, credit_limit=None):
super().__init__(name, social, account_number, balance, acctype)
self.card_no = card_no
self.credit_score = credit_score
self.credit_limit = credit_limit
""" set credit limit, check if acct exists, then call get credit limit """
def set_credit_limit(self, account_number, acctype, credit_score):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
credit_limit = CreditCard.set_credit_limit_helper(self, account_number, credit_score)
if credit_limit:
c.execute("""UPDATE credit_card SET credit_limit=:credit_limit
WHERE account_number =:account_number """,
{'account_number':account_number, 'credit_limit':credit_limit})
print("Account number {} credit limit is set to {}".format(account_number, credit_limit))
conn.commit()
def withdraw(self, account_number, acctype, amount):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
balance = account_found[3]
credit_limit = CreditCard.get_credit_limit(self, account_number)
amount_left = credit_limit - (int(balance))
if balance - (int(amount)) < credit_limit:
print("Your balance is: {}, and your credit limit is: {}".format(balance, credit_limit))
print("The max you can withdraw is {}".format(amount_left))
else:
existing_bal = account_found[3]
c.execute("""UPDATE credit_card SET balance=balance -:amount
WHERE account_number =:account_number""",
{'account_number':account_number, 'amount':amount})
print("${} has been withdrawn from account {} and the new balance is ${}".format(amount, account_number, existing_bal - (int(amount))))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications have been set for this acct")
else:
notif_withdraw = notif_set[7]
if notif_withdraw == 1:
notify = BankAccount.send_email(self,account_number, acctype, 'Withdraw', amount, existing_bal - amount)
conn.commit()
object-oriented design-patterns
New contributor
$endgroup$
add a comment |
$begingroup$
Python beginner here. Building an OOP bank account program with sqlite and starting to struggle a bit with its design. From a design standpoint I have a file (bank) which calls ATM. ATM simulates an ATM, and is the file which then calls bank_account or credit_card depending on the account data passed in from bank.
To initially setup an account I decided to put this into a different file, for example bank_account_setup or for credit_card, credit_card_setup. These would create_account, help setup pin etc so that the account is created and ready to use. Then the actual bank_account or credit_card contains other functions, like, deposit, withdraw, get_balance etc. Also send_email is in another file
My question is basically around my design, is there a way to structure this better? How about my setup files to create bank or credit card accts? Is that a good or bad idea? Also - another issue I am having is that when I run bank I pass in account type to ATM. In ATM I then had to know what class I am using in advance and instantiate that inside ATM. Could I handle that dynamically?
(Also - the code does work - just concerned with bad design)
Thanks in advance. Code samples below
Heres my calling file bank:
import atm
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
if __name__ == '__main__':
obj1 = atm.ATM.main_menu( "Frank Smith", 135063522, 5544, 850, 'credit_card', 4400110022004400)
Heres ATM, which calls the other files:
import sqlite3, smtplib
import bank_account
import secrets
import send_email
import credit_card
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class ATM:
def get_pin(account_number, acctype, user_pin):
with conn:
db_pin = c.execute("SELECT pin from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
db_pin = c.fetchone()
if db_pin is not None:
return(db_pin[0])
else:
print("db pin is None")
pass
def set_pin(account_number, acctype, input_code):
with conn:
get_code = ATM.get_user_code(account_number, acctype)
if get_code is None:
pass
print("You need to request an authorization code first before you set your pin")
else:
if get_code !=input_code:
print("Authorization code not valid")
else:
pin = input("Please set your 4 digit pin: ")
if len(pin) < 4 or len(pin) >4 or len(pin) == 4 and pin.isdigit()==False:
print("This is not a 4 digit pin")
else:
print("pin accepted")
c.execute("""UPDATE {} SET pin=:pin
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'pin':pin})
print("Pin for account has been updated")
def main_menu(name, social, account_number, balance, acctype, card_no=None):
# obj1 = bank_account.BankAccount(name, social, account_number, balance, acctype)
# obj1 = credit_card.CreditCard(name, social, account_number, balance, acctype, card_no)
user_pin = int(input("nATM Home Screen. Please enter your pin code: "))
db_pin = ATM.get_pin(account_number, acctype, user_pin)
if user_pin != db_pin and db_pin != '':
print("No pin match")
elif db_pin is '':
print("Pin has not been set")
print("First request an authorization code and use that to set the pin")
else:
user_pin == db_pin
print("nPin accepted continue n ")
print("""""""ATM Menu, choose an option""""""")
print("n1 - Deposit funds")
print("2 - Withdraw funds")
print("3 - Check balance")
print("4 - Reset Pin")
print("5 - Exit")
while True:
try:
choice = int(input("Please enter a number: "))
except ValueError:
print("This is not a number")
if choice >= 1 and choice <=5:
if choice == 1:
amount = input("nPlease enter the deposit amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.deposit( account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice == 2:
amount = input("Please enter the withdrawl amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.withdraw(account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice ==3:
obj1.get_balance(account_number, acctype)
elif choice ==4:
new_pin = input("Please enter a new 4 digit pin: ")
if new_pin != '' and new_pin.isdigit():
int(new_pin)
obj1.set_reset_pin(account_number, acctype, new_pin)
elif choice ==5:
break
else:
print("Not a valid number")
A piece of bank_account_setup:
import sqlite3
import secrets
import getpass
import smtplib, sqlite3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
""" create different accounts based on account type passed in """
def create_account(self, name, social, account_number, balance, acctype, card_no=None, credit_score=None, credit_limit=None):
self.rate = None
with conn:
# account_found = BankAccount.get_account(self, account_number, acctype)
# if not account_found:
if acctype == 'bank_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :pin)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'pin':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'savings_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :rate)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'rate':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'credit_card':
c.execute("INSERT INTO credit_card VALUES (:name, :social, :account_number, :balance, :card_no,:credit_score, :credit_limit, :pin)",
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'card_no'
:card_no, 'credit_score':credit_score, 'credit_limit':credit_limit, 'pin':'' })
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
conn.commit()
Piece of bank_account:
import sqlite3
import secrets
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
def get_balance(self, account_number, acctype):
with conn:
balance = c.execute("SELECT balance from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
balance = c.fetchone()
print("The balance for account number: {} is ${}".format(account_number, balance[0]))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_balance = notif_set[4]
name = notif_set[0]
if notif_balance == 1:
notify = send_email.send_email(account_number, acctype, 'Balance', balance, balance, name)
return(balance[0])
""" Deposit funds into the account number + acctype for the account passed in """
def deposit(self, account_number, acctype, amount):
with conn:
""" Check acct exists before making deposit """
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
existing_bal = account_found[3]
c.execute("""UPDATE {} SET balance=balance +:amount
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'amount':amount})
new_bal = existing_bal + (int(amount))
print("${} has been deposited to account {} and the new balance is ${}".format(amount, account_number, existing_bal + (int(amount))))
# Check email configurations are turned on for deposits
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_deposits = notif_set[5]
name = notif_set[0]
if notif_deposits == 1:
notify = send_email.send_email(account_number, acctype, 'Deposit', amount, new_bal, name)
Piece of credit_card:
from bank_account import BankAccount
import sqlite3
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class CreditCard(BankAccount):
def __init__(self, name, social, account_number, balance, acctype, card_no, credit_score=None, credit_limit=None):
super().__init__(name, social, account_number, balance, acctype)
self.card_no = card_no
self.credit_score = credit_score
self.credit_limit = credit_limit
""" set credit limit, check if acct exists, then call get credit limit """
def set_credit_limit(self, account_number, acctype, credit_score):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
credit_limit = CreditCard.set_credit_limit_helper(self, account_number, credit_score)
if credit_limit:
c.execute("""UPDATE credit_card SET credit_limit=:credit_limit
WHERE account_number =:account_number """,
{'account_number':account_number, 'credit_limit':credit_limit})
print("Account number {} credit limit is set to {}".format(account_number, credit_limit))
conn.commit()
def withdraw(self, account_number, acctype, amount):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
balance = account_found[3]
credit_limit = CreditCard.get_credit_limit(self, account_number)
amount_left = credit_limit - (int(balance))
if balance - (int(amount)) < credit_limit:
print("Your balance is: {}, and your credit limit is: {}".format(balance, credit_limit))
print("The max you can withdraw is {}".format(amount_left))
else:
existing_bal = account_found[3]
c.execute("""UPDATE credit_card SET balance=balance -:amount
WHERE account_number =:account_number""",
{'account_number':account_number, 'amount':amount})
print("${} has been withdrawn from account {} and the new balance is ${}".format(amount, account_number, existing_bal - (int(amount))))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications have been set for this acct")
else:
notif_withdraw = notif_set[7]
if notif_withdraw == 1:
notify = BankAccount.send_email(self,account_number, acctype, 'Withdraw', amount, existing_bal - amount)
conn.commit()
object-oriented design-patterns
New contributor
$endgroup$
Python beginner here. Building an OOP bank account program with sqlite and starting to struggle a bit with its design. From a design standpoint I have a file (bank) which calls ATM. ATM simulates an ATM, and is the file which then calls bank_account or credit_card depending on the account data passed in from bank.
To initially setup an account I decided to put this into a different file, for example bank_account_setup or for credit_card, credit_card_setup. These would create_account, help setup pin etc so that the account is created and ready to use. Then the actual bank_account or credit_card contains other functions, like, deposit, withdraw, get_balance etc. Also send_email is in another file
My question is basically around my design, is there a way to structure this better? How about my setup files to create bank or credit card accts? Is that a good or bad idea? Also - another issue I am having is that when I run bank I pass in account type to ATM. In ATM I then had to know what class I am using in advance and instantiate that inside ATM. Could I handle that dynamically?
(Also - the code does work - just concerned with bad design)
Thanks in advance. Code samples below
Heres my calling file bank:
import atm
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
if __name__ == '__main__':
obj1 = atm.ATM.main_menu( "Frank Smith", 135063522, 5544, 850, 'credit_card', 4400110022004400)
Heres ATM, which calls the other files:
import sqlite3, smtplib
import bank_account
import secrets
import send_email
import credit_card
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class ATM:
def get_pin(account_number, acctype, user_pin):
with conn:
db_pin = c.execute("SELECT pin from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
db_pin = c.fetchone()
if db_pin is not None:
return(db_pin[0])
else:
print("db pin is None")
pass
def set_pin(account_number, acctype, input_code):
with conn:
get_code = ATM.get_user_code(account_number, acctype)
if get_code is None:
pass
print("You need to request an authorization code first before you set your pin")
else:
if get_code !=input_code:
print("Authorization code not valid")
else:
pin = input("Please set your 4 digit pin: ")
if len(pin) < 4 or len(pin) >4 or len(pin) == 4 and pin.isdigit()==False:
print("This is not a 4 digit pin")
else:
print("pin accepted")
c.execute("""UPDATE {} SET pin=:pin
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'pin':pin})
print("Pin for account has been updated")
def main_menu(name, social, account_number, balance, acctype, card_no=None):
# obj1 = bank_account.BankAccount(name, social, account_number, balance, acctype)
# obj1 = credit_card.CreditCard(name, social, account_number, balance, acctype, card_no)
user_pin = int(input("nATM Home Screen. Please enter your pin code: "))
db_pin = ATM.get_pin(account_number, acctype, user_pin)
if user_pin != db_pin and db_pin != '':
print("No pin match")
elif db_pin is '':
print("Pin has not been set")
print("First request an authorization code and use that to set the pin")
else:
user_pin == db_pin
print("nPin accepted continue n ")
print("""""""ATM Menu, choose an option""""""")
print("n1 - Deposit funds")
print("2 - Withdraw funds")
print("3 - Check balance")
print("4 - Reset Pin")
print("5 - Exit")
while True:
try:
choice = int(input("Please enter a number: "))
except ValueError:
print("This is not a number")
if choice >= 1 and choice <=5:
if choice == 1:
amount = input("nPlease enter the deposit amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.deposit( account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice == 2:
amount = input("Please enter the withdrawl amount: ")
if amount != '' and amount.isdigit():
int(amount)
obj1.withdraw(account_number, acctype, amount)
else:
print("Please enter a valid number")
elif choice ==3:
obj1.get_balance(account_number, acctype)
elif choice ==4:
new_pin = input("Please enter a new 4 digit pin: ")
if new_pin != '' and new_pin.isdigit():
int(new_pin)
obj1.set_reset_pin(account_number, acctype, new_pin)
elif choice ==5:
break
else:
print("Not a valid number")
A piece of bank_account_setup:
import sqlite3
import secrets
import getpass
import smtplib, sqlite3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
""" create different accounts based on account type passed in """
def create_account(self, name, social, account_number, balance, acctype, card_no=None, credit_score=None, credit_limit=None):
self.rate = None
with conn:
# account_found = BankAccount.get_account(self, account_number, acctype)
# if not account_found:
if acctype == 'bank_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :pin)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'pin':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'savings_account':
c.execute("INSERT INTO {} VALUES (:name, :social, :account_number, :balance, :rate)".format(acctype),
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'rate':''})
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
elif acctype == 'credit_card':
c.execute("INSERT INTO credit_card VALUES (:name, :social, :account_number, :balance, :card_no,:credit_score, :credit_limit, :pin)",
{'name':name, 'social': social,'account_number': account_number, 'balance':balance, 'card_no'
:card_no, 'credit_score':credit_score, 'credit_limit':credit_limit, 'pin':'' })
print("New account: {} has been created, acc # is: {}".format(acctype, account_number))
conn.commit()
Piece of bank_account:
import sqlite3
import secrets
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import send_email
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class BankAccount:
def __init__(self, name, social, account_number, balance, acctype):
self.name = name
self.social = social
self.account_number = account_number
self.balance = balance
self.acctype = acctype
def get_balance(self, account_number, acctype):
with conn:
balance = c.execute("SELECT balance from {} WHERE account_number=:account_number".format(acctype),
{'account_number':account_number})
balance = c.fetchone()
print("The balance for account number: {} is ${}".format(account_number, balance[0]))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_balance = notif_set[4]
name = notif_set[0]
if notif_balance == 1:
notify = send_email.send_email(account_number, acctype, 'Balance', balance, balance, name)
return(balance[0])
""" Deposit funds into the account number + acctype for the account passed in """
def deposit(self, account_number, acctype, amount):
with conn:
""" Check acct exists before making deposit """
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
existing_bal = account_found[3]
c.execute("""UPDATE {} SET balance=balance +:amount
WHERE account_number =:account_number""".format(acctype),
{'account_number':account_number, 'amount':amount})
new_bal = existing_bal + (int(amount))
print("${} has been deposited to account {} and the new balance is ${}".format(amount, account_number, existing_bal + (int(amount))))
# Check email configurations are turned on for deposits
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications are set for this user")
else:
notif_deposits = notif_set[5]
name = notif_set[0]
if notif_deposits == 1:
notify = send_email.send_email(account_number, acctype, 'Deposit', amount, new_bal, name)
Piece of credit_card:
from bank_account import BankAccount
import sqlite3
conn = sqlite3.connect('bank_account.db')
c = conn.cursor()
class CreditCard(BankAccount):
def __init__(self, name, social, account_number, balance, acctype, card_no, credit_score=None, credit_limit=None):
super().__init__(name, social, account_number, balance, acctype)
self.card_no = card_no
self.credit_score = credit_score
self.credit_limit = credit_limit
""" set credit limit, check if acct exists, then call get credit limit """
def set_credit_limit(self, account_number, acctype, credit_score):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
credit_limit = CreditCard.set_credit_limit_helper(self, account_number, credit_score)
if credit_limit:
c.execute("""UPDATE credit_card SET credit_limit=:credit_limit
WHERE account_number =:account_number """,
{'account_number':account_number, 'credit_limit':credit_limit})
print("Account number {} credit limit is set to {}".format(account_number, credit_limit))
conn.commit()
def withdraw(self, account_number, acctype, amount):
with conn:
account_found = BankAccount.get_account(self, account_number, acctype)
if account_found:
balance = account_found[3]
credit_limit = CreditCard.get_credit_limit(self, account_number)
amount_left = credit_limit - (int(balance))
if balance - (int(amount)) < credit_limit:
print("Your balance is: {}, and your credit limit is: {}".format(balance, credit_limit))
print("The max you can withdraw is {}".format(amount_left))
else:
existing_bal = account_found[3]
c.execute("""UPDATE credit_card SET balance=balance -:amount
WHERE account_number =:account_number""",
{'account_number':account_number, 'amount':amount})
print("${} has been withdrawn from account {} and the new balance is ${}".format(amount, account_number, existing_bal - (int(amount))))
notif_set = BankAccount.get_notif(self, account_number, acctype)
if notif_set is None:
print("No notifications have been set for this acct")
else:
notif_withdraw = notif_set[7]
if notif_withdraw == 1:
notify = BankAccount.send_email(self,account_number, acctype, 'Withdraw', amount, existing_bal - amount)
conn.commit()
object-oriented design-patterns
object-oriented design-patterns
New contributor
New contributor
New contributor
asked 12 mins ago
anfieldanfield
1
1
New contributor
New contributor
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
anfield is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214886%2fneed-help-on-design-patterns-for-my-oop-bank-account-program-in-python-3%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
anfield is a new contributor. Be nice, and check out our Code of Conduct.
anfield is a new contributor. Be nice, and check out our Code of Conduct.
anfield is a new contributor. Be nice, and check out our Code of Conduct.
anfield is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214886%2fneed-help-on-design-patterns-for-my-oop-bank-account-program-in-python-3%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown