Python: ATM
From Mike Beane's Blog
I'm auditing part 1 of a Programming class in Python as I have to take part 2 next semester (I have an old transfer credit that covered Programming 1, alas the last time I did programming in school for school, it was in C and C++). I don't think I've ever done anything from start to finish in Python outside of print ("Hello world!"), though I've looked at the code of others a lot. My PERL programming comes in handy with this, but I'm still new at it.
It's a seven week course and one of the semester projects is to build an ATM prototype. I was out week one and I picked up the course notes a week ago (week 2). Tomorrow starts week 3.
To get through the project I had to figure out
- How Python works with lists
- This wasn't called for in the project, but it made things so much easier for the account setup.
- console output
- Why all the () stuff?
- if, elsif, else
- elif???
- casting types
- int\float, etc - I still have some basic trouble with this, mostly around remembering what I was hoping to do
- format output in columns
- not called for, I just don't like ugly columns
- functions
- I actually like Python's handling of functions, though I didn't look into passing information in an out, nor did I look into local vs global variables.
- Loops
- Made sense!
Here's my first iteration of the semester project, four days after I started it in IDLE:
################################################################################# ## /---------------------------------------------------------------------------\* ## | Program: ATM ## | Version: 0.0.1 ## | Language: 3.7.4 ## | ## | Description: ATM Project Iteration #1 ## | ## | Course: IT 261-1 ## | Author: Mike Beane ## \---------------------------------------------------------------------------/* ## Changelog ## Date Description ## ----- ------------- ## 9/11/2019 Program Setup - Created Lists ## Basic account input created and sanity test ## 9/12/2019 Added PIN check (simple) ## 9/13/2019 Added WHILE LOOP screen clear: cls() ## 9/14/2019 Added Account # loop and testing to see if the ## value is in the list or not or input is ## valid by length. ## Added help() to list account variables (this ## is more for you than for me, it would NOT ## exist in a real program. Instead there ## would be Post-IT notes for this information. ## Updated PIN check (advanced and now with fail!) ## Created functions for repetitive things ## Added Deposit (simple) - needs sanity checks ## 9/15/2019 Updated Deposit checks ## Added Withdrawal routine and checks ################################################################################# # Variables debug = 1 PIN_Max_Attempts=3 ################################################################################# ## System Variables - Do Not Edit Below This Line ############################### ################################################################################# ## Function - Clear Screen cludge def cls(): i = 0 while i < 39: # Default window size seems to be 40 lines print (" ") # Avoiding making sys() calls and just i += 1 # Carriage returning the screen clear ## Function - Output Account Lists if "?" is used in the Account input section def help(): cls() print ("--------------------------------------------------------") print ("|***************** Help: Account Info *****************|") print ("--------------------------------------------------------") print ("Account Pin Name ") print ("--------------------------------------------------------") i=0 while i < len(accounts): print (""+accounts[i]+" "+pins[i]+" "+users[i]) i += 1 print (" ") print (" ") print ("** Realistically this wouldn't be here **") print ("--------------------------------------------------------") def header(): cls() print ("--------------------------------------------------------") print (" Name Account ") print ("--------------------------------------------------------") print (" "+users[account_position]+" "+User_Account) print ("--------------------------------------------------------") def main_menu(): print ("--------------------------------------------------------") print ("Options: ") print (" 1. Fund Balance Inquiry") print (" 2. Deposit") print (" 3. Withdraw ") print (" 4. Quit") print ("--------------------------------------------------------") def balance_display(): print ("--------------------------------------------------------") print ("Balance: ") print (" Checking: $"+ str(BALANCE_Checking)) print (" Savings [1]: $"+ str(BALANCE_Savings_1)) print (" Savings [2]: $"+ str(BALANCE_Savings_2)) print ("--------------------------------------------------------") def ledger(): table_data = [ # https://docs.python.org/2.7/library/string.html#format-specification-mini-language # https://stackoverflow.com/questions/9989334/create-nice-column-output-in-python [' ', 'STARTING','TOTAL','TOTAL','ENDING'], ['TYPE', 'BALANCE','DEPOSITS','WITHDRAWLS','BALANCE'], ['----------','----------','----------','----------','----------'], ['Checking', str(STARTING_BALANCE_CHECKING), DEPOSIT_TALLY_CHECKING, WITHDRAWAL_TALLY_CHECKING, BALANCE_Checking], ['Savings[1]', str(STARTING_BALANCE_Savings_1), DEPOSIT_TALLY_SAVINGS_1, WITHDRAWAL_TALLY_SAVINGS_1, BALANCE_Savings_1], ['Savings[2]', str(STARTING_BALANCE_Savings_2), DEPOSIT_TALLY_SAVINGS_2, WITHDRAWAL_TALLY_SAVINGS_2, BALANCE_Savings_2], ['----------','----------','----------','----------','----------'], ['TOTALS','',DEPOSIT_TALLY_CHECKING+DEPOSIT_TALLY_SAVINGS_1+DEPOSIT_TALLY_SAVINGS_2,WITHDRAWAL_TALLY_CHECKING+WITHDRAWAL_TALLY_SAVINGS_1+WITHDRAWAL_TALLY_SAVINGS_2,'',] ] for row in table_data: print("{: >10} {: >10} {: >10} {: >10} {: >10}".format(*row)) def startup(): cls() print ("--------------------------------------------------------") print ("--------------------------------------------------------") print ("-------A.T.M.-------------------------------------------") print ("---------NOTE: All Input Via Numeric Keypad-------------") print ("--------------------------------------------------------") print ("|************| |************|") print ("|************| [ 7 ] [ 8 ] [ 9 ] |************|") print ("|************| |************|") print ("|************| [ 4 ] [ 5 ] [ 6 ] |************|") print ("|************| |************|") print ("|************| [ 1 ] [ 2 ] [ 3 ] |************|") print ("|************| |************|") print ("|************| [ 0 ] [ . ] [ ENTER ] |************|") print ("|************| |************|") print ("--------------------------------------------------------") ################################################################################# ## List Setup - User Accounts,Pins,Names ## Usage: ## List position dictates linkage between UA->Pin->Name ## Example: Entering 7654321 will match at position 3 below ## and will correspond with PIN 4567 and USER Hank Simpson ################################################################################# ## Ref: https://www.w3schools.com/python/python_arrays.asp #### Python doesn't do Arrays #### It does Lists. Let's do Lists ################################################################################# accounts = ["1234567","8675309","6666666","7654321","5551212"] pins = ["1234","2345","3456","4567","5678"] users = ["Brock Shumway","Gale Winds","Gustavo Adolpho","Hank Simpsons","Hector Lizondo"] total_accounts = len(accounts) total_pins = len(pins) total_users = len(users) STARTING_BALANCE_CHECKING = 500 STARTING_BALANCE_Savings_1 = 1500 STARTING_BALANCE_Savings_2 = 5000 BALANCE_Checking = STARTING_BALANCE_CHECKING BALANCE_Savings_1 = STARTING_BALANCE_Savings_1 BALANCE_Savings_2 = STARTING_BALANCE_Savings_2 DEPOSIT_TALLY_CHECKING = 0 DEPOSIT_TALLY_SAVINGS_1 = 0 DEPOSIT_TALLY_SAVINGS_2 = 0 WITHDRAWAL_TALLY_CHECKING = 0 WITHDRAWAL_TALLY_SAVINGS_1 = 0 WITHDRAWAL_TALLY_SAVINGS_2 = 0 DEPOSIT_AMOUNT = 0 ################################################################################# ## User Input: Account #### http://introtopython.org/while_input.html ################################################################################# cls() #print ("#####") startup() While_Account_Input=0 while While_Account_Input == 0: User_Account = input("Please enter your seven digit Account Number or 0 to exit: ") # https://snakify.org/en/lessons/if_then_else_conditions/ if User_Account == '0': print ("You entered 0, exiting program.") quit() elif len(User_Account) < 7: if User_Account == "?": help() else: print ("The entered string was too short: " + str(len(User_Account))) elif len(User_Account) > 7: print ("The entered string was too long: " + str(len(User_Account))) else: print ("The entered string was correct: " + str(len(User_Account))) ######################################################### ### Length was correct, but is it a valid account? ### Check 'accounts' list to see if typed in value exists ### We really don't care if the user put in alpha ### characters, it will fail the lookup. ######################################################### if User_Account not in accounts: print ("Account not found") else: While_Account_Input=1 ##################################################### ## We have some valid input -> Find the position ##################################################### account_position = accounts.index(User_Account) #################################################### ## debug to dump out known elements to screen #################################################### if debug == 1: print ("Debugging Enabled") print ("Total Accounts: " + str(total_accounts)) print ("Total Pins: " + str(total_pins)) print ("Total Users: " + str(total_users)) print ("Entered Account: " +User_Account) print ("Account Position: " + str(account_position)) print ("Pin at Pos " + str(account_position) + ": " + pins[account_position]) print ("User at Pos " + str(account_position) + ": " + users[account_position]) cls() #################################################### # PIN Check #################################################### While_PIN_Input=0 PIN_Input_Fail=0 while While_PIN_Input==0: print ("Account: " +User_Account) User_PIN = input("Please enter your four digit PIN Number or 0 to exit: ") # https://snakify.org/en/lessons/if_then_else_conditions/ if User_PIN == '0': print ("You entered 0, exiting program.") quit() elif len(User_PIN) < 4: if User_PIN == "?": help() else: print ("The entered string was too short: " + str(len(User_PIN))) elif len(User_PIN) > 4: print ("The entered string was too long: " + str(len(User_PIN))) else: print ("The entered string was correct: " + str(len(User_PIN))) ######################################################### ### Length was correct, but is it a valid match for ? ### Check 'accounts' list to see if typed in value exists ### We really don't care if the user put in alpha ### characters, it will fail the lookup. ######################################################### if User_PIN == pins[account_position]: While_PIN_Input=1 else: PIN_Input_Fail=PIN_Input_Fail+1 if PIN_Input_Fail == PIN_Max_Attempts: cls() print ("*****************************************************************") print ("You have failed to enter a correct PIN. Please contact the bank.") print ("*****************************************************************") EXIT = input("Press ENTER to exit") quit() else: print ("Incorrect PIN. Attempt "+str(PIN_Input_Fail)+" of "+str(PIN_Max_Attempts)) ############################################################ ## If you are here, you are logged in ############################################################ ############################################################ # Two level while ## Level 1: main_menu area #### Level 2: each individual option ############################################################ WHILE_MAIN_MENU = 0 while WHILE_MAIN_MENU == 0: cls() header() main_menu() main_menu_input = input ("Enter your choice: ") print (main_menu_input) if main_menu_input == '4': print ("Selected Exit...") WHILE_MAIN_MENU = 1 elif main_menu_input == '1': print ("Selected Balance Inquiry...") cls() header() balance_display() EXIT = input("Press ENTER to return to Main Menu... ") elif main_menu_input == '?': print ("Selected Ledger Inquiry...") cls() header() ledger() EXIT = input("Press ENTER to return to Main Menu... ") elif main_menu_input == '2': ################################### DEPOSITS START ##################################### print ("Selected Deposits...") WHILE_DEPOSITS_MENU = 0 while WHILE_DEPOSITS_MENU == 0: cls() header() ########################### How much to deposit? print ("How much would you like to deposit?") DEPOSIT_AMOUNT = input ("[0 to return, max deposit is $1000]: ") if DEPOSIT_AMOUNT == '0': print ("!") WHILE_DEPOSITS_MENU=1 elif float(DEPOSIT_AMOUNT) > 1000: BAD_ENTRY = input ("Max entry is $1000. Press ENTER to continue") print ("!22") WHILE_DEPOSITS_MENU=1 else: ################################################ ## **** !!!!!!!! NEED TO ADD A TALLY SYSTEM FOR DEPOSITS ## DONE !!!!!!!! NEED TO ADD A 0 <> 1000 CHECK ################################################ print (" 1. Checking") print (" 2. Savings [1]") print (" 3. Savings [2]") print (" 4. Return to Menu [2]") ################################################ DEPOSIT_SELECTION = input ("Which acount would you like to make a deposit into? ") if DEPOSIT_SELECTION == '4': WHILE_DEPOSITS_MENU = 1 elif DEPOSIT_SELECTION == '1': BALANCE_Checking=float(DEPOSIT_AMOUNT) + float(BALANCE_Checking) DEPOSIT_TALLY_CHECKING = float(DEPOSIT_TALLY_CHECKING) + float(DEPOSIT_AMOUNT) DEPOSIT_AMOUNT = 0 WHILE_DEPOSITS_MENU = 1 elif DEPOSIT_SELECTION == '2': BALANCE_Savings_1=float(DEPOSIT_AMOUNT) + float(BALANCE_Savings_1) DEPOSIT_TALLY_SAVINGS_1 = float(DEPOSIT_TALLY_SAVINGS_1) + float(DEPOSIT_AMOUNT) DEPOSIT_AMOUNT = 0 WHILE_DEPOSITS_MENU = 1 elif DEPOSIT_SELECTION == '3': BALANCE_Savings_2=float(DEPOSIT_AMOUNT) + float(BALANCE_Savings_2) DEPOSIT_TALLY_SAVINGS_2 = float(DEPOSIT_TALLY_SAVINGS_2) + float(DEPOSIT_AMOUNT) DEPOSIT_AMOUNT = 0 WHILE_DEPOSITS_MENU = 1 ################################### DEPOSITS END ##################################### elif main_menu_input == '3': ################################### WITHDRAWALS START ##################################### print ("Selected Deposits...") WHILE_WITHDRAWALS_MENU = 0 while WHILE_WITHDRAWALS_MENU == 0: cls() header() ########################### How much to withdraw? ############################### # Withdraw amounts can only be $20, $40, $60, $80, or $100. # Cannot withdraw more money than what exists in the account. # Total withdraws from a single account cannot exceed $300. # Total withdraws from ALL accounts cannot exceed $750. ################################################################################# WITHDRAWAL_AMOUNT = 0 #Reset ################################################################################## ######### Total withdraws from ALL accounts cannot exceed $750. ######### Let's just check it as it comes into the menu, if you don't have the $, ######### don't waste time going through the tree ################################################################################## if WITHDRAWAL_TALLY_CHECKING+WITHDRAWAL_TALLY_SAVINGS_1+WITHDRAWAL_TALLY_SAVINGS_2+20 > 750: print ("Any more transactions will exceed your daily withdrawal limit.") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 else: print ("------------------------------------") print (" 1. $20 4. $80") print (" 2. $40 5. $100") print (" 3. $60 0. Return to Menu") print ("------------------------------------") WITHDRAWAL_AMOUNT_SELECTION = input ("How much would you like to withdraw? ") if WITHDRAWAL_AMOUNT_SELECTION == '0': print ("!") WHILE_WITHDRAWALS_MENU=1 elif WITHDRAWAL_AMOUNT_SELECTION == '1': WITHDRAWAL_AMOUNT = 20 elif WITHDRAWAL_AMOUNT_SELECTION == '2': WITHDRAWAL_AMOUNT = 40 elif WITHDRAWAL_AMOUNT_SELECTION == '3': WITHDRAWAL_AMOUNT = 60 elif WITHDRAWAL_AMOUNT_SELECTION == '4': WITHDRAWAL_AMOUNT = 80 elif WITHDRAWAL_AMOUNT_SELECTION == '5': WITHDRAWAL_AMOUNT = 100 else: WHILE_WITHDRAWALS_MENU=1 if WHILE_WITHDRAWALS_MENU == 0: ######### Total withdraws from ALL accounts cannot exceed $750. if WITHDRAWAL_TALLY_CHECKING+WITHDRAWAL_TALLY_SAVINGS_1+WITHDRAWAL_TALLY_SAVINGS_2+WITHDRAWAL_AMOUNT > 750: print ("This transaction will exceed your daily withdrawal limit.") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 if WHILE_WITHDRAWALS_MENU == 0: if debug == 1: ledger() ##### WHICH ACCOUNT? ###### print ("------------------------------------") print (" 1: CHECKING ") print (" 2: SAVINGS[1]") print (" 3: SAVINGS[2]") print (" ") print (" 0: Return to Menu") print ("------------------------------------") WITHDRAWAL_SELECTION = input ("Which account would you like to make a withdrawal from? ") if WITHDRAWAL_SELECTION == '0': print ("!") WHILE_WITHDRAWALS_MENU=1 # Cannot withdraw more money than what exists in the account. # Total withdraws from a single account cannot exceed $300. elif WITHDRAWAL_SELECTION == '1': print ("CHECKING") if WITHDRAWAL_AMOUNT + WITHDRAWAL_TALLY_CHECKING > 300: print ("You have exceeded your daily individual account withdrawal limit.") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 elif BALANCE_Checking - WITHDRAWAL_AMOUNT < 0: print ("Insufficient funds..") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 else: WITHDRAWAL_TALLY_CHECKING = WITHDRAWAL_TALLY_CHECKING+WITHDRAWAL_AMOUNT BALANCE_Checking = BALANCE_Checking-WITHDRAWAL_AMOUNT elif WITHDRAWAL_SELECTION == '2': print ("SAVINGS[1]") if WITHDRAWAL_AMOUNT + WITHDRAWAL_TALLY_SAVINGS_1 > 300: print ("You have exceeded your daily individual account withdrawal limit.") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 elif BALANCE_Savings_1 - WITHDRAWAL_AMOUNT < 0: print ("Insufficient funds..") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 else: WITHDRAWAL_TALLY_SAVINGS_1 = WITHDRAWAL_TALLY_SAVINGS_1+WITHDRAWAL_AMOUNT BALANCE_Savings_1 = BALANCE_Savings_1-WITHDRAWAL_AMOUNT elif WITHDRAWAL_SELECTION == '3': print ("SAVINGS[1]") if WITHDRAWAL_AMOUNT + WITHDRAWAL_TALLY_SAVINGS_2 > 300: print ("You have exceeded your daily individual account withdrawal limit.") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 elif BALANCE_Savings_2 - WITHDRAWAL_AMOUNT < 0: print ("Insufficient funds..") EXIT = input("Press ENTER to return to Main Menu... ") WHILE_WITHDRAWALS_MENU=1 else: WITHDRAWAL_TALLY_SAVINGS_2 = WITHDRAWAL_TALLY_SAVINGS_2+WITHDRAWAL_AMOUNT BALANCE_Savings_2 = BALANCE_Savings_2-WITHDRAWAL_AMOUNT else: WHILE_WITHDRAWALS_MENU=1 #### If you're here, you exited the main_menu ledger() print ("Thank you and have a good day.")