ATM+
ATM:模拟实现一个ATM + 购物商城程序
额度 15000或自定义
实现购物商城,买东西加入 购物车,调用信用卡接口结账
可以提现,手续费5%
支持多账户登录
支持账户间转账
记录每月日常消费流水
提供还款接口
ATM记录操作日志
提供管理接口,包括添加账户、用户额度,冻结账户等。。。
用户认证用装饰器
文件结构:
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)