程序要求
- 用户注册功能
- 用户登录功能
- 用户余额查询
- 转账,还款
- 查询历史记录
- 购物
- 购物车结账
conf 目录
import os
import logging.config
##########
# 功能字典#
##########
FUNC_MSG = {
'0': '注销',
'1': '登录',
'2': '注册',
'3': '查看余额',
'4': '转账',
'5': '还款',
'6': '取款',
'7': '查看流水',
'8': '购物',
'9': '购物车',
'q': '退出'
}
##################
# db/log文件夹路径#
##################
ATM_PATH = os.path.dirname(os.path.dirname(__file__))
DB_PATH = os.path.join(ATM_PATH, 'db')
LOG_PATH = os.path.join(ATM_PATH, 'log')
GOODS_INFO_PATH = os.path.join(DB_PATH, 'goods_info.xlsx')
##############
# logging配置#
##############
# 定义三种日志输出格式 开始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' # 其中name为getLogger()指定的名字;lineno为调用日志输出函数的语句所在的代码行
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
# 定义日志输出格式 结束
logfile_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # log文件的目录,需要自定义文件路径 # atm
logfile_dir = os.path.join(logfile_dir, 'log') # C:\Users\oldboy\Desktop\atm\log
logfile_name = 'log.log' # log文件名,需要自定义路径名
# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir): # C:\Users\oldboy\Desktop\atm\log
os.mkdir(logfile_dir)
# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name) # C:\Users\oldboy\Desktop\atm\log\log.log
# 定义日志路径 结束
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {}, # filter可以不定义
'handlers': {
# 打印到终端的日志
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
# 打印到文件的日志,收集info及以上的日志
'default': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'standard',
'filename': logfile_path, # 日志文件
'maxBytes': 1024 * 1024 * 5, # 日志大小 5M (*****)
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
# logging.getLogger(__name__)拿到的logger配置。如果''设置为固定值logger1,则下次导入必须设置成logging.getLogger('logger1')
'': {
# 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'handlers': ['default', 'console'],
'level': 'DEBUG',
'propagate': False, # 向上(更高level的logger)传递
},
},
}
core 目录
##########
# src.py #
##########
from lib import common
from interface import user, bank, store
logger = common.load_logging_config('user')
user_auth = {'username': None}
username = user_auth['username']
@common.login_auth
def logout():
username = None
user_auth['username'] = None
print(f"{username}已经注销")
logger.info(f"{username}已经注销")
def login():
print('欢迎来到登陆功能')
global username
count = 0
while count < 3:
login_username, pwd = common.input_username_pwd()
flag, msg, level = user.login_interface(login_username, pwd)
print(msg)
if flag:
user_auth['username'] = login_username
username = login_username
logger.info(f'{username}登录成功')
break
# 判断是否需要锁定
if level in [2, 3]:
user.locked_interface(login_username)
print('你的账户已经被锁定了')
break
count += 1
def register():
print('欢迎来到注册功能')
count = 0
while count < 3:
username, pwd = common.input_username_pwd()
flag, msg = user.register_interface(username, pwd)
# 判断是否注册成功
print(msg)
if flag:
logger.info(f'{username}注册成功')
break
count += 1
@common.login_auth
def check_extra():
print('欢迎来到查看余额功能')
extra = bank.check_extra_interface(username)
print(f'你的余额为{extra}')
logger.info(f'{username}查看余额,余额为{extra}')
return extra
@common.login_auth
def transfer():
print('欢迎来到转账功能')
from_username = username
to_username = input('请输入你需要转账的用户>>>')
flag = common.check_user(to_username)
if flag:
money = int(input('请输入你需要转账的金额'))
flag, msg = bank.transfer_interface(from_username, to_username, money)
print(msg)
if flag:
logger.info(f'{from_username}向{to_username}转了{money}')
print(f'{from_username}向{to_username}转了{money}')
else:
print('用户不存在')
@common.login_auth
def repay():
print('欢迎来到还款功能')
flag, msg = bank.repay_interface(username)
print(msg)
logger.info(f'{username}{msg}')
@common.login_auth
def withdraw():
print('欢迎来到取款功能')
money = int(input('取现多少钱>>>').strip())
flag, msg = bank.withdraw_interface(username, money)
print(msg)
if flag:
logger.info(f'{username}{msg}')
return
@common.login_auth
def history():
print('欢迎来到银行流水查看功能')
s = bank.history_interface(username)
print(f'流水为:\n{s}')
logger.info(f'{username}查看了流水')
@common.login_auth
def shopping():
print('欢迎来到购物功能')
msg = store.shopping_interface()
print(f'{username}{msg}')
logger.info(f'{username}{msg}')
@common.login_auth
def shopping_car():
print('欢迎来到购车车功能')
shopping_car_dict = store.shopping_car_dict
flag, msg = store.shopping_car_interface(shopping_car_dict, username)
print(msg)
if flag:
logger.info(f'{username}土豪{msg}')
def run():
FUNC_DICT = {
'0': logout,
'1': login,
'2': register,
'3': check_extra,
'4': transfer,
'5': repay,
'6': withdraw,
'7': history,
'8': shopping,
'9': shopping_car,
}
from conf.settings import FUNC_MSG
"""运行函数,进行功能选择"""
while True:
for k, v in FUNC_MSG.items():
print(f'{k}:{v}')
func_choice = input('请选择你需要的功能,按q退出').strip()
# 退出判断
if func_choice == 'q':
break
# 获取功能
func = FUNC_DICT.get(func_choice)
if not func:
print('傻逼,功能不存在')
continue
func()
if __name__ == '__main__':
run()
db目录
#################
# db_handler.py #
#################
interface 目录
###########
# bank.py #
###########
import os
from conf import settings
from db import db_handler
def check_extra_interface(username):
"""检查余额接口"""
data = db_handler.read_json(username)
return data['extra']
def transfer_interface(from_username, to_username, money):
from_username_data = db_handler.read_json(from_username)
to_username_data = db_handler.read_json(to_username)
if from_username_data['extra'] > money:
to_username_data['extra'] += money
from_username_data['extra'] -= money
db_handler.save_json(from_username, from_username_data)
db_handler.save_json(to_username, to_username_data)
return True, '转账成功'
return False, '转账失败'
def repay_interface(username):
username_data = db_handler.read_json(username)
extra = username_data['extra']
if extra >= 15000:
return True, '无需还款'
else:
username_data['extra'] = 15000
db_handler.save_json(username, username_data)
return True, f'还款{(15000-extra)*1.005}成功'
def withdraw_interface(username, money):
username_data = db_handler.read_json(username)
if username_data['extra'] > money:
username_data['extra'] -= money
db_handler.save_json(username, username_data)
return True, f'取现{money}成功'
return False, f'余额不足'
def history_interface(username):
filename = os.path.join(settings.LOG_PATH, 'log.log')
with open(filename, 'r', encoding='utf8') as fr:
s = ''
for i in fr:
if i.split('[')[-1].startswith(username):
s += i
return s
############
# store.py #
############
from db import db_handler
from conf import settings
from lib import common
shopping_car_dict = dict()
def read_goods_interface():
df = db_handler.read_excel(settings.GOODS_INFO_PATH)
return df
df = read_goods_interface()
def shopping_interface():
while True:
print(df)
common.goods_visualize(df)
# 打印商品信息
goods = df.columns
goods_choice = input('请选择你需要的商品,输入q退出>>>').strip()
if goods_choice == 'q':
break
if goods_choice in goods:
count_choice = input('请输入你需要购买的商品数量,输入q退出>>>').strip()
if count_choice == 'q':
break
count_choice = int(count_choice)
if int(df.loc['amount', goods_choice]) < count_choice:
print('傻逼,库存不足')
continue
else:
goods_price = int(df.loc['price', goods_choice])
if shopping_car_dict.get(goods_choice):
shopping_car_dict[goods_choice] += (count_choice * goods_price)
else:
shopping_car_dict[goods_choice] = (count_choice * goods_price)
print(f'已经把{goods_choice}*{count_choice}加入购物车')
df.loc['amount', goods_choice] -= count_choice
else:
print('傻逼,中文看不懂,英文也看不懂')
return f'已加入购物车{shopping_car_dict}'
def shopping_car_interface(shopping_car_dict, username):
goods_price = sum(shopping_car_dict.values())
username_data = db_handler.read_json(username)
if username_data['extra'] >= goods_price:
username_data['extra'] -= goods_price
username_data.update(shopping_car_dict)
db_handler.save_json(username, username_data)
new_shopping_car_dict = shopping_car_dict.copy()
shopping_car_dict.clear()
# 保存为excel文件
db_handler.save_excel(df, settings.GOODS_INFO_PATH)
return True, f'购物成功{new_shopping_car_dict}'
else:
shopping_car_dict.clear()
return False, '穷逼也购物'
if __name__ == '__main__':
read_goods_interface()
###########
# user.py #
###########
from lib import common
from db import db_handler
def register_interface(username, pwd):
"""注册接口"""
flag = common.check_user(username)
if flag:
return False, '用户已经存在'
else:
content = {'username': username, 'pwd': pwd, 'extra': 15000, 'locked': 0}
db_handler.save_json(username, content)
return True, '用户注册成功'
def login_interface(username, pwd):
# 判断用户是否存在
flag = common.check_user(username)
if not flag:
return False, '用户不存在', 1
# 判断用户是否锁定
data = db_handler.read_json(username)
if data['locked']:
return False, '用户已经锁定,去解锁', 2
# 判断密码
if pwd == data['pwd']:
return True, '登陆成功', 0
return False, '密码错误', 3
def locked_interface(username):
"""输入密码错误就锁"""
data = db_handler.read_json(username)
data['locked'] = 1
db_handler.save_json(username, data)
lib 目录
#############
# common.py #
#############
import os
import hashlib
import logging
import logging.config
from conf import settings
from interface import store
def login_auth(func):
from core import src
def wrapper(*args, **kwargs):
# 判断是否登陆
if not src.user_auth.get('username'):
src.login()
res = func(*args, **kwargs)
return res
res = func(*args, **kwargs)
return res
return wrapper
def load_logging_config(name):
logging.config.dictConfig(settings.LOGGING_DIC)
logger = logging.getLogger(name)
return logger
def check_user(username):
"""注册接口"""
username_filename = os.path.join(settings.DB_PATH, f'{username}.json')
if os.path.exists(username_filename):
return True
def input_username_pwd():
username = input('请输入你的用户名>>>').strip()
pwd = input('请输入你的密码>>>').strip()
# 密码加密
m = hashlib.md5()
m.update(pwd.encode('utf8'))
pwd = m.hexdigest()
return username, pwd
def goods_visualize(df):
"""想写就写"""
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname='D:\STXIHEI.TTF')
goods_columns = df.columns.to_list()
goods_price = df.loc['price', :].to_list()
price_index = list(range(len(goods_price)))
goods_amount = df.loc['amount', :].to_list()
amount_index = list(range(len(goods_amount)))
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax1.bar(price_index, goods_price,color='yellow')
ax1.set_title('价格表', fontproperties=font)
plt.xticks(amount_index, goods_columns, fontproperties=font, rotation=45)
for i in amount_index:
plt.text(amount_index[i],goods_price[i],s=goods_price[i])
ax2 = fig.add_subplot(122)
ax2.bar(amount_index, goods_amount,color='green')
ax2.set_title('数量表', fontproperties=font)
plt.xticks(amount_index,goods_columns,fontproperties=font,rotation=45)
for i in amount_index:
plt.text(amount_index[i],goods_amount[i],s=goods_amount[i])
plt.suptitle('商品信息表', fontproperties=font, fontsize=15, weight='bold')
plt.show()
if __name__ == '__main__':
# res = check_user('nick')
# print(res)
goods_visualize()
log目录
程序运行的目录
run主文件
##########
# run.py #
##########
from core import src
if __name__ == '__main__':
src.run()