模拟实现一个ATM + 购物商城程序
- 额度 15000或自定义
- 实现购物商城,买东西加入 购物车,调用信用卡接口结账
- 可以提现,手续费5%
- 支持多账户登录
- 支持账户间转账
- 记录每月日常消费流水
- 提供还款接口
- ATM记录操作日志
- 提供管理接口,包括添加账户、用户额度,冻结账户等。。。
- 用户认证用装饰器
Git:https://github.com/kris-2018/task
core__start.py
# -*- coding:utf-8 -*- #Author:Kris import sys,os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from core import main main.run()
core__auth.py
# -*- coding:utf-8 -*- #Author:Kris import os,sys import hashlib BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) def accse_login(user_data): #定义一个用户登录装饰器 def out_wrapper(func): #func接收 admin_info,shop_info,admin_info函数的返回值 def wrapper(*args,**kwargs): count = 0 if not user_data['is_authenticated'] and count < 3: print("\33[32;0m用户登录认证\33[0m".center(40, "-")) while count < 3: user = input('\033[32;1m请输入用户名>>>:\033[0m') db_path = BASE_DIR + r'\db\user_info' db_path_user = db_path + '\%s.json' % user if os.path.isfile(db_path_user): #判断用户文件是否存在 with open(db_path_user, 'r', encoding='utf-8') as fh: user_datas = eval(fh.read()) #将用户文件中内容转换为字典形式 pwd = input('\033[32;1m请输入用户密码>>>:\033[0m') m = hashlib.md5() m.update(pwd.encode()) if m.hexdigest() == user_datas['password'] : #if pwd == user_datas['password']: user_data['account_id'] = user_datas["cardid"] user_data['is_authenticated'] = True user_data['account_data'] = user_datas break else: print('\033[31;1m密码错误请重新输入\033[0m') else: count += 1 print('\033[31;1m该用户不存在,请重新输入还剩 %s 次机会\033[0m'% (3-count)) func(*args,**kwargs) return func return wrapper return out_wrapper
core__main.py
# -*- coding:utf-8 -*- #Author:Kris import sys,os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from core import auth from modules import creditcard from modules import shopping from modules import admincenter #用户数据信息 user_data = { 'account_id':None, #帐号ID 'is_authenticated':False, #是否认证 'account_data':None #帐号数据 } def run(): #定义一个主界面函数 while True: print('''\033[31;0m ----------欢迎来到ATM电子商务运行---------- 1.信用卡中心 2.购物中心 3.管理中心 4.退出\033[0m''') inputs = input('\033[34;1m请选择操作方式>>>:\033[0m').strip() dict = { '1':card_info, '2':shop_info, '3':admin_info } if inputs in dict.keys(): dict[inputs]() elif inputs == '4': exit('程序退出 欢迎下次使用') else: print('\033[31;1m请输入有效操作方式\033[0m') def admin_info(): #定义一个管理员权限用户主函数 auth_user() #调用用户认证接口 if user_data['account_data']['type'] == 1: while True: print('''\033[31;0m------------欢迎 %s 来到信用卡管理中心----------- 1.发行信用卡 2.冻结信用卡 3.解冻信用卡 4.提升信用卡额度 5.返回主菜单 6.退出\033[0m'''%user_data['account_data']["username"]) inputs = input('\033[35;1m请选择操作方式>>>:\033[0m').strip() menu_dic = { "1": admincenter.banks, "2": admincenter.freezing, "3": admincenter.defrosting, "4": admincenter.limit, } if inputs in menu_dic.keys(): menu_dic[inputs](user_data['account_data']) elif inputs == '5': break elif inputs == '6': exit('程序退出 欢迎下次使用') else: print('\033[31;1m请输入有效操作方式\033[0m') else: exit('对不起您的账号权限不足无法登录该模块') def shop_info(): #定义一个用户购物的主函数 auth_user() #调用用户认证接口 while True: print('''\033[31;0m---------------欢迎来到购物中心--------------- 1.购物商城 2.查看购物车 3.查看购物记录 4.返回主菜单 5.退出\033[0m''') menu_dic = { '1':shopping.shopping, '2':shopping.shop_car, '3':shopping.center } inputs = input('\033[35;1m请选择操作方式>>>:\033[0m').strip() if inputs in menu_dic.keys(): menu_dic[inputs](user_data['account_data']) elif inputs == '4': break elif inputs == '5': exit('程序退出 欢迎下次使用') else: print('\033[31;1m请输入有效操作方式\033[0m') def card_info(): #定义一个信用卡管理中心的主函数 auth_user() #调用用户认证接口 while True: print('''\033[31;0m ------------欢迎%s来到信用卡中心----------- 1.账户信息 2.存款 3.提现 4.转账 5.账单 6.返回主菜单 7.退出 \033[0m'''%user_data['account_data']["username"]) user_account = user_data['account_data'] inputs = input('\033[35;1m请选择操作方式>>>:\033[0m').strip() menu_dic = { "1": creditcard.account_info, "2": creditcard.repay, "3": creditcard.withdraw, "4": creditcard.transfer, "5": creditcard.paycheck, } if inputs in menu_dic.keys(): menu_dic[inputs](user_account) elif inputs == '6': break elif inputs == '7': exit('程序退出,欢迎下次使用') else: print('\033[31;1m请输入有效操作方式\033[0m') @auth.accse_login(user_data) #装饰器认证 def auth_user(): #调用 auth模块中的accse_login装饰器对用户进行登录认证 print('\033[32;1m用户 %s 登录认证成功\033[0m'% user_data['account_data']["username"])
db__shop_car(自动创建的xx_shopcar.txt)
db__user_info(json数据)
db__user_info_kris.json
{ "status":1, "expire_date": "2021-01-01", "credit":6000, "pay_day":22, "balance":15000, "enroll_date": "2018-01-01", "cardid":1112, "password": "202cb962ac59075b964b07152d234b70", "username": "kris", "type":1, "cardname":"招商银行-星耀" }
db__user_info_user1.json
{ "status": 0, "expire_date": "2021-01-01", "credit": 15000, "pay_day": 22, "balance": 15000, "enroll_date": "2018-01-01", "cardid": 1112, "password": "202cb962ac59075b964b07152d234b70", "username": "user1", "type": 0, "cardname":"工商银行" }
db__user_info_user2.json
{ "status": 0, "expire_date": "2021-01-01", "credit": 15000, "pay_day": 22, "balance": 15000, "enroll_date": "2018-01-01", "cardid": 1112, "password": "202cb962ac59075b964b07152d234b70", "username": "user2", "type": 0, "cardname":"中信银行" }
db product_list
IPhone 1299 IWatch 2999 IPad 2199 Tesla 50000 小米9 4000 Book 99
log card_log(xx_card.log)
log shop_log(xx_shop.log)
log loggers.py
# -*- coding:utf-8 -*- #Author:Kris import logging,sys,os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) def card_log(username,log): #定义一个信用卡日志函数 log_path = BASE_DIR+r'\log\card_log\%s_card.log'%username logger = logging.getLogger('Test_LOG') logger.setLevel(logging.INFO) fh = logging.FileHandler(log_path,encoding='utf-8') #将日志打印到log目录下的日志文件中 fh.setLevel(logging.INFO) fh_format = logging.Formatter('%(asctime)s %(message)s',datefmt='%m/%d/%Y %H:%M:%S') fh.setFormatter(fh_format) logger.addHandler(fh) logger.info(log) logger.removeHandler(fh) #避免打印重复日志 def shop_log(username,log): #定义一个购物日志函数 log_path = BASE_DIR + r'\log\shop_log\%s_shop.log' % username logger = logging.getLogger('Test_LOG') logger.setLevel(logging.INFO) fh = logging.FileHandler(log_path,encoding='utf-8') fh.setLevel(logging.INFO) fh_format = logging.Formatter('%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S') fh.setFormatter(fh_format) logger.addHandler(fh) logger.info(log) logger.removeHandler(fh)
module admincenter.py
# -*- coding:utf-8 -*- #Author:Kris import os,sys,logging BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) db_path = BASE_DIR + r'\db\user_info' def banks(account): #定义一个查询发行信用卡函数 print('\033[33;1m尊敬的用户您的发行信用卡是%s' '\n卡号为:%s,开户日期为:%s,信用卡有效期至:%s' '\n我们将会真挚的为您服务!!!' %(account['cardname'],account["cardid"],account["enroll_date"],account["expire_date"])) def freezing(account): #定义一个冻结信用卡函数 db_path_user = db_path+'\%s.json'%account['username'] with open(db_path_user,'r',encoding='utf-8') as fh: fr = fh.read() fd = eval(fr) if fd['status'] == 0: print('\033[31;1m当前信用卡已冻结\033[0m') if fd['status'] == 1: free = input('\033[33;1m当前信用卡未冻结,按任意键选择冻结 按b返回>>>\033[0m') if free != 'b': with open(db_path_user,'w',encoding='utf-8') as fw: res = fr.replace(str(fd["status"]),'0',1) fw.write(res) print('\033[31;1m当前信用卡已冻结\033[0m') def defrosting(account): #定义一个解冻函数 db_path_user = db_path + '\%s.json' % account['username'] with open(db_path_user, 'r', encoding='utf-8') as fh: fr = fh.read() fd = eval(fr) if fd['status'] == 1: print('\033[31;1m当前信用卡未冻结\033[0m') if fd['status'] == 0: free = input('\033[33;1m当前信用卡已冻结,按任意键选择解冻 按b返回>>>\033[0m') if free != 'b': with open(db_path_user, 'w', encoding='utf-8') as fw: res = fr.replace(str(fd["status"]), '0', 1) fw.write(res) print('\033[31;1m当前信用卡已解冻\033[0m') def limit(account): #定义一个提升信用额度函数 db_path_user = db_path + '\%s.json' % account['username'] with open(db_path_user, 'r', encoding='utf-8') as fh: fr = fh.read() fd = eval(fr) print('\033[33;1m尊敬的用户您当前信用额度是 %s元'%account["credit"]) limit = input('\033[34;1m是否选择提升信用额度 按任意键确认提示 按Q取消提升>>>') if limit.capitalize() != 'Q': while True: lines = input('\033[35;1m请输入提升信用额度>>>\033[0m') if lines.isdigit(): lines = int(lines) if lines <= 2000: limits = fd['credit'] + lines with open(db_path_user, 'w', encoding='utf-8') as fw: res = fr.replace(str(fd["credit"]), str(limits)) fw.write(res) print('\033[31;1m当前信用额度提升为:%s元 \033[0m'%limits) break else: print('\033[31;1m提升额度超出提升范围\033[0m') else: print('\033[31;1m请输入有效提升额度\033[0m')
modules creditcard.py
# -*- coding:utf-8 -*- #Author:Kris import os,sys,logging BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) db_path = BASE_DIR + r'\db\user_info' log_path = BASE_DIR+r'\log\card_log\%s_card.log' from log import loggers def account_info(user_account): #定义一个查看用户信息的函数 user_account = user_data['account_data'] 接收用户字典信息 db_path_user = db_path + '\%s.json' % user_account["username"] with open(db_path_user, 'r',encoding='utf-8') as fh: fd = eval(fh.read()) print("\033[33;1m我的账户信息:" "\n持卡人: %s " "\n卡号: %s" "\n存款: ¥%s" "\n可提现额度: ¥%s \033[0m" %(user_account["username"],user_account["cardid"],fd["balance"],fd["credit"])) inputs = input('\033[33;1m按任意键返回上一级菜单>>>:\033[0m') def repay(user_account): #定义一个用户存款函数 db_path_user = db_path + '\%s.json' % user_account["username"] with open(db_path_user, 'r',encoding='utf-8') as fh: fr = fh.read() fd = eval(fr) print("\033[33;1m您的当前存款为: ¥%s "% fd["balance"]) while True: repays = input('\033[33;1m请输入存款金额并确认存款,按Q取消存款>>>\033[0m') if repays.capitalize() == 'Q' : exit() else: if repays.isdigit(): repays = int(repays) user_balance = fd["balance"] + repays #当前存款=原存款+存款金额 with open(db_path_user,'w',encoding='utf-8') as fh: res = fr.replace(str(fd["balance"]),str(user_balance)) #修改用户文件操作 fh.write(res) print('\033[33;1m尊敬的用户已为您成功存入 %s 元,您当前存款金额为 %s 元!\033[0m' %(repays,user_balance)) break else: print('\033[31;1m请输入有效存款金额\033[0m') log = ('\033[31;1m尊敬的用户已为您成功存入: %s元,您当前存款金额: %s元!\033[0m' % (repays, user_balance)) loggers.card_log(user_account["username"], log) def withdraw(user_account): #定义一个用户提现函数 db_path_user = db_path + '\%s.json' % user_account["username"] with open(db_path_user, 'r',encoding='utf-8') as fh: fr = fh.read() fd = eval(fr) print("\033[33;1m您的当前存款为: ¥%s" % fd["balance"]) print("\033[33;1m您可提现额度为: ¥%s" % fd["credit"]) while True: repays = input('\033[33;1m请输入提现金额,按Q取消提现>>>\033[0m') if repays.capitalize() == 'Q': #判断用户输入 break else: if repays.isdigit(): repays = int(repays) if repays > fd["credit"]: #判断用户输入的提现金额是否大于现有存款 print('\033[31;1m提现金额不得大于可提现额度\033[0m') else: print('\033[31;1m提现金额: ¥%s 手续费:¥%s \033[0m'%(repays,repays*0.05)) user_balance = fd["balance"] - (repays + repays * 0.05) #提现后的用户余额 inputs = input('\033[33;1m请确认提现金额,按任意键提现>>>\033[0m') if user_balance <= 0: #判断结算后存款是否为负数,如结算后存款为负给出提示不让提现 print('\033[31;1m当前存款不足以提现\033[0m') else: user_credit = user_account["credit"] - repays #提现后的可提现额度 print('\033[31;1m尊敬的用户您已成功提现 %s 元!\033[0m'% repays) print("\033[33;1m您的当前存款为: ¥%s" % user_balance) print("\033[33;1m您可提现额度为: ¥%s" % user_credit) with open(db_path_user, 'w',encoding='utf-8') as fh: res1 = fr.replace(str(fd["balance"]), str(user_balance)) #先扣除用户的余额 res2 = res1.replace(str(fd["credit"]), str(user_credit)) #然后扣除用户的可提现额度 fh.write(res2) #将变更后的余额和提现额度重新写入json文本中 break else: print('\033[31;1m请输入有效提现金额\033[0m') log = ("\033[31;1m尊敬的用户您已成功提现: %s元 所剩存款: %s元 可提现金额为: %s元!\033[0m" % (repays, user_balance, user_credit)) #打印日志内容 loggers.card_log(user_account["username"], log) #传递参数给card_log日志主函数 def transfer(user_account): #定义一个用户转账的函数 count = 0 while count < 3: transfer = input('\033[33;1m请输入需转账人用户名>>>\033[0m') db_path_user1 = db_path + '\%s.json' % transfer #需被转账用户 db_path_user2 = db_path + '\%s.json' % user_account["username"] #当前用户 if transfer == user_account["username"]: print('\033[31;1m转账人不能是自己\033[0m') else: if os.path.isfile(db_path_user1): # 判断用户文件是否存在 with open(db_path_user1, 'r',encoding='utf-8') as fh: frh = fh.read() fd = eval(frh) #需被转账用户 with open(db_path_user2,'r',encoding='utf-8') as fw: frw = fw.read() fc = eval(frw) #当前用户 print('\033[33;1m转账用户信用卡号为:\033[0m \033[32;1m %s \033[0m'%fd["cardid"]) while True: money = input('\033[33;1m请输入需转账金额:\033[0m') if money.isdigit(): money = int(money) if money > fc["balance"]: #判断转账金额是否大于存款 print('\033[31;1m对不起您的存款不足,无法转账\033[0m') else: print('\033[31;1m转账用户卡号: %s 转账金额:¥%s\033[0m' % (fd["cardid"],money)) inputs = input('\033[33;1m请再次确认转账信息数据:按Q|q取消>>>\033[0m') if inputs.capitalize() == 'Q': break else: user_balance1 = fc["balance"] - money #当前用户转账后余额 with open(db_path_user2,'w',encoding='utf-8') as fw: res1 = frw.replace(str(fc["balance"]),str(user_balance1)) fw.write(res1) print('\033[33;1m您转账后存款为: ¥%s '%user_balance1) user_balance2 = fd["balance"] + money #需被转账用户转账后余额 with open(db_path_user1,'w',encoding='utf-8') as fh: res2 = frh.replace(str(fd["balance"]), str(user_balance2)) fh.write(res2) log = ('\033[31;1m您为卡号:%s 用户转账: %s元 您当前存款金额: %s元!\033[0m' % (fd["cardid"], money, user_balance1)) loggers.card_log(user_account["username"], log) break else: print('\033[31;1m请输入有效转账金额\033[0m') else: count += 1 print('\033[31;1m该用户不存在,请重新输入还剩 %s 次机会\033[0m' % (3 - count)) break def paycheck(user_account): if not os.path.isfile(log_path % user_account["username"]): print('\033[31;1m当前用户无流水记录\033[0m') else: with open(log_path % user_account["username"], 'r', encoding='utf-8') as fh: for line in fh: print(line)
modules shopping.py
# -*- coding:utf-8 -*- #Author:Kris import os,sys,logging BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) shop_path = BASE_DIR+r'\db\product_list' shop_car_path = BASE_DIR+r'\db\shop_car' #shop_car_paths = shop_car_path + '\%s_shopcar.txt %user_account["username"]' db_path = BASE_DIR + r'\db\user_info' log_path = BASE_DIR+r'\log\shop_log\%s_shop.log %user_account["username"]' from core import main from log import loggers def shopping(user_account): #定义一个购物商城函数 shopcar_list,pro_list = [],[] #shopcar_list:购物车列表 pro_list:商品清单列表 with open(shop_path,'r',encoding='utf-8') as fh: for item in fh: pro_list.append(item.strip('\n').split()) def shop_info(): print("\t编号\t\t\t商品\t\t\t价格") for index,item in enumerate(pro_list): print('\t %s\t\t\t%s\t\t%s'%(index,item[0],item[1])) while True: print(("\033[32;0m目前商城在售的商品信息\033[0m").center(40, "-")) shop_info() choice_id = input("\n\33[34;0m选择要购买的商品编号ID /【返回输入b】\33[0m:") if choice_id.isdigit(): choice_id = int(choice_id) if choice_id < len(pro_list) and choice_id >= 0: #判断用户选择商品编号是否大于商品清单列表最大值 pro_item = pro_list[choice_id] #定义一个 pro_item 变量存储 用户选择的商品 信息和价格 num = input('\033[34;1m选择商品数量>>>\033[0m') if num.isdigit(): num = int(num) if num > 0: print("\33[31;0m商品 %s 加入购物车 价格%s 数量%s\33[0m" % (pro_item[0], pro_item[1],num)) shopcar_list.append(pro_item) shop_car_paths = shop_car_path+'\%s_shopcar.txt'%user_account['username'] with open(shop_car_paths,'a',encoding='utf-8') as fc: fc.write(str('%s\t%s\t%s')%(pro_item[0],pro_item[1],num) +'\n') else: print('\033[31;1m购买数量不得为0\033[0m') else: print('\033[31;1m请输入有效购买数量\033[0m') else: print("\33[31;0m错误:没有相应的编号 请重新输入:\33[0m\n") elif choice_id == "b": main.shop_info() else: print("\33[31;0m错误:没有相应的编号 请重新输入:\33[0m\n") def shop_car(user_account): #定义一个购物车函数 money_list,product_list= [],[] product_info = '' shop_car_paths = shop_car_path + '\%s_shopcar.txt' % user_account['username'] if not os.path.isfile(shop_car_paths): print('\033[31;1m您还未有购物记录,请先进入商城购物\033[0m') shopping(user_account) else: with open(shop_car_paths,'r',encoding='utf-8')as fc: print(('\033[32;1m购物车清单\033[0m').center(32, '-')) print("编号\t\t商品\t\t价格\t\t数量") lock_list = fc.readlines() for index ,lock_info in enumerate(lock_list): lock = lock_info.split() product_name = lock[0] money = lock[1] num = lock[2] print('%s\t\t%s\t%s\t\t%s'%(index,product_name,money,num)) moneys = int(money)*int(num) #定义moneys变量来计算 单个商品总金额 = 商品金额*数量 product_info = '%s商品%s件'%(product_name,num) #定义打印商品名称及数量 字符串 money_list.append(moneys) #将单个商品总金额 添加至 金额列表中 product_list.append(product_info) #将product_info添加至 购物信息列表中 if sum(money_list) == 0 : # sum(money_list) = 购物车所有商品总金额 print('\033[31;1m购物车空空如也\033[0m') else: db_path_user = db_path + '\%s.json' % user_account["username"] with open(db_path_user, 'r',encoding='utf-8') as fh: fr = fh.read() fd = eval(fr) print('\n\33[33;0m您当前余额为 %s 元,当前商品金额为 %s 元'%(fd['balance'],sum(money_list))) go_shop = input("\n\33[34;0m是否选择购买 " "任意键:购买 /【返回输入b】\33[0m:") #使用sum方法求出购物车商品总支付金额 if go_shop == 'b': main.shop_info() else: if sum(money_list) < fd["balance"]: #判断用户余额买得起购物商品 balance = fd["balance"] - sum(money_list) # 当前余额 = 原余额-商品总额 log = ('\033[31;1m尊敬的用户您已成功购物 %s ,购物总额为 %s 元,您购物后余额: %s元!\033[0m' %(str(product_list),sum(money_list),balance)) loggers.shop_log(user_account['username'],log) # 调用购物日志打印函数 print("\033[33;1m购物成功!余额为: ¥%s\033[0m" % balance) with open(db_path_user,'w',encoding='utf-8') as fh: res = fr.replace(str(fd["balance"]), str(balance)) # 修改用户文件操作 fh.write(res) shop_car_paths = shop_car_path + '\%s_shopcar.txt %user_account["username"]' with open(shop_car_paths,'w',encoding='utf-8') as fc: #fc.seek(0) fc.truncate(0) #购物支付完成后 购物车文件清空 else: print("\33[31;0m对不起您的余额不足无法购买:\33[0m\n") main.shop_info() def center(user_account): #定义一个查看购物记录的函数 if not os.path.isfile(log_path % user_account["username"]): print('\033[31;1m当前用户无流水记录\033[0m') else: with open(log_path % user_account["username"], 'r', encoding='utf-8') as fh: for line in fh: print(line) main.shop_info()
README
模拟实现一个ATM + 购物商城程序 1.额度 15000或自定义 2.实现购物商城,买东西加入购物车,调用信用卡接口结账 3.可以提现,手续费5% 4.支持多账户登录 5.支持账户间转账 6.记录每月日常消费流水 7.提供还款接口 8.ATM记录操作日志 9.提供管理接口,包括添加账户、用户额度,冻结账户等。。。 10.用户认证用装饰器 说明: 1.管理员的账号:kris 密码:123 2.普通账号:user1 / user2 / 密码:123 程序运行入口是:bin文件夹下的start.py 结构见流程图
来源:http://www.cnblogs.com/shengyang17/p/8689913.html