記得上次小編上傳了一個購物車程序,這次呢稍微復雜一點,還是那句話,上傳在這里不是為了炫耀什么,只是督促小編學習,如果大神有什么意見和建議,歡迎指導。
於2018.3.11開始動筆,繼續完成這個項目。
一,需求:模擬實現一個ATM + 購物商城程序
要求如下: 1.額度15000或者自定義 2.實現購物商城,買東西加入購物車,調用信用卡接口結賬 3.可以提現,手續費5% 4.支持多賬戶登陸 5.支持賬戶間轉賬 6.記錄每月日常消費流水 7.提供還款接口 8.ATM記錄操作日志 9.提供管理接口,包括添加賬戶,用戶額度,凍結賬戶等 10.用戶認證用裝飾器
二,分析功能需求
ATM的角色: 管理員功能: 1,增刪改查,加錢,減錢 2,記錄日志 3,基本信息 4,額度 15000 普通用戶功能: 1,可以提現,手續費5% 2,支持多賬戶登錄 3,支持賬戶間轉賬 4,記錄每月日常消費流水 5,提供還款接口 6,ATM記錄操作日志 購物車程序: 1,可以進入程序購買商品 2,支持多賬戶登錄 3,購完東西顯示余額和購買的東西
三,文件創建
文件的創建是有開發規范的,比如下面:
bin 用於執行可執行文件 conf 配置文件 core 用於存放核心代碼 db 用於存放用戶數據 log 日志,記錄相關信息
四,思路流程圖
五,簡要說明
1,本程序思路是寫了一個ATM和購物商城的程序 其中購物商場簡單的實現了功能,並沒有調用ATM中的信用卡結賬 ATM寫了信用卡操作和管理員操作,沒有實現記錄每月日常消費流水 2,對於購物商城: 調用/shopping_mall/shopping_run.py文件執行 簡單的實現了用戶進入商城,選擇購物,則對賬戶余額進行扣款,推出時打印購買商品和余額 3,對於ATM有兩個入口: (1):普通用戶對信用卡操作 調用/atm-learn/bin/atm.py文件執行,可以打印賬戶信息、還款、取款、轉賬、賬單、退出等操作 ①賬戶信息 ②還款 ③取款 ④轉賬 ⑤賬單 ⑥退出 (2):管理用戶對信用卡操作 調用/atm-learn/bin/atm_manage.py文件執行則可以對用戶進行管理,解凍用戶、凍結用戶、申領新卡等操作 ①添加賬戶 ②凍結賬戶 ③解凍賬戶 ④退出
概述 本次作業文件夾一共包含了以下6個文件: 流程圖一:ATM用戶登錄思路流程圖 流程圖二:ATM管理登陸思路流程圖 流程圖三:購物車思路流程圖 程序結構圖:整個ATM+shopping的程序文件結構 程序文件: ATM + shopping 程序說明文件:README.md 程序介紹 本程序思路是寫了一個ATM和購物商城的程序 ATM寫了信用卡操作和管理員操作,沒有實現記錄每月日常消費流水 購物商場簡單的實現了功能,並沒有調用ATM中的信用卡結賬 1,對於ATM有兩個入口: (1):普通用戶對信用卡操作 調用/atm/bin/atm.py文件執行,可以打印賬戶信息、還款、取款、轉賬、賬單、退出等操作 (2):管理用戶對信用卡操作 調用/atm-learn/bin/atm_manage.py文件執行則可以對用戶進行管理,解凍用戶、凍結用戶、申領新卡等操作 2,對於購物商城: 調用/shopping/shopping_run.py文件執行 簡單的實現了用戶進入商城,選擇購物,則對賬戶余額進行扣款,推出時打印購買商品和余額 程序結構 備注 目前還不會在windows中用樹的結構,所以做出程序結構的txt版本,放在文件外面 對幾個實例json文件的說明 0000.json 一個用戶賬戶示例文件(這個是賬號正常,但是賬號過期,不在使用范圍內) 123.json 一個用戶賬戶示例文件(這個是賬號正常) 1234.json 一個用戶賬戶示例文件(這個是賬號被鎖定,除非登陸管理端修改被凍結的狀態,才能正常使用) admin.json 一個管理賬戶示例文件(如果不知道管理者的賬戶和密碼,可以查看) 不足及其改進的方面 1,未實現購物商城調用信用卡接口結賬 2,賬戶之間的轉賬 3,ATM中查看賬單,未能實現調用每個月的流水帳單,只是簡單的查看信用額度和賬戶余額 4,購物商場比較簡單,每次買一個東西就自己結賬退出
六,程序結構
atm+shopping`` ├── README ├── atm #ATM主程序目錄 │ ├── __init__.py │ ├── bin #ATM 執行文件 目錄 │ │ ├── __init__.py │ │ ├── atm.py #ATM 執行程序 │ │ └── manage.py #ATM 管理端 執行程序 │ ├── conf #配置文件 │ │ ├── __init__.py │ │ └── settings.py │ ├── core #主要程序邏輯都 在這個目錄 里 │ │ ├── __init__.py │ │ ├── accounts.py #用於從文件里加載和存儲賬戶數據 │ │ ├── atm_main.py #atm 主邏輯交互程序 │ │ ├── auth.py #用戶認證模塊 │ │ ├── db_handler.py #數據庫連接引擎 │ │ ├── logger.py #日志記錄模塊 │ │ ├── manage_main.py #atm管理端主邏輯交互程序 │ │ └── transaction.py #記賬\還錢\取錢等所有的與賬戶金額相關的操作都 在這 │ ├── db #用戶數據存儲的地方 │ │ ├── __init__.py │ │ ├── account_sample.py #一個存用戶的賬戶數據的例子 │ │ └── accounts #存各個用戶的賬戶數據 ,一個用戶一個文件 │ │ └── 0000.json #一個用戶賬戶示例文件(這個是賬號正常,但是賬號過期,不在使用范圍內) │ │ └── 123.json #一個用戶賬戶示例文件(這個是賬號正常) │ │ └── 1234.json #一個用戶賬戶示例文件(這個是賬號被鎖定,除非登陸管理端修改被凍結的狀態,才能正常使用) │ │ └── admin.json #一個管理賬戶示例文件(如果不知道管理者的賬戶和密碼,可以查看) │ └── log #日志目錄 │ ├── __init__.py │ ├── access.log #用戶訪問和操作的相關日志 │ └── transactions.log #所有的交易日志 └── shopping #購物車目錄 └── __init__.py └── 123.json #一個購物用戶賬戶示例文件(包括用戶id,密碼,余額) └── shopping_main.py #主邏輯交互程序 └── shopping_run.py #購物車 執行程序
七,程序代碼
7.1 ATM代碼
bin下atm.py
# _*_ coding: utf-8 _*_ import os import sys #添加環境變量 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #找到路徑 sys.path.append(BASE_DIR) #添加路徑 #將main.py里面所有代碼封裝成main變量 from core import atm_main '''ATM程序的執行文件''' if __name__ == '__main__': atm_main.run_atm()
bin下atm_manage.py
# _*_ coding: utf-8 _*_ import os import sys #添加環境變量 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #找到路徑 sys.path.append(BASE_DIR) #添加路徑 from core import manage_main '''管理程序的執行文件''' if __name__ == '__main__': manage_main.run_manage()
conf/setting.py
# _*_ coding: utf-8 _*_ '''初始化的配置''' import logging import os import sys #到ATM目錄,方便后面創建賬戶文件 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) DATABASE = { 'engine':'file_storage', #文件存儲,這里可擴展成數據庫形式的 'name':'accounts', #db下的文件名 'path':'%s/db' %BASE_DIR } LOGIN_LEVEL = logging.INFO #初始化日志記錄級別為INFO,INFO以下的可以直接打印 #日志類型 LOGIN_TYPE = { 'access':'access.log', 'transaction':'transaction.log' } TRANSACTION_TYPE = { 'repay':{'action':'plus','interest':0}, 'withdraw':{'action':'minus','interest':0.05}, 'transfer':{'action':'minus','interest':0.05}, 'consume':{'action':'minus','interest':0}, }
core/accounts.py
# _*_ coding: utf-8 _*_ import os import sys import json import logging import time import datetime BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) #添加環境變量 from core import auth from core import db_handler from conf import settings def load_current_balance(account_id): ''' # 把數據load下,返回賬戶余額和其他基礎信息 :param account_id: 用戶賬戶的名字 :return: 返回最新讀到的數據文件中的最新數據 ''' db_path = db_handler.db_handler(settings.DATABASE) account_file = "%s/%s.json"%(db_path,account_id) with open(account_file,'r',encoding='utf-8') as f: acc_data = json.load(f) return acc_data def dump_account(account_dic): ''' 在更新完后,把數據dump到文件中,文件地址為\atm-learn/db/accounts :param account_data: :return: ''' db_path =db_handler.db_handler(settings.DATABASE) account_file = "%s/%s.json" %(db_path,account_dic['id']) with open(account_file,'w',encoding='utf-8') as f: acc_data = json.dump(account_dic,f)
core/atm_main.py
# _*_ coding: utf-8 _*_ '''主邏輯交互模塊''' import logging import sys from core import auth from core import logger from core import accounts from core import transaction from core import db_handler #用戶數據信息 user_data = { 'account_id':None , #賬戶ID 'is_authenticated':False, #是否認證 'account_data':None #賬戶數據 } #調用log文件下的log方法,返回日志對象 access_logger = logger.logger('access') trans_logger = logger.logger('transaction') def account_info(func): ''' 用戶賬號信息,acc_data:包括ID,is_authenticaed,用戶帳號信息,主要看是否被鎖住 :return: ''' def wrapper(acc_data): account_id=acc_data["account_id"] account_data=acc_data["account_data"] status=acc_data['account_data']["status"] if int(status) ==0: func(acc_data) return True else: print("\033[32;1msorry your account was locked\033[0m") exit() return wrapper @account_info def disp_account_info(acc_data): ''' 展示賬戶信息 #去除 password 字段顯示 :param account_data: 賬戶信息 :return: ''' print("--------------ACCOUNT INFO---------------") for i in acc_data['account_data']: print("{:^20}:\033[32;1m{:^20}\033[0m".format(i, acc_data['account_data'][i])) @account_info def repay(acc_data): ''' 存款 acc_data:包括ID,is_authenticaed,用戶帳號信息 :return: ''' account_data = accounts.load_current_balance(acc_data['account_id']) current_balance = '''---------------------BALANCE INFO----------------- Credit : %s Balance: %s'''%(account_data['credit'],account_data['balance']) print(current_balance) back_flag = False while not back_flag: repay_amount = input("\033[32;1mInput repay amout(input 'b' is back):\033[0m").strip() if len(repay_amount) >0 and repay_amount.isdigit(): new_balance = transaction.make_transaction( trans_logger,account_data,'repay',repay_amount) if new_balance: print('''\033[34;1mNEW Balance:%s\033[0m'''%(new_balance['balance'])) elif repay_amount == 'b': back_flag = True else: print("\033[31;1m%s is not valid amount ,Only accept interger!\033[0m"%repay_amount) @account_info def withdraw(acc_data): ''' 打印當前余下的錢,並且讓用戶做取錢的功能 :param acc_data: :return: ''' account_data = accounts.load_current_balance(acc_data['account_id']) current_balance ='''---------------------BALANCE INFO----------------- Credit : %s Balance: %s'''%(account_data['credit'],account_data['balance']) print(current_balance) back_flag = False while not back_flag: withdraw_amount = input("\033[33;1mInput withdraw amout(input 'b' is back):\033[0m").strip() if len(withdraw_amount) > 0 and withdraw_amount.isdigit(): new_balance = transaction.make_transaction( trans_logger, account_data, 'withdraw', withdraw_amount) if new_balance: print('''\033[32;1mNEW Balance:%s\033[0m''' % (new_balance['balance'])) elif withdraw_amount == 'b': back_flag = True else: print('\033[31;1m[%s] is not a valid amount , only accept integer\033[0m'%withdraw_amount) @account_info def transfer(acc_data): ''' 轉賬 :return: ''' account_data = accounts.load_current_balance(acc_data['account_id']) current_balance = '''---------------------BALANCE INFO----------------- Credit : %s Balance: %s''' % (account_data['credit'], account_data['balance']) print(current_balance) back_flag = False while not back_flag: transfer_amount = input("\033[33;1mInput transfer amount(input 'b' is back):\033[0m").strip() if len( transfer_amount) > 0 and transfer_amount.isdigit(): new_balance = transaction.make_transaction( trans_logger, account_data, 'transfer', transfer_amount) if new_balance: print('''\033[32;1mNEW Balance:%s\033[0m''' % (new_balance['balance'])) elif transfer_amount == 'b': back_flag = True else: print('\033[31;1m[%s] is not a valid amount , only accept integer\033[0m' % transfer_amount) @account_info def paycheck(acc_data): ''' 賬單檢查,記錄每月日常消費流水 :return: ''' account_data = accounts.load_current_balance(acc_data['account_id']) current_balance = '''---------------------BALANCE INFO----------------- Credit : %s Balance: %s''' % (account_data['credit'], account_data['balance']) print(current_balance) @account_info def logout(acc_data): ''' 退出登陸 :return: ''' print("\033[32;1m-------Looking forward to your next visit-------\033[0m") exit() def interactive(acc_data): ''' 用戶交互 :return: ''' msg = ( ''' ------------------CHINA BANK -------------- \033[31;1m1.賬戶信息 2.存款 3.取款 4.轉賬 5.賬單 6.退出 \033[0m''' ) menu_dic = { "1":disp_account_info, "2":repay, "3":withdraw, "4":transfer, "5":paycheck, "6":logout, } exit_flag = False while not exit_flag: print(msg) user_choice = input(">>>>").strip() if user_choice in menu_dic: menu_dic[user_choice](acc_data) else: print("\033[31;1mYou choice doesn't exist!\033[0m") def run_atm(): ''' 當程序啟動時候,調用,主要用於實現主要交互邏輯 :return: ''' # 調用認證模塊,返回用戶文件json.load后的字典,傳入access_logger日志對象 access_data = auth.access_login(user_data,access_logger) if user_data['is_authenticated']: #如果用戶認證成功 user_data["account_data"] = access_data interactive(user_data) #用戶交互開始
core/auth.py
# _*_ coding: utf-8 _*_ import os import json import time from core import accounts from core import db_handler from conf import settings from bin import atm_manage from core import atm_main def access_auth(account,password,log_obj): ''' 下面access_login調用access_auth方法,用於登陸 :param account: 用戶名 :param password: 密碼 :return: 如果為超期,返回字典,超期則打印相應提示 ''' db_path = db_handler.db_handler(settings.DATABASE) #調用db_handle下的handle方法,返回路徑/db/accounts account_file = '%s/%s.json'%(db_path, account) #用戶文件 #判斷文件和i否存在,如果存在的話 則執行下面的 if os.path.isfile(account_file): #如果用戶文件存在(即用戶存在) with open(account_file,'r',encoding='utf-8') as f: #打開文件 account_data = json.load(f) #file_data為字典形式 if account_data['password'] == password: expire_time = time.mktime(time.strptime(account_data['expire_date'],'%Y-%m-%d')) if time.time() > expire_time: #如果信用卡已經過期,當前時間戳大於國企的時間戳 log_obj.error("Account [%s] had expired,Please contract the bank" % account) print("\033[31;1mAccount %s had expired,Please contract the bank"%account) else: #信用卡未過期,返回用戶數據的字典 log_obj.info("Account [%s] logging success" % account) return account_data else: log_obj.error("Account or Password does not correct!") print("\033[31;1mAccount or Passwordoes not correct!\033[0m") else: #用戶不存在 log_obj.error("Account [%s] does not exist!" % account) print("\033[31;1mAccount [%s] does not exist!\033[0m"%account) def access_login(user_data,log_obj): ''' 用戶登陸,當登陸失敗超過三次 :param user_date:main.py里面的字典,用戶信息數據,只存在內存中 :return:若用戶賬號密碼正確,且信用卡未過期,則返回用戶數據的字典 ''' retry_count = 0 while user_data['is_authenticated'] is not True and retry_count < 3: account = input('\033[32;1mplease input Acount:\033[0m').strip() password = input('\033[32;1mplease input Password:\033[0m').strip() #用戶賬號密碼正確而且信用卡未過期,返回用戶數據的字典 auth = access_auth(account, password,log_obj) if auth: user_data['is_authenticated'] = True #用戶認證為True user_data['account_id'] = account #用戶賬號ID為賬號名 # print("welcome") return auth retry_count += 1 else: print("Account [%s] try logging too many times..."%account) log_obj.error("Account [%s] try logging too many times..." % account) exit()
core/db_handler.py
# _*_ coding: utf-8 _*_ '''處理與數據之間的交互,如果file_db_storage,返回路徑''' import json import time from conf import settings def file_db_handle(conn_params): ''' parse the db file path 對文件路徑做語法分析 :param conn_params: :return: ''' db_path = '%s/%s' %(conn_params['path'],conn_params['name']) return db_path def db_handler(conn_parms): ''' :param conn_parms: the db connection params set in settings :return: a DATABASE = { 'engine':'file_storage', #文件存儲,這里可擴展成數據庫形式的 'name':'accounts', #db下的文件名 'path':'%s/db' %BASE_DIR } ''' if conn_parms['engine'] == 'file_storage': return file_db_handle(conn_parms)
core/logger.py
# _*_ coding: utf-8 _*_ '''操作所有的日志工作''' import logging from conf import settings def logger(log_type): logger = logging.getLogger(log_type) logger.setLevel(settings.LOGIN_LEVEL) #創建屏幕對象和設置等級debug # ch = logging.StreamHandler() # ch.setLevel(settings.LOGIN_LEVEL) #創建文件對象,給文件對象設置等級 log_file = "%s/log/%s"%(settings.BASE_DIR,settings.LOGIN_TYPE[log_type]) fh = logging.FileHandler(log_file) fh.setLevel(settings.LOGIN_LEVEL) # 設置輸出對象格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #把格式添加到配置中 # ch.setFormatter(formatter) fh.setFormatter(formatter) #把日志打印到指定的handler # logger.addHandler(ch) logger.addHandler(fh) return logger
core/manage_main.py
# _*_ coding: utf-8 _*_ '''管理端,提供管理接口,包括添加賬戶,用戶額度,凍結賬戶,解凍賬戶''' import os import sys import json from core import auth from core import accounts from core import transaction from core import db_handler from conf import settings # 解凍賬戶 def unlock_account(): '''解凍賬戶的初步思路是讀取用戶文件,把status的狀態一更改就ok ''' account = input("\033[34;1mPlease input the account that you want to unlock:\033[0m") read_data = unlock_accountcore(account) return read_data def unlock_accountcore(account): ''' 解凍賬戶,讀取用戶文件,讀到status,把狀態更改為0 #0 = naormal,1 = locked , :param account: :return: ''' # 調用db_handle下的handle方法,返回路徑/db/accounts db_path = db_handler.db_handler(settings.DATABASE) account_file = '%s/%s.json' % (db_path, account) account_new = '%s/%s.json' % (db_path, account) if os.path.isfile(account_file): with open(account_file, 'r', encoding='utf-8') as f: account_data = json.load(f) account_data['status'] = 0 with open(account_new, 'w', encoding='utf-8') as fnew: new_data = json.dump(account_data, fnew) # 凍結賬戶 def lock_account(): ''' 凍結賬戶,思路與解凍剛好相反 :param acc_data: :return: ''' account = input("\033[34;1mPlease input the account that you want to lock:\033[0m") read_data = lock_accountcore(account) return read_data def lock_accountcore(account): ''' 凍結賬戶,讀取用戶文件,讀到status,把狀態更改為1 #0 = naormal,1 = locked , :param account: :return: ''' # 調用db_handle下的handle方法,返回路徑/db/accounts db_path = db_handler.db_handler(settings.DATABASE) account_file = '%s/%s.json' % (db_path, account) account_new = '%s/%s.json' % (db_path, account) if os.path.isfile(account_file): with open(account_file, 'r', encoding='utf-8') as f: account_data = json.load(f) account_data['status'] = 1 with open(account_new, 'w', encoding='utf-8') as fnew: new_data = json.dump(account_data, fnew) # 添加賬戶 def add_account(): ''' 添加賬戶,是admin添加的用戶,下次就可以登陸添加的賬戶了 :return: ''' acc_dic = { 'id':None, 'balance':None, 'password': None, 'credit': None, 'enroll_date': None, 'expire_date': None, 'status': None # 0 = naormal,1 = locked , 2 = disabled } menu = { 0:"請輸入要添加的賬戶:", 1:"請輸入要添加的余額:", 2:"請輸入要添加的密碼:", 3:"請輸入要添加的信用額度(only more than 0)", 4:"請輸入要添加的辦卡日期(such as 2018-8-8)", 5:"請輸入要添加的卡到期時間(such as 2018-8-8)", 6:"請輸入是否鎖定添加賬號的狀態(only input 0 or 1)", } menu_user = { 0: "id", 1: "balance", 2: "password", 3: "credit", 4: "enroll_date", 5: "expire_date", 6: "status", } print("\033[31;1m\t\twelcome to add account\033[0m") print('*'.center(40,'*')) for i in range(7): data = input('%s'%menu[i]).strip() acc_dic["%s" % menu_user[i]] = data accounts.dump_account(acc_dic) print("\033[32;1mcongratulations you account was created successfully\033[0m") return True # 退出程序 def logout(): ''' 退出登陸 :return: ''' print("\033[32;1m-------Looking forward to your next visit-------\033[0m") exit() def auth_login(): ''' 登陸管理員密碼賬號 :return: ''' print("\033[34;1m-------Welcome into the management interface--------\033[0m") managename = input("\033[34;1mplease input Username:\033[0m") password = input("\033[34;1mplease input Password:\033[0m") account = account_auth(managename,password) return account def account_auth(managename,password): ''' 管理員認證信息 {"id": admin,"password": "root" } :return: ''' db_path = db_handler.db_handler(settings.DATABASE) # 調用db_handle下的handle方法,返回路徑/db/accounts managename_file = '%s/%s.json'%(db_path,managename) if os.path.isfile(managename_file): with open(managename_file,'r',encoding='utf-8') as f: manage_data = json.load(f) # print(manage_data) if manage_data['password'] == password: print("\033[31;1m-------Welcome to the administrator--------\033[0m") return manage_interactive(managename) else: print("\033[31;1mAccount or Passwordoes not correct!\033[0m") # 管理界面主程序 def manage_interactive(managename): menu = ''' \033[31;1m-----------management console----------- 1,add_account 2,lock_account 3,unblock_account 4, exit\033[0m''' menu_dic = { '1':add_account, '2':lock_account, '3':unlock_account, '4': logout } exit_flag = False while not exit_flag: print(menu) user_option = input('please input your choice>>>').strip() if user_option in menu_dic: print(menu_dic[user_option]()) else: print("\033[31;1mYou choice doesn't exist!\033[0m") def run_manage(): ''' 當程序啟動的時候調用,主要用於實現主要交互邏輯,客戶認證登陸 :return: ''' auth_login()
core/tranction.py
# _*_ coding: utf-8 _*_ import json from conf import settings from core import accounts def make_transaction(log_obj,account_data,tran_type,amount,**others): ''' 處理所有的用戶的交易 :param log_obj: :param amount_data: user account data :param tran_type: transaction type :param amount: transaction amount :param other: mainly for logging usage :return: ''' # 將字符串類型轉換為float類型 amount = float(amount) # tran_type 交易類型 if tran_type in settings.TRANSACTION_TYPE: # 利息金額 interest =amount * settings.TRANSACTION_TYPE[tran_type]['interest'] old_balance = account_data['balance'] if tran_type in settings.TRANSACTION_TYPE: # 利息金額 interest = amount * settings.TRANSACTION_TYPE[tran_type]["interest"] # 用戶原金額 old_balace = account_data["balance"] if settings.TRANSACTION_TYPE[tran_type]['action'] == 'plus': new_balance = float(old_balance) + amount + float(interest) elif settings.TRANSACTION_TYPE[tran_type]['action'] == 'minus': new_balance = float(old_balance) - amount - float(interest) # 做一個判斷小於0的操作,減錢時對帳戶金額進行檢查,防止超額 if new_balance <0: print('\033[31;1mYour credit [%s] is not enough for this transaction' '[%s]'%(account_data['credit'],(amount + interest),old_balance)) return account_data['balance'] = new_balance # 保存新的余額返回到文件中 accounts.dump_account(account_data) log_obj.info("account:%s action:%s amount:%s interest:%s " %(account_data['id'],tran_type,amount,interest)) return account_data else: print("\033[31;1mTransaction type [%s] is not exist\033[0m"%tran_type)
db/account_sample/py(此處只舉一個例子)
# _*_ coding: utf-8 _*_ import json acc_dic = { 'id':1234, 'password':'abc', 'credit':15000, 'balance':15000, 'enroll_date':'2018-01-01', 'expire_date':'2023-01-01', # 'pay_day':22, #支付日期(但是現在沒有要求,可以不考慮) 'status':0 #0 = naormal,1 = locked , 2 = disabled } print(acc_dic,type(acc_dic)) a = json.dumps(acc_dic) print(a,type(a))
7.2 shopping代碼
shopping_main.py
# _*_ coding: utf-8 _*_ import datetime import os import json def auth_login(): ''' 登陸密碼賬號 :return: ''' print("-------welcome to shopping_mall--------") username = input("\033[32;1mplease input Username:\033[0m") password = input("\033[32;1mplease input Password:\033[0m") account = account_auth(username,password) return account def account_auth(username,password): ''' 用戶認證賬戶信息格式化讀取模塊,並驗證賬號密碼是否正確 :return: ''' username_file = '%s.json'%username if os.path.isfile(username_file): with open(username_file,'r',encoding='utf-8') as f: username_data = json.load(f) if username_data['password'] == password: balance = username_data['balance'] print("\033[32;1myou balance is %s\033[0m"% balance) return account_shopping(username,balance) else: print("\033[31;1mAccount or Passwordoes not correct!\033[0m") def account_shopping(username,balance): '''用戶購物操作 這次只能買一件東西,不能重復買 ''' goods = [ {"name": "電腦", "price": 6999}, {"name": "鼠標", "price": 300}, {"name": "游艇", "price": 2000}, {"name": "美女", "price": 9980}, ] print("*".center(40, '*')) print("goods".center(40, '-')) for index,item in enumerate(goods): print(index,item) print('end'.center(40,'-')) while True: choice = input("請輸入要想購買的商品編號(或者按q直接退出):") if choice.isdigit(): #判斷是否為數字 choice = int(choice) if choice>=0 and choice<len(goods): #判斷是否在商品范圍里面 choice_goods = goods[choice].get('name') print("you will buy \033[32;1m%s\033[0m"%choice_goods) if balance > goods[choice].get('price'): new_balance = balance - goods[choice].get('price') print("now your balance is \033[32;1m%s\033[0m"% new_balance) else: print("sorry your balance is \033[32;1m%s\033[0m,unable to purchase" %balance) continue else: print("\033[31;1mplease input the correct goods number\033[0m") elif choice == 'q': exit() return write_data(username,new_balance) def write_data(username, new_balance): ''' 買了東西之后,余額信息更新一下 :param username: 用戶姓名 :param new_balance: 余額信息 :return: ''' username_file = '%s.json' % username usernew_file = '%s.json' % username f = open(username_file, 'r', encoding='utf-8') username_data = json.load(f) username_data['balance'] = new_balance f.close() fnew = open(usernew_file, 'w', encoding='utf-8') new_data = json.dump(username_data,fnew) fnew.close() def run_shopping(): ''' 當程序啟動的時候,調用,主要用於實現主要交互邏輯,客戶認證登陸函數 :return: ''' userdata = auth_login() def account_recharge(balance): '''用戶充值操作,此思路是接ATM''' recharge_money = input("please input recharge money: ") recharge_money =int(recharge_money) balance = balance + recharge_money print("Congratulations. Recharge success. balance is \033[32;1m%s\033[0m" %balance) return balance def legout(): ''' 退出程序 :return: ''' print("\033[32;1m-------Looking forward to your next visit-------\033[0m") exit() def interactive(acc_data): ''' 用戶交互 :param acc_data: :return: ''' msg = ( ''' ------------------SHOPPING INFO -------------- \033[31;1m1.購物 2.充值 3.退回 \033[0m''' ) menu_dic = { "1": account_shopping, "2": account_recharge, "3": legout, } exit_flag = False while not exit_flag: print(msg) user_choice = input(">>>>").strip() if user_choice in menu_dic: menu_dic[user_choice]() else: print("\033[31;1mYou choice doesn't exist!\033[0m") def manage_accountauth(): ''' 管理員賬戶認證函數, :return: ''' manage_account = [] with open('manageinfo.txt', 'r', encoding='utf-8') as f: for i in f.readlines(): i_space = i.replace('\n', '') manage_account.append(i_space) return manage_account def account_balance(): ''' 賬戶余額信息格式化讀取模塊 :return: ''' balance = [] with open('account_balance.txt', 'r', encoding='utf-8') as f: for i in f.readlines(): i_space = i.replace('\n', '') balance.append(i_space) return balance def account_save(account,cash): ''' 把賬戶及其余額信息持久化到本地,以消除文件內容,然后以讀寫的方式打開文件 :param account: 用戶信息 :return: ''' save_info = open('account_balance.txt','w+',encoding='utf-8') save_info.write(account) save_info.write('\n') save_info.write(str(cash)) save_info.close() def account_auth_changshi(username,password): ''' 用戶認證賬戶信息格式化讀取模塊,嘗試登陸三次, {"id": 123,"password": "123", "balance": 20000 } :return: ''' retry_count = 0 while username_data['password'] is not True and retry_count <3: username_file = '%s.json'%username if os.path.isfile(username_file): with open(username_file,'r',encoding='utf-8') as f: username_data = json.load(f) print(username_data['password']) print(password) if username_data['password'] == password: return account_shopping else: print("\033[31;1mAccount or Passwordoes not correct!\033[0m") retry_count += 1 else: print("Account [%s] try logging too many times..." % username) exit()
shopping_run.py
# _*_ coding: utf-8 _*_ import os import sys #添加環境變量 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #找到路徑 sys.path.append(BASE_DIR) #添加路徑 from shopping import shopping_main '''購物車程序的執行文件''' if __name__ == '__main__': shopping_main.run_shopping()