ATM:模擬實現一個ATM + 購物商城程序python
額度 15000或自定義git
實現購物商城,買東西加入 購物車,調用信用卡接口結帳數據庫
能夠提現,手續費5%app
支持多帳戶登陸ide
支持帳戶間轉帳ui
記錄每個月平常消費流水spa
提供還款接口3d
ATM記錄操做日誌日誌
提供管理接口,包括添加帳戶、用戶額度,凍結帳戶等。。。code
用戶認證用裝飾器
文件結構:
Atm
--bin ---logon.py ...登陸入口
--conf---initialize.py ...初始化商店商品
---goods.conf ...存儲商品信息
--core---admin.py ...管理員接口
---idcard.py ...ATM接口
---main.py . ...登陸門戶
---shopping.py ...購物商店
--db ---dbinfo.py ...讀寫用戶信息接口
---username.dir ...存儲用戶信息
---username.bak
---username.dat
--log ---record.py ...讀寫ATM操做日誌
---username.log ...ATM操做日誌
readme:
已存在用戶:zhuhuan,密碼123
管理員登陸:admin/admin
使用註冊註冊帳號,直接登陸使用已存在用戶,管理員帳號密碼只能在管理員的功能中使用
調用關係:
logon.py中的logo()調用main.py中的face()
face()調用admin.py中的admin();
idcard.py中的atm;
shopping中的shop()
admin()調用本文件內的build(新建帳號),write_off(註銷帳號),freeze(凍結帳號),unfreeze(解凍帳號),chance(修改額度)
atm() 調用本文件內的repay(還款),withdrawals(提現),transfer(轉帳),調用log中的record.py中的logs記錄操做日誌
shop() 調用idcard.py中的pay_bill()結帳
log中記錄ATM操做日誌
conf中記錄商店商品
db中記錄用戶信息
atm()中有裝飾器deco,用於判斷在調用atm時是否使用登陸接口登陸過.
流程圖:
bin 下的logon.py:
#!/usr/bin/env python # -*-coding:utf-8-*- # Author:zh import sys,os sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import core we=core.main.Welcome() #入口方法 def logo(): info = '''\033[36;1m--------Welcome-------- \t1.註冊 \t2.登錄\033[0m ''' print(info) recv = input("請輸入須要進行的操做序號-->").strip() if recv == "1": we.regis() we.login() if recv == "2": we.login() else: print("輸入錯誤") logo()
conf:初始化商城信息
#!/usr/bin/env python # -*-coding:utf-8-*- # _author_=zh import os path=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"conf" def initialize(): #初始化商店貨物 GOODS='''[["clothes",80],["pants",40],["Shoes",50],["watch",300],["bicycle",500]]''' if not os.path.exists("goods.conf"): with open(r"%s%s%s" % (path, os.sep,"goods.conf"),"w",encoding="utf-8") as files: files.write(GOODS)
core:主要內容:包含ATM接口,購物商城接口,管理員接口,主程序
主程序:
#!/usr/bin/env python # -*-coding:utf-8-*- # Author:zh import sys,os sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import log import db from core import idcard from core import shopping from core import admin class Welcome(object): name,pwd='','' def enter(self): name = input("請輸入用戶名:").strip().lower() pwd = input("請輸入密碼:").strip().lower() self.name=name self.pwd=pwd #登陸 def login(self): count=0 sign=True while sign: self.enter() if self.name=="q" or self.pwd=="q": exit() dict_l=db.dbinfo.file_r(self.name) if not dict_l: exit() count += 1 if count>3: print("錯誤次數過多,帳戶被凍結,請聯繫管理員") dict_l["user_sign"]=1 db.dbinfo.file_w(self.name, dict_l) sign = False if dict_l["name"]==self.name and dict_l["pwd"]==self.pwd: if dict_l["user_sign"]==0: print("Welcome,%s"%self.name) dict_l["logon_sign"]=1 db.dbinfo.file_w(self.name,dict_l) while True: face(dict_l) sign=False else: print("帳戶已被凍結") else: print("輸入錯誤,請從新輸入") #註冊 def regis(self): self.enter() dict_r={} dict_r["name"]=self.name dict_r["pwd"] = self.pwd dict_r["money"]=15000 #用戶狀態(1表示凍結,0正常) dict_r["user_sign"]=0 #用戶登陸狀態(1表示已登陸,0表示未登陸 dict_r["logon_sign"]=0 db.dbinfo.file_w(self.name,dict_r) print("\033[32;1m註冊成功!請登陸\033[0m") #登錄後的首界面 def face(dict_l): dict_info = {"1": shopping.shop, "2": idcard.atm, "3": admin.admin, "4": log.record.notes} info = '''\033[34;1m 1.購物商城 2.ATM 3.管理員 4.操做記錄 5.退出 \033[0m ''' print(info) num=input("請輸入須要進行的操做序號-->").strip() if num=="5": exit() try: dict_info[num](dict_l) except FileNotFoundError as e: print("\33[31;1m還未存在信用卡操做,沒有記錄\33[0m")
ATM接口:
#!/usr/bin/env python # -*-coding:utf-8-*- # Author:zh import db import log import core def deco(func): # 裝飾器:判斷用戶登陸是否使用的登陸接口登陸 def account(*args, **kwargs): user = args if user[0]["logon_sign"] == 1: func(*args, **kwargs) else: print("請從新登陸") we = core.main.Welcome() we.login() return account @deco def atm(dict_l): money = Money(dict_l) dict_info = {"1": money.repay, "2": money.withdrawals, "3": money.transfer} while True: info='''\033[32;1m 1.還款 2.提現 3.轉帳 4.查看信息 5.退出 6.返回上一層 \033[0m ''' print(info) num = input("請輸入須要進行的操做序號-->").strip() if num=="5": exit() elif num=="6": break elif num=="4": log.record.notes(dict_l) elif num in dict_info.keys(): dict_info[num]() else: print("輸入錯誤") class Money(object): # dict_l:傳入的登陸人信息 def __init__(self,dict_l): self.dict_l=dict_l self.info = db.dbinfo.file_r(self.dict_l["name"]) # 還款 def repay(self): arrears=15000-self.info["money"] print("name:%s,欠費:%s"%(self.info["name"],arrears)) num=input("請輸入還款金額:") if num.isdigit(): num=int(num) self.info["money"]=self.info["money"]+num db.dbinfo.file_w(self.info["name"],self.info) print("還款成功") infomation="還款,還款金額:%s,可用額度%s"%(num,self.info["money"]) log.record.logs(infomation,self.dict_l["name"]) else: print("輸入錯誤") # 提現 def withdrawals(self): print("可提現金額:%s"%self.info["money"]) num = input("請輸入提現金額:") if num.isdigit(): num=int(num) self.info["money"]=self.info["money"]-num-0.05*num db.dbinfo.file_w(self.info["name"],self.info) print("提現成功") infomation="提現,提現金額:%s,可用額度%s"%(num,self.info["money"]) log.record.logs(infomation,self.dict_l["name"]) else: print("輸入錯誤") # 轉帳 def transfer(self): print("可轉帳金額:%s"%self.info["money"]) name = input("請輸入轉帳用戶名稱:") num = input("請輸入轉帳金額:") info_other = db.dbinfo.file_r(name) if info_other: if num.isdigit(): num = int(num) self.info["money"]-=num info_other["money"]+=num db.dbinfo.file_w(self.info["name"], self.info) db.dbinfo.file_w(info_other["name"], info_other) print("轉帳成功") infomation = "轉帳,轉帳帳戶:%s,轉帳金額:%s,此卡可用額度%s" % (num,info_other["name"],info["money"]) log.record.logs(infomation, self.dict_l["name"]) else: print("輸入錯誤") # 支付,bill:傳入須要結帳的金額 def pay_bill(self,bill): if bill>self.dict_l["money"]: print("信用卡錢不夠") else: self.dict_l["money"]-=bill db.dbinfo.file_w(self.dict_l["name"],self.dict_l) infomation = "結帳,結帳金額:%s,可用額度%s" % (bill, self.dict_l["money"]) log.record.logs(infomation, self.dict_l["name"])
購物商城接口:
#!/usr/bin/env python # -*-coding:utf-8-*- # Author:zh import sys,os sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import conf from core import idcard path=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"conf" def show(): # 格式化輸出商品 conf.initialize.initialize() with open(r"%s%s%s" % (path, os.sep,"goods.conf"),"r",encoding="utf-8") as files: goods=files.read() goods=eval(goods) for i in goods: print("\033[32;1m%s.%s......%s\033[0m"%(goods.index(i)+1,i[0],i[1])) return goods #購物商城 def shop(dict_l): having=[] money = idcard.Money(dict_l) while True: snap=show() num=input("請輸入須要加入購物車的商品編號(s結帳):").strip() #傳給結帳接口的費用參數 bill=0 if num.isdigit(): num=int(num) if num in range(1,len(snap)+1): having.append(snap[num-1]) elif num=="s": for i in having: bill=bill+i[1] money.pay_bill(dict_l,bill) break elif num=="b": break elif num=="q": exit() else: print("輸入錯誤")
管理員接口:
#!/usr/bin/env python # -*-coding:utf-8-*- # _author_=zh import os import db from core import main #管理員接口 def admin(dict_l): account = Account() dict_info = {"1": account.build, "2": account.write_off, "3": account.freeze, "4": account.unfreeze, "5": account.chance} name = input("請輸入管理員帳號和密碼(name/pwd):") if name == "admin/admin": print("Welcome") while True: info = '''\033[32;1m 1.新建帳戶 2.註銷帳戶 3.凍結帳戶 4.解凍帳戶 5.修改額度 6.退出 7.返回上一層 \033[0m ''' print(info) num = input("請輸入須要進行的操做序號-->").strip() if num == "6": exit() elif num == "7": break elif num in dict_info.keys(): dict_info[num]() else: print("輸入錯誤") else: print("輸入錯誤") class Account(object): #新建帳戶 def build(self): name = input("請輸入用戶名:").strip().lower() pwd = input("請輸入密碼:").strip().lower() dict_r = {} dict_r["name"] =name dict_r["pwd"] =pwd dict_r["money"] = 15000 dict_r["user_sign"] = 0 db.dbinfo.file_w(name, dict_r) print("新建成功") #註銷帳戶 def write_off(self): name=input("請輸入須要註銷的帳號:") self.path_data=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"db"+os.sep+name self.path_log=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"log"+os.sep+name try: os.remove(self.path_data+".txt.dir") os.remove(self.path_data + ".txt.dat") os.remove(self.path_data + ".txt.bak") os.remove(self.path_log+".log") print("刪除成功") except FileNotFoundError as e: print(e) #凍結帳戶 def freeze(self): name=input("請輸入須要凍結的帳號:") info=db.dbinfo.file_r(name) info["user_sign"]=1 db.dbinfo.file_w(name,info) info = db.dbinfo.file_r(name) print("凍結成功!") #解凍帳戶 def unfreeze(self): name = input("請輸入須要解凍的帳號:") info=db.dbinfo.file_r(name) info["user_sign"]=0 db.dbinfo.file_w(name,info) print("解凍成功!") #修改額度 def chance(self): name = input("請輸入須要修改的帳號:") info = db.dbinfo.file_r(name) print("現有額度:%s"%info["money"]) num=input("請輸入須要修改的額度:") if num.isdigit(): num=int(num) info["money"]=num db.dbinfo.file_w(name, info) print("修改爲功!") else: print("輸入錯誤")
db:數據庫目錄,存儲用戶基本信息
dbinfo.py:寫入用戶信息,讀取用戶信息
#!/usr/bin/env python # -*-coding:utf-8-*- # Author:zh import shelve import os import bin path=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"db" #寫入文件,按用戶名稱存入 def file_w(name,dict): db=shelve.open(r"%s%s%s.txt"%(path,os.sep,name)) db[name]=dict #讀取文件內容 def file_r(name): if os.path.exists(r"%s%s%s.txt.dir" % (path, os.sep, name)): db = shelve.open(r"%s%s%s.txt" % (path, os.sep, name)) return db[name] else: print("\033[31;1m用戶名不存在!\033[0m") return None
log:記錄日誌信息
record.py:日誌記錄,讀取
#!/usr/bin/env python # -*-coding:utf-8-*- # _author_=zh import os import logging from logging import handlers path=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"log" #讀取日誌 def notes(dict_l): with open(r"%s%s%s.log"%(path,os.sep,dict_l["name"]),encoding="utf-8") as files: info=files.read() print(info) #記錄並在屏幕輸出日誌,infomation:日誌內容 def logs(infomation,name): logger=logging.getLogger(__name__) logger.setLevel(logging.DEBUG) #格式 f_formatter = logging.Formatter("%(asctime)s %(levelname)s:%(message)s") #h爲屏幕輸出的Handler fh爲日誌輸出的Handler ch=logging.StreamHandler() ch.setLevel(logging.DEBUG) ch.setFormatter(f_formatter) fh=handlers.TimedRotatingFileHandler(r"%s%s%s.log"%(path,os.sep,name),when="D",interval=1,backupCount=3,encoding="utf-8") fh.setLevel(logging.INFO) fh.setFormatter(f_formatter) logger.addHandler(ch) logger.addHandler(fh) logger.info(infomation)