一 基本需求
模拟实现一个ATM + 购物商城程序
额度 15000或自定义
实现购物商城,买东西加入 购物车,调用信用卡接口结账
可以提现,手续费5%
支持多账户登录
支持账户间转账
记录日常消费流水
提供还款接口
ATM记录操作日志
提供管理接口,包括添加账户、冻结账户等。。。
用户认证用装饰器
根据上面需求,我们来实现以下几个功能:
1 注册 2 登录 3 查看余额 4 转账 5 取款 6 还款 7 查看流水 8 购物 9 查看购买商品
二 项目目录结构
bin目录
start.py---》程序启动页
conf目录
setting.py---》用于存放整个项目的配置信息
core目录
src.py---》用户端功能
interface目录
bank.py---》银行相关接口
shop.py---》购物相关接口
user.py---》用户相关接口
db目录
db_handler.py---》对文件的读写操作
用于存放所有用户信息,以json格式存储
lib目录
common.py---》公共方法(用户认证装饰器,获取日志对象等)
log目录
记录日志
三 分模块
start.py
import os,sys
path = os.path.dirname(__file__)
# print(path)
sys.path.append(path)
from core import src
# print(path)
if __name__ == '__main__':
src.run()
View Code
src.py
from interface import bank,shop,user
from lib import common
user_dic = {
'name':None
}
def register():
if user_dic['name']:
print('已经登录,不能注册')
return
print('注册')
while True:
name = input('请输入名字:').strip()
password = input('请输入密码:').strip()
conf_password = input('请确认密码:').strip()
if password == conf_password:
flag,msg = user.register_interface(name,password)
if flag:
print(msg)
break
else:
print(msg)
else:
print('两次输入的密码不一致')
def login():
if user_dic['name']:
print('已经登录')
return
print('登录')
while True:
name = input('请输入名字:').strip()
password = input('请输入密码:').strip()
flag,msg = user.login_interface(name,password)
if flag:
user_dic['name']=name
print(msg)
break
else:
print(msg)
@common.login_auth
def check_balance():
print('查看余额')
balance = bank.check_balance_interface(user_dic['name'])
print(balance)
@common.login_auth
def transfer():
print('转账')
while True:
to_user = input('请输入对方账户:').strip()
account = input('请输入转账金额:').strip()
if account.isdigit():
account = int(account)
flag,msg = bank.transfer_interface(user_dic['name'],to_user,account)
if flag:
print(msg)
break
else:
print(msg)
else:
print('请输入数字')
@common.login_auth
def repay():
print('还款')
while True:
account = input('请输入还款金额:').strip()
if account.isdigit():
account = int(account)
flag,msg = bank.repay_interface(user_dic['name'],account)
if flag:
print(msg)
break
else:
print(msg)
else:
print('请输入数字')
@common.login_auth
def withdraw():
print('取款')
while True:
account = input('请输入取款金额:').strip()
if account.isdigit():
account = int(account)
flag,msg = bank.withdraw_interface(user_dic['name'],account)
if flag:
print(msg)
break
else:
print(msg)
else:
print('请输入数字')
@common.login_auth
def check_records():
print('查看流水')
records = bank.check_records_interface(user_dic['name'])
if records:
for record in records:
print(record)
else:
print('暂无流水')
@common.login_auth
def shopping():
print('购物')
goods_list = [
['coffee',10],
['chicker',20],
['car',100000]
]
user_balance = bank.check_balance_interface(user_dic['name'])
cost = 0
shoppingcard = {
}
while True:
for i,goods in enumerate(goods_list):
print('%s : %s'%(i,goods))
buy = input('请输入要购买的数字(数字)(q退出并购买):').strip()
if buy.isdigit():
buy = int(buy)
if buy < len(goods_list):
goods_name = goods_list[buy][0]
goods_price = goods_list[buy][1]
if user_balance >= goods_price:
if goods_name not in shoppingcard:
shoppingcard[goods_name] = {'price':goods_price,'count':1}
else:
# shoppingcard[goods_name] += 1
shoppingcard[goods_name]['count'] += 1
user_balance -= goods_price
cost += goods_price
print('%s 添加购物车成功' %goods_name)
else:
print('余额不足')
else:
print('请选择存在的商品')
elif buy == 'q':
if shoppingcard:
flag,msg = shop.shopping_interface(user_dic['name'],cost,shoppingcard)
if flag:
print(msg)
break
else:
print(msg)
break
else:
print('请输入数字')
@common.login_auth
def check_shoppingcard():
print('查看购物车')
shoppingcart = shop.check_shopingcart_interface(user_dic['name'])
if shoppingcart:
print(shoppingcart)
else:
print('购物车为空')
func_dic = {
'1': register,
'2': login,
'3': check_balance,
'4': transfer,
'5': repay,
'6': withdraw,
'7': check_records,
'8': shopping,
'9': check_shoppingcard
}
def run():
while True:
print('''
1 注册
2 登录
3 查看余额
4 转账
5 还款
6 取款
7 查看流水
8 购物
9 查看购买商品
''')
choice = input('请选择:')
if choice not in func_dic:continue
func_dic[choice]()
View Code
user.py
from db import db_handler
def register_interface(name,password,balance=1500):
user_dic = db_handler.select(name)
if user_dic:
return False,'用户已存在'
else:
user_dic = {
'name': name,
'password': password,
'lockd': False,
'balance': balance,
'credit': balance,
'bankflow': [],
'shoppingcard': {}
}
db_handler.save(user_dic)
return True,'注册成功'
def login_interface(name,password):
user_dic = db_handler.select(name)
if user_dic:
if password == user_dic['password']:
return True,'登录成功'
else:
return False,'密码错误或者已经锁定'
else:
return False,'用户不存在'
View Code
shop.py
from db import db_handler
from interface import bank
def check_shopingcart_interface(name):
user_dic = db_handler.select(name)
return user_dic['shoppingcard']
def shopping_interface(name,cost,shoppingcard):
flag = bank.consume_interface(name,cost)
if flag:
user_dic = db_handler.select(name)
user_dic['shoppingcard'] = shoppingcard
db_handler.save(user_dic)
return True,'购买成功'
else:
return False,'购买失败'
View Code
bank.py
import db.db_handler
from db import db_handler
from lib import common
bank_logger = common.get_logger('bank')
def check_balance_interface(name):
user_dic = db_handler.select(name)
return user_dic['balance']
def transfer_interface(from_name,to_name,account):
to_user_dic = db_handler.select(to_name)
if to_user_dic:
from_user_dic = db.db_handler.select(from_name)
if from_user_dic['balance'] >= account:
from_user_dic['balance'] -= account
to_user_dic['balance'] += account
from_user_dic['bankflow'].append('%s 向 %s 转账 %s'%(from_name,to_name,account))
to_user_dic['bankflow'].append('%s 收到 %s 转账 %s'%(to_name,from_name,account))
db_handler.save(from_user_dic)
db_handler.save(to_user_dic)
return True,'转账成功'
else:
return False,'您的额度不够'
else:
return False,'对方账户不存在'
def repay_interface(name,account):
user_dic = db_handler.select(name)
user_dic['balance'] += account
user_dic['bankflow'].append('还款 %s' %(account))
db_handler.save(user_dic)
bank_logger.info('还款成功')
return True,'还款成功'
def withdraw_interface(name,account):
user_dic = db_handler.select(name)
account = account*1.05
if user_dic['balance'] >= account:
user_dic['balance'] -= account
user_dic['bankflow'].append('取款 %s' % (account))
db_handler.save(user_dic)
return True,'取款成功'
else:
return False,'余额不足'
def check_records_interface(name):
user_dic = db_handler.select(name)
return user_dic['bankflow']
def consume_interface(name,account):
user_dic = db_handler.select(name)
if user_dic['balance'] >= account:
user_dic['balance'] -= account
user_dic['bankflow'].append('消费 %s' % (account))
db_handler.save(user_dic)
return True
else:
return False
View Code
db_handler.py
import os
from conf import setting
import json
def select(name):
path = os.path.join(setting.base_db, '%s,json' %name)
if os.path.exists(path):
with open(path,'r',encoding='utf-8') as f:
return json.load(f)
else:
return None
def save(user_dic):
path = os.path.join(setting.base_db,'%s,json'%user_dic['name'])
with open(path,'w',encoding='utf-8') as f:
json.dump(user_dic,f)
f.flush()
View Code
common.py
import logging.config
from conf import setting
def login_auth(func):
from core import src
def wrapper(*args,**kwargs):
if not src.user_dic['name']:
src.login()
else:
return func(*args,**kwargs)
return wrapper
def get_logger(name):
logging.config.dictConfig(setting.LOGGING_DIC)
my_logger = logging.getLogger(name)
return my_logger
View Code
setting.py
import os
base_dir = os.path.dirname(os.path.dirname(__file__))
base_db = os.path.join(base_dir,'db')
base_log = os.path.join(base_dir,'log')
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' # 其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
# 定义日志输出格式 结束
# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(base_log):
os.mkdir(base_log)
# log文件的全路径
logfile_path = os.path.join(base_log, 'log.log')
logfile_another = os.path.join(base_log, 'another.log')
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {},
'handlers': {
# 打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
# 打印到文件的日志,收集info及以上的日志
'default': {
'level': 'DEBUG',
'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配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'INFO',
'propagate': True, # 向上(更高level的logger)传递
},
},
}
View Code
发表评论