模拟实现一个ATM + 购物商城程序
-
额度 15000或自定义
-
实现购物商城,买东西加入 购物车,调用信用卡接口结账
-
可以提现,手续费5%
-
每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
-
支持多账户登录
-
支持账户间转账
-
记录每月日常消费流水
-
提供还款接口
-
ATM记录操作日志
-
提供管理接口,包括添加账户、用户额度,冻结账户等。。。
-
用户认证用装饰器
# import time import datetime # time.time() # 当前时间戳 # datetime.datetime.now() # 本地之间 # 数据处理===================================== # 全部用户数据 user_data = [] # 加载数据到内存 def load_data(): f = open("DB/user_db.txt","rt",encoding="utf-8") for line in f: line = line.strip("\n") if line == "\n":continue ls = line.split("|") usr_dic = {"name":ls[0], "pwd":ls[1], "max": ls[2], "money": ls[3], "lock": ls[4]} user_data.append(usr_dic) f.close() # 根据账户名获取一个用户 def get_usr(name): for usr in user_data: if usr["name"] == name: return usr # 将内存中的数据持久存储到文件中 def save_to_file(): f = open("DB/user_db.txt","wt",encoding="utf-8") for usr in user_data: text = "|".join(usr.values()) text += "\n" f.write(text) f.close() # 数据处理===================================== # 登录验证装饰器(闭包函数) (再不改变源代码的调用方式基础上 为这个函数添加新功能) def login_auth(func): def wrapper(*args,**kwargs): # 验证是否登陆过了 if current_usr == None: print("请先登录!") atm_login() if current_usr: return func(*args,**kwargs) else: return func(*args,**kwargs) return wrapper # 购物中心======================================== # 商品信息 products = [{"name":"挨粪叉","price":6888}, {"name":"锤子TNT","price":10888}, {"name":"小米mix2","price":2888}] # 购物车 car = {} # 购物 def shopping(): while True: # 打印出所有商品信息 count = 1 for p in products: print("序号:%-3s 名称:%-10s 价格:%-6s" % (count,p["name"],p["price"])) count += 1 select = input("亲输入商品的序号q退出:\n") if select == "q": return if select.isdigit() and int(select) >= 1 and int(select) <= len(products): pd = products[int(select)-1] print("%s已成功加入购物车!" % pd["name"]) # 判断商品是否已经存在于购物车 if pd["name"] in car: car[pd["name"]]["count"] += 1 else: car[pd["name"]] = {"price":pd["price"],"count":1} else: print("输入有误请重新输入!") # 查看购物车 def show_cars(): if not car: s = input("你的购物车是空的! 你要买点什么吗? y/n") if s == "y": shopping() return else: return print("您的购物车信息:") for p in car: print("名称:%-10s 价格:%-8s 数量:%-3s 总价:%-10s" % (p, car[p]["price"], car[p]["count"], car[p]["price"] * car[p]["count"])) select = input("输入y调整商品数量!(数量为0则删除商品!) 输入其他退出!") if select == "y": modify_count() # 调整购物车中的商品数量 def modify_count(): while True: name = input("请输入商品名称q退出:\n") if name == "q": return if name not in car: print("输入不正确请重试!") continue while True: count = input("输入调整后数量:\n") if not count.isdigit(): print("数量不正确 必须是整数!") continue count = int(count) if count == 0: car.pop(name) print("%s已删除" % name) return else: car[name]["count"] = count print("修改成功!") return # 结算 @login_auth def pay_cars(): # 计算商品总价格 sum = 0 for p in car: sum += car[p]["price"] * car[p]["count"] print("您的订单总价为:%s元" % sum) if paymoney(sum): print("剁手成功! 回家等着吧!") clear_cars() # 清空购物车 def clear_cars(): car.clear() print("购物车已清空!") def shop_center(): shopfuncs = {"1":shopping,"2":show_cars,"3":pay_cars,"4":clear_cars} while True: print(""" 1.购物 2.查看购物车 3.结算 4.清空 q.退出""") index = input("请选择:\n").strip() if index == "q": return if index in shopfuncs: shopfuncs[index]() else: print("输入不正确!请重试!") # 购物中心======================================== # ATM==================================================== # 用于保存登录成功的用户信息 current_usr = None # 日志装饰器. # 日志文件 atmlog_file = open("DB/log.txt","at",encoding="utf-8") # 用户流水文件 moneyflow = None def atm_logger(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) # 记录日志 atmlog_file.write("[%s] user:%s function:%s\n" % (datetime.datetime.now(),current_usr["name"],func.__name__)) atmlog_file.flush() # 立即刷出缓存区的数据到硬盘 如果每次write都操作一次硬盘 # 效率非常低 所以python内置了缓冲区 只有当缓冲区满了才会写入硬盘 一次来降低硬盘操作次数 return wrapper # 登录 def atm_login(): while True: name = input("请输入账户名:(q退出)\n").strip() # 手动记录日志 因为用户还没有登陆 atmlog_file.write("[%s] user:%s function:%s\n" % (datetime.datetime.now(), name, atm_login.__name__)) atmlog_file.flush() if name == "q": return if not name: print("用户名不能为空!") continue usr = get_usr(name) if not usr: print("用户名不存在!") continue pwd = input("请输入密码:\n").strip() if not pwd: print("密码不能为空!") continue if name == usr["name"] and pwd == usr["pwd"]: print("登录成功") global current_usr,moneyflow # 打开流水文件 moneyflow = open("DB/%s.txt" % name,"at",encoding="utf-8") # 记录当前登录用户信息 current_usr = usr return else: print("账户名或密码不正确!请重试!") # 提现 @login_auth @atm_logger def withdraw(): while True: print("当前余额:%s元" % current_usr["money"]) money = input("请输入提款金额:(整数 q退出)\n") if money == "q":return if not money.isdigit(): print("输入有误!请重试!") continue money = int(money) # 手续费 opt = money * 0.05 print("需要手续费%s元" % opt) usr_moeny = float(current_usr["money"]) if money+opt > usr_moeny: print("余额不足!很尴尬") continue current_usr["money"] = str(usr_moeny - money - opt) save_to_file() print("请提取你的钞票!") moneyflow.write("[%s] 账户:%s 提现%s元 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], money, current_usr["money"])) moneyflow.flush() return # 转账 @login_auth @atm_logger def transfer(): while True: account = input("请输入对方的账户名:\n") to_usr = get_usr(account) if not to_usr: print("账户不存在 请重新输入!") continue print("当前余额:%s元" % current_usr["money"]) money = input("请输入转账金额:(整数 q退出)\n") if money == "q": return money = str_to_num(money) if not money: print("输入有误!请重试!") continue usr_moeny = float(current_usr["money"]) if money > usr_moeny: print("余额不足!很尴尬") continue # 原始账户减去 current_usr["money"] = str(usr_moeny - money) # 目标账户加上 to_usr["money"] = str(float(to_usr["money"]) + money) save_to_file() print("转账成功!") moneyflow.write("[%s] 账户:%s 转账%s元 给%s 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], money, account, current_usr["money"])) moneyflow.flush() return # 将字符串转成数字 "11212101.s" def str_to_num(text): if text.isdigit(): return int(text) if "." in text: ts = text.split(".") if len(ts) == 2: if ts[0].isdigit() and ts[1].isdigit(): return float(text) # 还款 @login_auth @atm_logger def repayment(): print("您当前欠款:%s" % (str_to_num(current_usr["max"]) - str_to_num(current_usr["money"]))) while True: print("repayment") money = input("请输入还款金额!q退出:\n") if money == "q":return money = str_to_num(money) if not money: print("输入有误 请重试!") continue current_usr["money"] = str(str_to_num(current_usr["money"]) + money) save_to_file() print("还款成功!") moneyflow.write("[%s] 账户:%s 还款%s元 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], money, current_usr["money"])) moneyflow.flush() return # 结算 需要传入订单总价格 @login_auth @atm_logger def paymoney(price): if price > str_to_num(current_usr["money"]): print("额度不足!又尴尬了") else: current_usr["money"] = str(str_to_num(current_usr["money"]) - price) save_to_file() print("结算成功!") moneyflow.write("[%s] 账户:%s 购物消费%s元 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], price, current_usr["money"])) moneyflow.flush() return True def atm(): atm_funcs = {"1": atm_login, "2": withdraw, "3": transfer, "4": repayment} while True: print(""" 1.登录 2.提现 3.转账 4.还款 (q.退出!)""") index = input("请选择:\n") if index == "q": # 清空当前用户信息 关闭流水文件 global current_usr if current_usr: current_usr = None moneyflow.close() return if index in atm_funcs: atm_funcs[index]() else: print("输入有误请重试!") # ATM==================================================== # 管理员接口============================================= # 显示所有的用户信息 并从中选择一个用户 def show_users_and_select(): while True: for usr in user_data: print("%-10s %-10s %-10s %-2s" % (usr["name"],usr["max"],usr["money"],usr["lock"])) select = input("请选择一个用户(输入用户名:q退出)\n") if select == "q": return for u in user_data: if select == u["name"]: return u else: print("输入不正确 请重新输入!") # 管理员登录 def admin_login(): while True: name = input("请输入管理员账户名:(q退出)\n").strip() if name == "q": return if not name: print("用户名不能为空!") continue pwd = input("请输入管理员密码:\n").strip() if not pwd: print("密码不能为空!") continue if name == "admin" and pwd == "123": print("登录成功") return True else: print("账户名或密码不正确!请重试!") #添加账户 def create_user(): while True: name = input("请输入账户名:(q退出)\n").strip() if name == "q": return if not name: print("用户名不能为空!") continue # 获取用户 通过账户名 usr = get_usr(name) if usr: print("用户名已经存在,请重试!") continue pwd = input("请输入密码:\n").strip() if not pwd: print("密码不能为空!") continue if pwd != input("请再次输入密码:").strip(): print("两次密码不相同请重试!") continue # 将用户输入的信息打包成字典 存到列表中 new_usr = {"name":name,"pwd":pwd,"max":"15000","money":"500","lock":"0"} user_data.append(new_usr) print("创建成功!") # 持久化存储...... save_to_file() return #调整额度 def modify_amount(): # 先选择一个用户 usr = show_users_and_select() if not usr: return while True: # 输入新的额度 new_max = input("请输入新的额度:(q退出)\n").strip() if new_max == "q": return if not new_max.isdigit(): print("输入不正确 请重新输入!") continue usr["max"] = new_max save_to_file() print("修改成功!") return #冻结账户 def lock_user(): # 先选择一个用户 usr = show_users_and_select() if not usr: print("取消操作!") return usr["lock"] = "1" save_to_file() print("冻结成功!") #解冻账户 def unlock_user(): # 先选择一个用户 usr = show_users_and_select() if not usr: print("取消操作!") return usr["lock"] = "0" save_to_file() print("解冻成功!") # 管理员接口界面 def admin_view(): # 调用登录功能验证是否有权限执行操作 if not admin_login(): return admin_funcs = {"1":create_user,"2":modify_amount,"3":lock_user,"4":unlock_user} while True: print(""" 1.添加账户 2.修改额度 3.冻结账户 4.解冻账户 (q.退出!)""") index = input("请选择:\n") if index == "q": return if index in admin_funcs: admin_funcs[index]() else: print("输入有误请重试!") # 管理员接口============================================= # 程序的入口函数 def run(): print("welcome to oldboy ATM system!") # 将函数装到字典中 用序号作为key 方便判断 funcs = {"1": shop_center, "2": atm, "3": admin_view} while True: print(""" 1.购物中心 2.ATM 3.管理员接口 (q.退出!)""") index = input("请选择:\n") if index == "q": print("下次再见!") return if index in funcs: funcs[index]() else: print("输入有误请重试!") # 启动系统 load_data() run() atmlog_file.close() # print(user_data) # print(str_to_num("100.s"))
# import time import datetime # time.time() # 当前时间戳 # datetime.datetime.now() # 本地之间 # 数据处理===================================== # 全部用户数据 user_data = [] # 加载数据到内存 def load_data(): f = open("DB/user_db.txt","rt",encoding="utf-8") for line in f: line = line.strip("\n") if line == "\n":continue ls = line.split("|") usr_dic = {"name":ls[0], "pwd":ls[1], "max": ls[2], "money": ls[3], "lock": ls[4]} user_data.append(usr_dic) f.close() # 根据账户名获取一个用户 def get_usr(name): for usr in user_data: if usr["name"] == name: return usr # 将内存中的数据持久存储到文件中 def save_to_file(): f = open("DB/user_db.txt","wt",encoding="utf-8") for usr in user_data: text = "|".join(usr.values()) text += "\n" f.write(text) f.close() # 数据处理===================================== # 登录验证装饰器(闭包函数) (再不改变源代码的调用方式基础上 为这个函数添加新功能) def login_auth(func): def wrapper(*args,**kwargs): # 验证是否登陆过了 if current_usr == None: print("请先登录!") atm_login() if current_usr: return func(*args,**kwargs) else: return func(*args,**kwargs) return wrapper # 购物中心======================================== # 商品信息 products = [{"name":"挨粪叉","price":6888}, {"name":"锤子TNT","price":10888}, {"name":"小米mix2","price":2888}] # 购物车 car = {} # 购物 def shopping(): while True: # 打印出所有商品信息 count = 1 for p in products: print("序号:%-3s 名称:%-10s 价格:%-6s" % (count,p["name"],p["price"])) count += 1 select = input("亲输入商品的序号q退出:\n") if select == "q": return if select.isdigit() and int(select) >= 1 and int(select) <= len(products): pd = products[int(select)-1] print("%s已成功加入购物车!" % pd["name"]) # 判断商品是否已经存在于购物车 if pd["name"] in car: car[pd["name"]]["count"] += 1 else: car[pd["name"]] = {"price":pd["price"],"count":1} else: print("输入有误请重新输入!") # 查看购物车 def show_cars(): if not car: s = input("你的购物车是空的! 你要买点什么吗? y/n") if s == "y": shopping() return else: return print("您的购物车信息:") for p in car: print("名称:%-10s 价格:%-8s 数量:%-3s 总价:%-10s" % (p, car[p]["price"], car[p]["count"], car[p]["price"] * car[p]["count"])) select = input("输入y调整商品数量!(数量为0则删除商品!) 输入其他退出!") if select == "y": modify_count() # 调整购物车中的商品数量 def modify_count(): while True: name = input("请输入商品名称q退出:\n") if name == "q": return if name not in car: print("输入不正确请重试!") continue while True: count = input("输入调整后数量:\n") if not count.isdigit(): print("数量不正确 必须是整数!") continue count = int(count) if count == 0: car.pop(name) print("%s已删除" % name) return else: car[name]["count"] = count print("修改成功!") return # 结算 @login_auth def pay_cars(): # 计算商品总价格 sum = 0 for p in car: sum += car[p]["price"] * car[p]["count"] print("您的订单总价为:%s元" % sum) if paymoney(sum): print("剁手成功! 回家等着吧!") clear_cars() # 清空购物车 def clear_cars(): car.clear() print("购物车已清空!") def shop_center(): shopfuncs = {"1":shopping,"2":show_cars,"3":pay_cars,"4":clear_cars} while True: print(""" 1.购物 2.查看购物车 3.结算 4.清空 q.退出""") index = input("请选择:\n").strip() if index == "q": return if index in shopfuncs: shopfuncs[index]() else: print("输入不正确!请重试!") # 购物中心======================================== # ATM==================================================== # 用于保存登录成功的用户信息 current_usr = None # 日志装饰器. # 日志文件 atmlog_file = open("DB/log.txt","at",encoding="utf-8") # 用户流水文件 moneyflow = None def atm_logger(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) # 记录日志 atmlog_file.write("[%s] user:%s function:%s\n" % (datetime.datetime.now(),current_usr["name"],func.__name__)) atmlog_file.flush() # 立即刷出缓存区的数据到硬盘 如果每次write都操作一次硬盘 # 效率非常低 所以python内置了缓冲区 只有当缓冲区满了才会写入硬盘 一次来降低硬盘操作次数 return wrapper # 登录 def atm_login(): while True: name = input("请输入账户名:(q退出)\n").strip() # 手动记录日志 因为用户还没有登陆 atmlog_file.write("[%s] user:%s function:%s\n" % (datetime.datetime.now(), name, atm_login.__name__)) atmlog_file.flush() if name == "q": return if not name: print("用户名不能为空!") continue usr = get_usr(name) if not usr: print("用户名不存在!") continue pwd = input("请输入密码:\n").strip() if not pwd: print("密码不能为空!") continue if name == usr["name"] and pwd == usr["pwd"]: print("登录成功") global current_usr,moneyflow # 打开流水文件 moneyflow = open("DB/%s.txt" % name,"at",encoding="utf-8") # 记录当前登录用户信息 current_usr = usr return else: print("账户名或密码不正确!请重试!") # 提现 @login_auth @atm_logger def withdraw(): while True: print("当前余额:%s元" % current_usr["money"]) money = input("请输入提款金额:(整数 q退出)\n") if money == "q":return if not money.isdigit(): print("输入有误!请重试!") continue money = int(money) # 手续费 opt = money * 0.05 print("需要手续费%s元" % opt) usr_moeny = float(current_usr["money"]) if money+opt > usr_moeny: print("余额不足!很尴尬") continue current_usr["money"] = str(usr_moeny - money - opt) save_to_file() print("请提取你的钞票!") moneyflow.write("[%s] 账户:%s 提现%s元 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], money, current_usr["money"])) moneyflow.flush() return # 转账 @login_auth @atm_logger def transfer(): while True: account = input("请输入对方的账户名:\n") to_usr = get_usr(account) if not to_usr: print("账户不存在 请重新输入!") continue print("当前余额:%s元" % current_usr["money"]) money = input("请输入转账金额:(整数 q退出)\n") if money == "q": return money = str_to_num(money) if not money: print("输入有误!请重试!") continue usr_moeny = float(current_usr["money"]) if money > usr_moeny: print("余额不足!很尴尬") continue # 原始账户减去 current_usr["money"] = str(usr_moeny - money) # 目标账户加上 to_usr["money"] = str(float(to_usr["money"]) + money) save_to_file() print("转账成功!") moneyflow.write("[%s] 账户:%s 转账%s元 给%s 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], money, account, current_usr["money"])) moneyflow.flush() return # 将字符串转成数字 "11212101.s" def str_to_num(text): if text.isdigit(): return int(text) if "." in text: ts = text.split(".") if len(ts) == 2: if ts[0].isdigit() and ts[1].isdigit(): return float(text) # 还款 @login_auth @atm_logger def repayment(): print("您当前欠款:%s" % (str_to_num(current_usr["max"]) - str_to_num(current_usr["money"]))) while True: print("repayment") money = input("请输入还款金额!q退出:\n") if money == "q":return money = str_to_num(money) if not money: print("输入有误 请重试!") continue current_usr["money"] = str(str_to_num(current_usr["money"]) + money) save_to_file() print("还款成功!") moneyflow.write("[%s] 账户:%s 还款%s元 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], money, current_usr["money"])) moneyflow.flush() return # 结算 需要传入订单总价格 @login_auth @atm_logger def paymoney(price): if price > str_to_num(current_usr["money"]): print("额度不足!又尴尬了") else: current_usr["money"] = str(str_to_num(current_usr["money"]) - price) save_to_file() print("结算成功!") moneyflow.write("[%s] 账户:%s 购物消费%s元 余额%s元\n" % (datetime.datetime.now(), current_usr["name"], price, current_usr["money"])) moneyflow.flush() return True def atm(): atm_funcs = {"1": atm_login, "2": withdraw, "3": transfer, "4": repayment} while True: print(""" 1.登录 2.提现 3.转账 4.还款 (q.退出!)""") index = input("请选择:\n") if index == "q": # 清空当前用户信息 关闭流水文件 global current_usr if current_usr: current_usr = None moneyflow.close() return if index in atm_funcs: atm_funcs[index]() else: print("输入有误请重试!") # ATM==================================================== # 管理员接口============================================= # 显示所有的用户信息 并从中选择一个用户 def show_users_and_select(): while True: for usr in user_data: print("%-10s %-10s %-10s %-2s" % (usr["name"],usr["max"],usr["money"],usr["lock"])) select = input("请选择一个用户(输入用户名:q退出)\n") if select == "q": return for u in user_data: if select == u["name"]: return u else: print("输入不正确 请重新输入!") # 管理员登录 def admin_login(): while True: name = input("请输入管理员账户名:(q退出)\n").strip() if name == "q": return if not name: print("用户名不能为空!") continue pwd = input("请输入管理员密码:\n").strip() if not pwd: print("密码不能为空!") continue if name == "admin" and pwd == "123": print("登录成功") return True else: print("账户名或密码不正确!请重试!") #添加账户 def create_user(): while True: name = input("请输入账户名:(q退出)\n").strip() if name == "q": return if not name: print("用户名不能为空!") continue # 获取用户 通过账户名 usr = get_usr(name) if usr: print("用户名已经存在,请重试!") continue pwd = input("请输入密码:\n").strip() if not pwd: print("密码不能为空!") continue if pwd != input("请再次输入密码:").strip(): print("两次密码不相同请重试!") continue # 将用户输入的信息打包成字典 存到列表中 new_usr = {"name":name,"pwd":pwd,"max":"15000","money":"500","lock":"0"} user_data.append(new_usr) print("创建成功!") # 持久化存储...... save_to_file() return #调整额度 def modify_amount(): # 先选择一个用户 usr = show_users_and_select() if not usr: return while True: # 输入新的额度 new_max = input("请输入新的额度:(q退出)\n").strip() if new_max == "q": return if not new_max.isdigit(): print("输入不正确 请重新输入!") continue usr["max"] = new_max save_to_file() print("修改成功!") return #冻结账户 def lock_user(): # 先选择一个用户 usr = show_users_and_select() if not usr: print("取消操作!") return usr["lock"] = "1" save_to_file() print("冻结成功!") #解冻账户 def unlock_user(): # 先选择一个用户 usr = show_users_and_select() if not usr: print("取消操作!") return usr["lock"] = "0" save_to_file() print("解冻成功!") # 管理员接口界面 def admin_view(): # 调用登录功能验证是否有权限执行操作 if not admin_login(): return admin_funcs = {"1":create_user,"2":modify_amount,"3":lock_user,"4":unlock_user} while True: print(""" 1.添加账户 2.修改额度 3.冻结账户 4.解冻账户 (q.退出!)""") index = input("请选择:\n") if index == "q": return if index in admin_funcs: admin_funcs[index]() else: print("输入有误请重试!") # 管理员接口============================================= # 程序的入口函数 def run(): print("welcome to oldboy ATM system!") # 将函数装到字典中 用序号作为key 方便判断 funcs = {"1": shop_center, "2": atm, "3": admin_view} while True: print(""" 1.购物中心 2.ATM 3.管理员接口 (q.退出!)""") index = input("请选择:\n") if index == "q": print("下次再见!") return if index in funcs: funcs[index]() else: print("输入有误请重试!") # 启动系统 load_data() run() atmlog_file.close() # print(user_data) # print(str_to_num("100.s")) # 只有程序时从当前文件开始运行时才进入if语句 # if __name__ == '__main__':
# 只有程序时从当前文件开始运行时才进入if语句 # if __name__ == '__main__':