作业要求
模拟实现一个ATM + 购物商城程序
- 额度 15000或自定义
- 实现购物商城,买东西加入 购物车,调用信用卡接口结账
- 可以提现,手续费5%
- 支持多账户登录
- 支持账户间转账
- 记录每月日常消费流水
- 提供还款接口
- ATM记录操作日志
- 提供管理接口,包括添加账户、用户额度,冻结账户等。。。
- 用户认证用装饰器
作业流程图
ATM_购物车程序目录
——————————————————————————————
作业中应注意的问题和解决方法
1.在创建用户文件的时候,要用json类型,这样可以避免用户信息修改的时候覆盖文件,导致其他的用户信息丢失。
2.程序的主入口py文件,在主目录的下一级,这样可以方面调用每一个模块之中的函数。
3.日志中的Formatter格式不要写死,可以在创建一个py文件,来进行调用。
4.用户名和密码进行判断的时候,可以通过用户名等同于文件名,进行判断。
5.创建setting文件的时候一定要不能随便更改其中的参数。
6.在对文件进行读取的时候,要利用os.path.dirname返回到前两级的目录,以及os.path.abspath获取到绝对路径,这样才可以打开用户文件。
7.在main.py的文件当中要尽量使用函数,这样可以减少代码的数量,增加可读性。
————————————————————————————————
manage.json
{"account":"manage","password":"1234","user":"manage"}
atm_start.py
#程序入口 if __name__ == '__main__': from atm import exchange exchange.user_exchange()
shopping.py
import json,os from tabulate import tabulate from atm.auth import userjudge from atm.logger import logger1 from conf.settings import user_path from atm.conroller_class import user_file shopping_list = [ ['1','Mac_pro','12000'] , ['2','iphone','8000'], ['3','Mi_mix','5000'] ] k = ["sum","goods","price"] print(tabulate(shopping_list, headers=k, tablefmt="grid")) print("\033[32;1mq:退出进入结账模式\033[0m") shopping_cart = [] #用户的购物列表 def payment(): """对结账用户进行认证, 成功后对用户的余额进行处理""" while True: username = input("Username:") password = input("Password:") f = userjudge(username,password) if f: money = [] for i in shopping_cart: i[2] = int(i[2]) money.append(i[2]) # 将商品价格 添加到列表当中 money_add = sum(money) # 商品总额 # print(f) f["balance"] = f["balance"] - money_add print("\033[31;1m-----支付成功-----\033[0m") logger1.debug("用户%s支付成功"%username) user_file(f,username) exit() else: print("\033[31;1m输入的用户名和密码错误\033[0m") while True: user_choise = input(">>:") if user_choise.isdigit(): user_choise = int(user_choise) if user_choise < len(shopping_list)+1 and user_choise >0: shopping_cart.append(shopping_list[user_choise-1]) # 将用户选择的商品 加入到proct中 # print(shopping_cart) print("您购买的\033[32;1m%s\033[0m已加入到购物车"%shopping_list[user_choise-1][1]) else: print("\033[31;1m请输入正确的商品编号\033[0m") elif user_choise == 'q': print("\033[31;1m------Shopping cart list-----\033[0m") print(tabulate(shopping_cart, headers=k, tablefmt="grid")) print("\033[31;1m------用户登陆-----\033[0m") payment() #调用结账函数 来进行支付 break
main.py
from conf.settings import main_path,user_path from .logger import logger,logger1 from .auth import userjudge from .conroller_class import * info = """ 1.查看用户信息 view_account_info 2.取现 with_draw 3.还款 pay_back 4.转账transfer """ def login(conroller): def entrance(): """ATM的交互入口""" user_entrance = { # 存储账户的认证状态,和账户信息 "user_status": False, 'data': None } while user_entrance["user_status"] is not True: # 如果用户没有认证则输入密码 account = input("Username:") password = input("Password:") user_file = userjudge(account, password)# 通过userjudge函数 来判断用户和密码是否正确 if user_file == None: print("\033[31;1m您输入用户或密码错误\033[0m") elif user_file["state"] == 1: if user_file: # 如果用户存在 user_entrance["user_status"] = True # 可以让认证后的用户,在user_entrance中体现出来 user_entrance['data'] = user_file # 将用户文件,添加到'data'当中 print("\033[31;1m--------------welcome--------------\033[0m") logger1.debug("用户%s登陆" % account) elif user_file["state"] == 0: #判断用户是否是锁定状态 print("\033[31;1m----用户被冻结----\033[0m") exit() else: conroller(account) #执行conroller函数 return entrance @login def conroller(account): """功能分发器""" print(info) #打印功能列表 while True: user_choise = input(">>(q退出):").strip() if user_choise.isdigit(): user_choise = int(user_choise) if user_choise == 1: # 信息查询 view_account_info(user_path,account) elif user_choise == 2:# 取现 with_draw(user_path,logger1,account) elif user_choise == 3:# 还款 pay_back(user_path,logger1,account) elif user_choise == 4:# 转账 transfer(user_path,logger1,account) elif user_choise == 'q': exit()
auth.py
from .db_handler import user_file_manage def userjudge(account,password): """对用户信息进行验证""" account_data = user_file_manage(account) # 通过user_file_manage来获取到账户账户信息 if account_data['status'] == 0: account_data = account_data['data'] if password == account_data['password']: return account_data else: return None else: return None
db_handler.py
import json,os import logging from conf.settings import main_path,user_path# 导入用户信息的上级目录 和绝对路径 def user_file_manage(account): """根据account 取处理用户文件""" # print(main_path) #E:\Moudule_1\ATM_project # print(user_path) #E:\Moudule_1\ATM_project\account f = os.path.join(user_path,"%s.json"%account)# 读取用户全部信息 if os.path.isfile(f): account_file = open(f) data = json.load(account_file) # print(data) account_file.close() return {'status':0,'data':data} else: return {'status':-1,'error':"账户不存在"}
setting.py
import os,sys import logging from logging import handlers main_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 获取程序的绝对路径 user_path = os.path.join(main_path,"account")# 指定目录和文件名 ATM_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %I:%M:%S') USER_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %I:%M:%S')
logger.py
import os import logging from logging import handlers from conf.settings import user_path,main_path,ATM_formatter,USER_formatter logger = logging.getLogger("atm") logger.setLevel(logging.DEBUG) fh_atm = logging.handlers.TimedRotatingFileHandler(filename=os.path.join(main_path,"log/atm.log"),encoding="utf-8") logger.addHandler(fh_atm) atm_formatter = ATM_formatter fh_atm.setFormatter(atm_formatter) logger1 = logging.getLogger("user") logger1.setLevel(logging.DEBUG) fh_user = logging.handlers.TimedRotatingFileHandler(filename=os.path.join(main_path,"log/user.log"),encoding="utf-8") logger1.addHandler(fh_user) user_formatter = USER_formatter fh_user.setFormatter(user_formatter)
exchange.py
from .auth import userjudge from .main import conroller from .atm_manage import manage_interface print("\033[31;1m-----1:进入管理员模式-----\033[0m") print("\033[31;1m-----2:ATM机操作模式------\033[0m") print("\033[32;1m管理员账号:manage,密码:1234\033[0m") def user_exchange(): """对管理员用户进行认证""" user_choise = input(">>:") while True: if user_choise == '1': print("\033[31;1m-----管理员模式-----\033[0m") username = input("\033[31;1mUsername:\033[0m") password = input("\033[31;1mPassword:\033[0m") manage_file = userjudge(username, password) # 获取到管理员文件中的内容 if manage_file: # print(manage_file) print("\033[32;1m-----欢迎登陆-----\033[0m") manage_interface() else: print("输入的用户名或者密码错误") elif user_choise == '2': conroller() # 进入到ATM操作模式 exit()
atm_manage.py
import os,json from conf.settings import user_path from atm.logger import logger from .db_handler import user_file_manage from .conroller_class import user_file info = """ 1.添加账户 2.用户额度 3.冻结账户 q(退出程序) """ def manage_interface(): """用于实现管理用户的接口""" while True: print(info) user_choise = input(">>:") if user_choise.isdigit(): user_choise = int(user_choise) if user_choise == 1: add_user() elif user_choise == 2: user_lines() elif user_choise == 3: user_lock() elif user_choise == 'q': exit() def add_user(): """添加用户""" username = input("username:") #用户名 == 文件名 password = input("password:") #密码 balance = input("balance:") #余额 lines = input("lines:") #额度 f = open(os.path.join(user_path, "%s.json"%username), 'w', encoding='utf-8') user_format ={"password":password,"balance":balance,"lines":lines,"state":1} json.dump(user_format,f) logger.debug("添加用户%s成功"%username) print("\033[32;1m----添加成功----\033[0m") def user_lines(): """改变用户额度""" username = input("username:") #文件名 userfile = user_file_manage(username) # 获取到文件内容 # print(user_file) if userfile['status'] == 0: #用户存在的话 new_lines = input("new_lines:")#额度 f = json.load(open(os.path.join(user_path, "%s.json"%username), 'r+', encoding='utf-8')) #读取用户信息 f['lines'] = new_lines logger.debug("更改用户%s额度成功" % username) print("\033[32;1m----用户额度更改成功----\033[0m") user_file(f,username) else: print("\033[32;1m用户名错误\033[0m") def user_lock(): """锁定用户,将用户状态 state:1 修改为 state:0""" print("\033[31;1m----输入想要冻结的用户----\033[0m") username = input("user:") f = json.load(open(os.path.join(user_path, "%s.json" % username), 'r+', encoding='utf-8')) # 读取用户信息 f['state'] = 0 logger.debug("冻结用户%s成功" % username) print("\033[31;1m----用户冻结成功----\033[0m") user_file(f,username)
conroller_class.py
import json,os from conf.settings import user_path info = """ 1.查看用户信息 view_account_info 2.取现 with_draw 3.还款 pay_back 4.转账transfer """ def user_file(user_data,account): """将修改后的用户信息 写入到对应文件当中 """ f = open(os.path.join(user_path, '%s.json'%account), 'w', encoding='utf-8') # f.seek(0) f.truncate() json.dump(user_data, f) f.close() def view_account_info(user_path,account): """查看用户信息""" user_data = json.load(open(os.path.join(user_path,"%s.json"%account),'r',encoding="utf-8"))#获取到用户信息 print("\033[32;1m用户余额:\033[0m",user_data["balance"]) print("\033[32;1m用户密码:\033[0m",user_data["password"]) def with_draw(user_path,logger1,account): """取现""" cash_money = int(input("Input your cash money:")) user_data = json.load(open(os.path.join(user_path,"%s.json"%account),'r',encoding="utf-8"))#获取到用户信息 if cash_money < int(user_data['lines']): user_data['balance'] = int(user_data['balance']) - cash_money * (1 - 0.05) print("\033[31;1m-------取现成功-------\033[0m") logger1.debug("用户%s取现金额%s"%(account,cash_money)) user_file(user_data,account) #通过user_file函数来 将用户信息写到文件当中 else: print("\033[32;1m提现金额超出信用额度!\033[0m") def pay_back(user_path,logger1,account): """还款""" refund_money = input("Input your refund money:") user_data = json.load(open(os.path.join(user_path,"%s.json"%account),'r',encoding="utf-8")) user_data['balance'] = int(user_data['balance']) + int(refund_money) print("\033[31;1m-------还款成功-------\033[0m") logger1.debug("用户%s还款金额%s"%(account,refund_money)) user_file(user_data,account) def transfer(user_path,logger1,account): """转账""" while True: transfer_user = input("Input accout(q退出):") #转账的用户 f = os.path.join(user_path,"%s.json"%transfer_user) if transfer_user == 'q': exit() if os.path.isfile(f): #判断文件是否存在 transfer_money = input("Input your transfer money:") user_data = json.load(open(os.path.join(user_path,"%s.json"%account),'r',encoding="utf-8")) #当前账户 transfer_user_file = json.load(open(f)) #取出转账用户的信息 transfer_user_file['balance'] = int(transfer_user_file['balance']) + int(transfer_money) user_file(transfer_user_file,transfer_user) #通过user_file函数来 将转账用户信息写到文件当中 print("\033[31;1m-------转账成功-------\033[0m") logger1.debug("用户%s给用户%s转账金额%s"%(account,transfer_user,transfer_money)) else: print("\033[31;1m输入的用户错误,请重新输入\033[0m")
atm.log
2018-03-14 10:34:02 - atm - DEBUG - 添加用户1成功
2018-03-14 10:34:11 - atm - DEBUG - 更改用户1额度成功
2018-03-14 10:34:16 - atm - DEBUG - 冻结用户1成功
2018-03-14 10:35:34 - atm - DEBUG - 更改用户1额度成功
user.log
2018-03-14 10:34:53 - user - DEBUG - 用户1234登陆
2018-03-14 10:34:59 - user - DEBUG - 用户1234取现金额100
2018-03-14 10:35:01 - user - DEBUG - 用户1234还款金额100
2018-03-14 10:35:07 - user - DEBUG - 用户1234给用户1转账金额10