1. 程式人生 > >python項目練習之ATM

python項目練習之ATM

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後語句。
11 main.run()
atm.py

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: "
%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 }
settings

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 True
accounts 技術分享圖片
 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