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.
Note:
Normally we would not be posting homework in this fashion however this approach should be fairly different than the course itself would have produced had I gone through all of the iteration steps using the course material.
If you use this for your homework, expect your instructor to see the red flags as there are some items here that are well outside of programming 1 and be prepared to be graded accordingly.
################################################################################# ## /---------------------------------------------------------------------------\* ## | Program: ATM ## | Version: 0.0.1 ## | Language: 3.7.4 ## | ## | Description: ATM Project Iteration #1 ## | ## | Course: IT XXX-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 == 0: 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: ##### 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 cls() ledger() print ("") print ("Thank you and have a good day.")