python項目練習之ATM
阿新 • • 發佈:2018-08-18
user plus bject 交易 not ted login code 登陸
程序框圖 (消費模塊暫未寫入)
bin:程序執行
1 import os 2 import sys 3 base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 print(base_dir) 5 sys.path.append(base_dir) 6 7 from core import main 8 9 10 if __name__ == ‘__main__‘: #當作為腳本直接運行的時候,此時__name__等於__main__,當作為模塊導入的時候,__name__為文件名但不帶.py,故不運行if後語句。atm.py11 main.run()
config:配置文件
1 import os 2 import sys 3 import logging 4 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 6 7 DATABASE = { 8 ‘engine‘: ‘file_storage‘, #support mysql,postgresql in the future 9 ‘name‘:‘accounts‘, 10 ‘path‘: "settings%s/db" % BASE_DIR 11 } 12 13 14 LOG_LEVEL = logging.INFO 15 LOG_TYPES = { 16 ‘transaction‘: ‘transactions.log‘, 17 ‘access‘: ‘access.log‘, 18 ‘11111‘:‘11111.log‘ 19 } 20 21 TRANSACTION_TYPE = { 22 ‘repay‘:{‘action‘:‘plus‘, ‘interest‘:0}, 23 ‘withdraw‘:{‘action‘:‘minus‘, ‘interest‘:0.05}, 24 ‘transfer‘:{‘action‘:‘minus‘, ‘interest‘:0.05}, 25 ‘consume‘:{‘action‘:‘minus‘, ‘interest‘:0}, 26 }
core:程序主要代碼
1 import json 2 import time 3 from core import db_handler 4 from conf import settings 5 6 7 def load_current_balance(account_id): 8 ‘‘‘ 9 return account balance and other basic info 10 :param account_id: 11 :return: 12 ‘‘‘ 13 db_path = db_handler.db_handler(settings.DATABASE) 14 account_file = "%s/%s.json" %(db_path,account_id) 15 with open(account_file) as f: 16 acc_data = json.load(f) 17 return acc_data 18 def dump_account(account_data): 19 ‘‘‘ 20 after updated transaction or account data , dump it back to file db 21 :param account_data: 22 :return: 23 ‘‘‘ 24 db_path = db_handler.db_handler(settings.DATABASE) 25 account_file = "%s/%s.json" %(db_path,account_data[‘id‘]) 26 with open(account_file, ‘w‘) as f: 27 acc_data = json.dump(account_data,f) 28 29 return Trueaccounts
1 import os 2 from core import db_handler 3 from conf import settings 4 from core import logger 5 import json 6 import time 7 8 def acc_auth(account,password): 9 ‘‘‘ 10 account auth func 11 :param account: credit account number 12 :param password: credit card password 13 :return: if passed the authentication , retun the account object, otherwise ,return None 14 ‘‘‘ 15 db_path = db_handler.db_handler(settings.DATABASE) 16 account_file = "%s/%s.json" %(db_path,account) 17 print(account_file) #base_dir + accounts + account.json 18 if os.path.isfile(account_file): #判斷文件名是否存在,存在執行下面語句 19 with open(account_file,‘r‘) as f: 20 account_data = json.load(f) 21 if account_data[‘password‘] == password: 22 exp_time_stamp = time.mktime(time.strptime(account_data[‘expire_date‘], "%Y-%m-%d")) 23 if time.time() >exp_time_stamp: 24 print("\033[31;1mAccount [%s] has expired,please contact the back to get a new card!\033[0m" % account) 25 else: #passed the authentication 26 return account_data 27 else: 28 print("\033[31;1mAccount ID or password is incorrect!\033[0m") 29 else: 30 print("\033[31;1mAccount [%s] does not exist!\033[0m" % account) 31 32 def acc_login(user_data,log_obj): 33 ‘‘‘ 34 account login func 35 :user_data: user info data , only saves in memory 36 :return: 37 ‘‘‘ 38 retry_count = 0 39 while user_data[‘is_authenticated‘] is not True and retry_count < 3 : 40 account = input("\033[32;1maccount:\033[0m").strip() 41 password = input("\033[32;1mpassword:\033[0m").strip() 42 auth = acc_auth(account, password) 43 if auth: #not None means passed the authentication 44 user_data[‘is_authenticated‘] = True 45 user_data[‘account_id‘] = account 46 #print("welcome") 47 return auth 48 retry_count +=1 49 else: 50 log_obj.error("account [%s] too many login attempts" % account) 51 exit()登陸認證
1 def file_db_handle(conn_params): 2 ‘‘‘ 3 parse the db file path 4 :param conn_params: the db connection params set in settings 5 :return: 6 ‘‘‘ 7 print(‘file db:‘,conn_params) 8 db_path =‘%s/%s‘ %(conn_params[‘path‘],conn_params[‘name‘]) 9 return db_path 10 11 def mysql_db_handle(conn_parms): 12 pass 13 def db_handler(conn_parms): 14 ‘‘‘ 15 connect to db 16 :param conn_parms: the db connection params set in settings 17 :return:a 18 ‘‘‘ 19 20 if conn_parms[‘engine‘] == ‘file_storage‘: 21 return file_db_handle(conn_parms) 22 23 if conn_parms[‘engine‘] == ‘mysql‘: 24 return mysql_db_handle(conn_parms)數據存儲路徑
1 import logging 2 from conf import settings 3 4 def logger(log_type): 5 6 #create logger 7 logger = logging.getLogger(log_type) 8 logger.setLevel(settings.LOG_LEVEL) 9 10 11 # create console handler and set level to debug 12 ch = logging.StreamHandler() 13 ch.setLevel(settings.LOG_LEVEL) 14 15 # create file handler and set level to warning 16 log_file = "%s/log/%s" %(settings.BASE_DIR, settings.LOG_TYPES[log_type]) 17 fh = logging.FileHandler(log_file) 18 fh.setLevel(settings.LOG_LEVEL) 19 # create formatter 20 formatter = logging.Formatter(‘%(asctime)s - %(name)s - %(levelname)s - %(message)s‘) 21 22 # add formatter to ch and fh 23 ch.setFormatter(formatter) 24 fh.setFormatter(formatter) 25 26 # add ch and fh to logger 27 logger.addHandler(ch) 28 logger.addHandler(fh) 29 30 return logger日誌
1 from core import auth 2 from core import accounts 3 from core import logger 4 from core import accounts 5 from core import transaction 6 import time 7 8 #transaction logger 9 trans_logger = logger.logger(‘transaction‘) 10 #access logger 11 access_logger = logger.logger(‘access‘) 12 13 14 #temp account data ,only saves the data in memory 15 user_data = { 16 ‘account_id‘:None, 17 ‘is_authenticated‘:False, 18 ‘account_data‘:None 19 20 } 21 22 def account_info(acc_data): 23 print(user_data) 24 def repay(acc_data): 25 ‘‘‘ 26 print current balance and let user repay the bill 27 :return: 28 ‘‘‘ 29 account_data = accounts.load_current_balance(acc_data[‘account_id‘]) #獲取用戶id,就是要用實時的最新數據,為了安全 30 #for k,v in account_data.items(): 31 # print(k,v ) 32 current_balance= ‘‘‘ --------- BALANCE INFO -------- 33 Credit : %s 34 Balance: %s‘‘‘ %(account_data[‘credit‘],account_data[‘balance‘]) 35 print(current_balance) 36 back_flag = False 37 while not back_flag: 38 repay_amount = input("\033[33;1mInput repay amount:\033[0m").strip() 39 if len(repay_amount) >0 and repay_amount.isdigit(): 40 #print(‘ddd 00‘) 41 new_balance = transaction.make_transaction(trans_logger,account_data,‘repay‘, repay_amount) 42 if new_balance: 43 print(‘‘‘\033[42;1mNew Balance:%s\033[0m‘‘‘ %(new_balance[‘balance‘])) 44 45 else: 46 print(‘\033[31;1m[%s] is not a valid amount, only accept integer!\033[0m‘ % repay_amount) 47 48 if repay_amount == ‘b‘: 49 back_flag = True 50 def withdraw(acc_data): 51 ‘‘‘ 52 print current balance and let user do the withdraw action 53 :param acc_data: 54 :return: 55 ‘‘‘ 56 account_data = accounts.load_current_balance(acc_data[‘account_id‘]) 57 current_balance= ‘‘‘ --------- BALANCE INFO -------- 58 Credit : %s 59 Balance: %s‘‘‘ %(account_data[‘credit‘],account_data[‘balance‘]) 60 print(current_balance) 61 back_flag = False 62 while not back_flag: 63 withdraw_amount = input("\033[33;1mInput withdraw amount:\033[0m").strip() 64 if len(withdraw_amount) >0 and withdraw_amount.isdigit(): 65 new_balance = transaction.make_transaction(trans_logger,account_data,‘withdraw‘, withdraw_amount) # new_balance就是 函數返回值 acount_data 66 if new_balance: 67 print(‘‘‘\033[42;1mNew Balance:%s\033[0m‘‘‘ %(new_balance[‘balance‘])) 68 69 else: 70 print(‘\033[31;1m[%s] is not a valid amount, only accept integer!\033[0m‘ % withdraw_amount) 71 72 if withdraw_amount == ‘b‘: 73 back_flag = True 74 75 def transfer(acc_data): 76 pass 77 def pay_check(acc_data): 78 pass 79 def logout(acc_data): 80 pass 81 def interactive(acc_data): 82 ‘‘‘ 83 interact with user 84 :return: 85 ‘‘‘ 86 menu = u‘‘‘ 87 ------- Oldboy Bank --------- 88 \033[32;1m1. 賬戶信息 89 2. 還款(功能已實現) 90 3. 取款(功能已實現) 91 4. 轉賬 92 5. 賬單 93 6. 退出 94 \033[0m‘‘‘ 95 menu_dic = { 96 ‘1‘: account_info, 97 ‘2‘: repay, 98 ‘3‘: withdraw, 99 ‘4‘: transfer, 100 ‘5‘: pay_check, 101 ‘6‘: logout, 102 } 103 exit_flag = False 104 while not exit_flag: 105 print(menu) 106 user_option = input(">>:").strip() 107 if user_option in menu_dic: 108 menu_dic[user_option](acc_data) #比如選擇了2 ,則運行 repay(acc_data),調用repay函數 109 110 else: 111 print("\033[31;1mOption does not exist!\033[0m") 112 def run(): 113 ‘‘‘ 114 this function will be called right a way when the program started, here handles the user interaction stuff 115 :return: 116 ‘‘‘ 117 acc_data = auth.acc_login(user_data,access_logger) #userdata作為條件,access_logger作為日誌信息傳入 118 if user_data[‘is_authenticated‘]: 119 user_data[‘account_data‘] = acc_data #acc_data 即是用戶信息 1234.json 120 interactive(user_data) #交互主程序
1 from conf import settings 2 from core import accounts 3 from core import logger 4 #transaction logger 5 6 7 def make_transaction(log_obj,account_data,tran_type,amount,**others): 8 ‘‘‘ 9 deal all the user transactions 10 :param account_data: user account data 11 :param tran_type: transaction type 12 :param amount: transaction amount 13 :param others: mainly for logging usage 14 :return: 15 ‘‘‘ 16 amount = float(amount) 17 if tran_type in settings.TRANSACTION_TYPE: 18 19 interest = amount * settings.TRANSACTION_TYPE[tran_type][‘interest‘] 20 old_balance = account_data[‘balance‘] 21 if settings.TRANSACTION_TYPE[tran_type][‘action‘] == ‘plus‘: 22 new_balance = old_balance + amount + interest 23 elif settings.TRANSACTION_TYPE[tran_type][‘action‘] == ‘minus‘: 24 new_balance = old_balance - amount - interest 25 #check credit 26 if new_balance <0: 27 print(‘‘‘\033[31;1mYour credit [%s] is not enough for this transaction [-%s], your current balance is 28 [%s]‘‘‘ %(account_data[‘credit‘],(amount + interest), old_balance )) 29 return 30 account_data[‘balance‘] = new_balance 31 accounts.dump_account(account_data) #save the new balance back to file 32 log_obj.info("account:%s action:%s amount:%s interest:%s" % 33 (account_data[‘id‘], tran_type, amount,interest) ) 34 return account_data 35 else: 36 print("\033[31;1mTransaction type [%s] is not exist!\033[0m" % tran_type)交易種類
db:用戶信息存儲
1 {"id": "gkx", "password": "123", "credit": 15000, "balance": 15000, "enroll_date": "2016-01-02", "expire_date": "2021-01-01", "pay_day": 22, "status": 0}View Code
python項目練習之ATM