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 accounts? 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).


DB Schema (this is mostly correct but some fields may have been added by hand to sqlite):

	c.execute("""CREATE TABLE IF NOT EXISTS bank_account  (

			name text,
			social integer,
			account_number integer PRIMARY KEY,
			balance integer,
			pin integer
			)""")

	c.execute("""CREATE TABLE IF NOT EXISTS credit_card (

			name text,
			social integer,
			account_number integer PRIMARY KEY,
			balance integer,
			card_no integer,
			credit_score integer,
			credit_limit integer
			)""")

	c.execute("""CREATE TABLE IF NOT EXISTS savings_account (

			name text,
			social integer,
			account_number integer PRIMARY KEY,
			balance integer,
			rate real
			)""")

	c.execute("""CREATE TABLE IF NOT EXISTS notifications (

			name text,
			email_address,
			account_number integer PRIMARY KEY,
			account_type,
			notif_bal,
			notif_deposits,
			notif_overdraft
			)""")

	c.execute("""CREATE TABLE IF NOT EXISTS auth_code (

			account_number integer PRIMARY KEY,
			account_type,
			email,
			auth_code
			)""")

Here's 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)

Here's 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")

ALL 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()

		""" Show all rows in DB for the the account type passed in """
		def get_account(self,account_number, acctype):
			with conn:
				account_find = c.execute("SELECT * from {} WHERE account_number=:account_number".format(acctype),
										 {'account_number':account_number})
				account_found = c.fetchone()
				if not account_found:
					print("No {} matching that number could be found".format(acctype))
				else:
					print("Account type: {} exists!".format(acctype))
					print(account_found)
			return(account_found)    

		""" Generate a random string for card activation """
		def set_user_code(self, account_number, acctype, email):
			with conn:
			#  account_found = BankAccount.get_account(self, account_number, acctype)
				account_found = BankAccount.get_user_code(self, account_number, acctype)
				if not account_found:
					auth_code = secrets.token_hex(4)
					print("User code {} generated".format(auth_code))
					c.execute("INSERT INTO auth_code VALUES (:account_number, :acctype, :email, :auth_code)",
								   {'account_number': account_number, 'acctype': acctype, 'email':email, 'auth_code':auth_code})
					print("DB updated with auth code for account")

					subject = 'Authorization code'
					body = 'Authorization code: {}\n \
					Use the authorization code when setting your pin for the first time'.format(auth_code)
					email_user = '[email protected]'
					email_send = '[email protected]'
					email_pass = 'Liverpool27'
					  
					msg = MIMEMultipart()
					msg['From'] = email_user
					msg['To'] = email_send
					msg['Subject'] = subject

					msg.attach(MIMEText(body, 'plain'))
					server = smtplib.SMTP('smtp.gmail.com: 587')
					server.starttls()
					server.login(email_user, email_pass)
					text = msg.as_string()
					server.sendmail(email_user, email_send, text)
					server.quit               
				else:
					print("Auth code {} is already set for this account {} ".format(account_found[2], account_number))
			conn.commit()
	   
					
		def get_user_code(self,account_number, acctype):
			with conn:
				account_found = c.execute("SELECT auth_code from auth_code WHERE account_number=:account_number",
				{'account_number':account_number})
				account_found = c.fetchone()
			if account_found is None:
				pass
				#   print("You need to request an authorization code first before you set your pin")
			else:    
				return(account_found[0])

		""" Set pin for an account based on the auth code entered for validation """
		def set_pin(self,account_number, acctype, input_code):
			with conn:
				get_code = BankAccount.get_user_code(self, 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")

	  
		
	if __name__ == '__main__':
		obj1 = BankAccount("Alexis Sanchez", 135063522, 5534, 100, 'bank_account')
	#    obj1.create_account("Alexis Sanchez", 135063522, 5534, 100, 'bank_account')
	#    obj1.set_user_code(5534, 'bank_account', '[email protected]')
		obj1.set_pin(5534, 'bank_account', '1f7bd3f9')

ALL of bank_account:

	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':
					print("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()

		""" Generate a random string for card activation """
		def set_user_code(self, account_number, acctype, email):
			with conn:
			#  account_found = BankAccount.get_account(self, account_number, acctype)
				account_found = BankAccount.get_user_code(self, account_number, acctype)
				if not account_found:
					auth_code = secrets.token_hex(4)
					print("User code {} generated".format(auth_code))
					c.execute("INSERT INTO auth_code VALUES (:account_number, :acctype, :email, :auth_code)",
								   {'account_number': account_number, 'acctype': acctype, 'email':email, 'auth_code':auth_code})
					print("DB updated with auth code for account")

					subject = 'Authorization code'
					body = 'Authorization code: {}\n \
					Use the authorization code when setting your pin for the first time'.format(auth_code)
					email_user = '[email protected]'
					email_send = '[email protected]'
					email_pass = 'Liverpool27'
					  
					msg = MIMEMultipart()
					msg['From'] = email_user
					msg['To'] = email_send
					msg['Subject'] = subject

					msg.attach(MIMEText(body, 'plain'))
					server = smtplib.SMTP('smtp.gmail.com: 587')
					server.starttls()
					server.login(email_user, email_pass)
					text = msg.as_string()
					server.sendmail(email_user, email_send, text)
					server.quit               
				else:
					print("Auth code {} is already set for this account {} ".format(account_found[2], account_number))
			conn.commit()
	   
					
		def get_user_code(self,account_number, acctype):
			with conn:
				account_found = c.execute("SELECT auth_code from auth_code WHERE account_number=:account_number",
				{'account_number':account_number})
				account_found = c.fetchone()
			if account_found is None:
				pass
			# print("You need to request an authorization code first before you set your pin")
			else:    
				return(account_found[0])

		""" Set pin for an account based on the auth code entered for validation """
		def set_pin(self,account_number, acctype, input_code):
			with conn:
				get_code = BankAccount.get_user_code(self, 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")

		""" Reset pin, pass in new pin """
		def set_reset_pin(self, account_number, acctype, new_pin):
			with conn:
				c.execute("""UPDATE {} SET pin=:new_pin
									WHERE account_number =:account_number""".format(acctype),
									  {'account_number':account_number, 'new_pin':new_pin})
				print("Pin for account has been updated")
				conn.commit()            
							
					  
		def get_pin(self, 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

					   
		""" Set email notification preferences for users who have confirmed bank accounts """
		""" Do an insert if no notifications record is found """
		""" If there is a notifications record, update all notifications for that user """
		def set_notifications(self, name, email_address, account_number, acctype, notif_bal, notif_deposits, notif_overdraft, notif_withdraw):
			with conn:
				""" check if an account is found first """
				account_found = BankAccount.get_account(self, account_number, acctype)

				""" Check if a notification record is found """
				notif_found = BankAccount.get_notif(self, account_number, acctype)

							
				if account_found and notif_found is None:
					c.execute("""INSERT INTO notifications VALUES (:name, :email_address, :account_number, :acctype, :notif_bal, :notif_deposits, :notif_overdraft, :notif_withdraw)""".format(acctype),
									  {'name':name, 'email_address': email_address,'account_number': account_number, 'acctype':acctype, 'notif_bal':notif_bal,
									   'notif_deposits':notif_deposits, 'notif_overdraft':notif_overdraft, 'notif_withdraw':notif_withdraw})  
					print("Notifications for acc#{} has been created, acctype {} have been setup".format(account_number, acctype))

				
				elif account_found and notif_found:
					c.execute("""UPDATE notifications SET notif_bal=:notif_bal, notif_deposits=:notif_deposits, notif_overdraft=:notif_overdraft, notif_withdraw=:notif_withdraw""",
							  {'notif_bal':notif_bal, 'notif_deposits':notif_deposits, 'notif_overdraft':notif_overdraft, 'notif_withdraw': notif_withdraw})
					print("Notificatons for acc# {} have been updated".format(account_number))
				else:
					print("Setup an account first then set notifications")
					
		def get_notif(self,account_number, acctype):
			with conn:
				notif_exist = c.execute("""SELECT * from notifications WHERE account_number=:account_number and
										  account_type=:account_type""",
											 {'account_number':account_number, 'account_type':acctype})
				notif_exist = c.fetchone()
			return(notif_exist)
		   
											
		""" Show all rows in DB for the the account type passed in """
		def get_account(self,account_number, acctype):
			with conn:
				account_find = c.execute("SELECT * from {} WHERE account_number=:account_number".format(acctype),
										 {'account_number':account_number})
				account_found = c.fetchone()
				if not account_found:
					print("No {} matching that number could be found".format(acctype))
				else:
					print("Account type: {} exists!".format(acctype))
					print(account_found)
			return(account_found)

		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)
								 
		""" withdraw funds from the bank account passed in """       
		def withdraw(self, account_number, acctype, amount):
			with conn:
				""" Check account exists """
				account_found = BankAccount.get_account(self, account_number, acctype)
				existing_bal = account_found[3]

				if account_found:  
					c.execute("""UPDATE bank_account SET balance=balance -:amount
							WHERE account_number =:account_number""",
							  {'account_number':account_number, 'amount':amount})
					new_bal = existing_bal - (int(amount))
					conn.commit() 
					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]
						name = notif_set[0]
						if notif_withdraw == 1:
							notify = send_email.send_email(account_number, acctype, 'Withdraw', amount, new_bal, name)
				else:
					print("Withdrawl notifications have been turned off")
				if account_found and new_bal < 0 and notif_set is not None:
					notify_o = send_email.send_email(account_number, acctype, 'Overdraft', amount, new_bal, name)    
				conn.commit()

ALL of credit card setup:

	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 get_credit_limit(self, account_number):
        with conn:
            c.execute("""SELECT credit_limit from credit_card WHERE account_number=:account_number""",
                      {'account_number':account_number})
            credit_limit = c.fetchone()
            if credit_limit is None:
                pass
            else:
                return(credit_limit[0])
            
    """ get credit limit based on credit score passed in """
    def set_credit_limit_helper(self, account_number, credit_score):

        if credit_score > 700:
            credit_limit = -2000

        elif credit_score > 100 and credit_score <= 300:
            credit_limit = -1500
            
        else:
            credit_limit = -1000
        return credit_limit

    if __name__ == '__main__':
                           
        obj1 =  CreditCard("Juan Santos", 135063555, 5544, 100, 'credit_card', 2200330066007700)
    #    obj1.create_account("Juan Santos", 135063555, 9922, 100, 'credit_card', 2200330066007700)
        obj1.set_credit_limit(5544, 'credit_card', 200)
    #    obj1.set_user_code(9922, 'credit_card', '[email protected]')
    #    obj1.set_pin(9922, 'credit_card', 'b4493a59')
			
ALL 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()
    
        def get_credit_limit(self, account_number):
            with conn:
                c.execute("""SELECT credit_limit from credit_card WHERE account_number=:account_number""",
                          {'account_number':account_number})
                credit_limit = c.fetchone()
                if credit_limit is None:
                    pass
                else:
                    return(credit_limit[0])
                
        """ get credit limit based on credit score passed in """
        def set_credit_limit_helper(self, account_number, credit_score):
    
            if credit_score > 700:
                credit_limit = -2000
    
            elif credit_score > 100 and credit_score <= 300:
                credit_limit = -1500
                
            else:
                credit_limit = -1000
            return credit_limit

Adding send email program also:

	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 bank_account

	conn = sqlite3.connect('bank_account.db')
	c = conn.cursor()

	""" get email config - check if there is an existing acct first """
	def get_email_config(account_number, acctype, action, amount, new_bal, name):
			
		subject = '{} account {} notification'.format(acctype, action)
		body = ''
		acctype = acctype.replace('_',' ')

		if action == 'Balance':
			body = '{},\n \
			The balance for account number: {} is : ${} '.format(name, account_number, amount[0])

		elif action == 'Deposit':
			body= '{},\n \
			A deposit of: ${} has been made to account number: {}\n \
			The new balance is now: ${}'.format(name, amount, account_number, new_bal)
			
		elif action == 'Overdraft':
			body = '{},\n \
			Please note that account number: {} is now overdrawn \n \
			The balance is ${}. Please add funds to avoid penalties'.format(name, account_number, new_bal)

		elif action == 'Withdraw':
			body = '{},\n \
			Please note that a withdrawl in the amount of: ${} has been made from account number: {} \n \
			The balance is ${}'.format(name, amount, account_number, new_bal)
		return(subject, body)

	def send_email( account_number, acctype, action, amount, new_bal, name):

		""" Pull subject and body from email_config """
		email_config = get_email_config(account_number, acctype, action, amount, new_bal, name)
		
		body = email_config[1]
		subject = email_config[0]
		email_user = '[email protected]'
		email_send = '[email protected]'
		email_pass = 'pass'
		msg = MIMEMultipart()
		msg['From'] = email_config[0]
		msg['To'] = email_config[1]
		msg['Subject'] = email_config[-2]

		msg.attach(MIMEText(body, 'plain'))
		server = smtplib.SMTP('smtp.gmail.com: 587')
		server.starttls()
		server.login(email_user, email_pass)
		text = msg.as_string()
		server.sendmail(email_user, email_send, text)
		server.quit

			
		if action == 'Deposit':                            
			print("Deposit Notification sent")

		elif action == 'Balance':
			print("Balance Notification sent")

		elif action == 'Overdraft':
			print("Overdraft Notification sent")
				
		elif action == 'Withdraw':
			print("Withdraw Notification sent")     
				
		else:
				pass