ATM+购物车项目
构架思路
首先根据需求总结出功能,
所有功能通过三层来实现:
第一层:
用户交互层(core文件名是核心层,在crs.py内)
:实现用户的输入输出,与结果返回显示
第二层:
接口层(进行逻辑判断,放在interface文件内通常,通常对各个功能进行分类)——最核心
:对用户交互层传输的数据,同数据层数据进行逻辑判断处理,保存或者输出
第三层:
数据处理层(要有存储和提取功能,一般在db_handler内)
购物车难点:
展示列表运用enumerate,解压赋值给编号,和商品列表
格式化输出给用户,再让客户选择
再对选择进行分析处理
1.不能是非数字
2.要在商品里表范围内
3.不能是Q
如果以上几点符合,进行下一步
通过索引取值取到商品名字和价格
通过对价格和余额的粗略比较,如果一次购买都大于余额,直接返回重新选择
进行下一步:
如果商品在购物车里,数量加一
如果不在,创建字典传入到购物车
余额减去商品价格,总价加上商品价格
西循环判断
当为Q时
判断消费是否为0
如果是零直接退出
不是
打印出购物车
询问客户是否结账买单
买单,传入到shop接口,进行数据判断,传入,name,cost,cart
,shop功能接口要实现两个功能:1,要更新购物车,2,扣款
因为对接口进行分类
扣款功能调用银行接库进行判断
最终返回 是哦付支付成功
,如果是不购买没直接退出,如果输入不合法,继续输入
core文件:
from interface import user, bank, shop
from lib import common
name_oline = {
'name': None
}
def login():
while True:
name = input('请输入用户名').strip()
pwd = input('请输入密码').strip()
tag, msg = user.login_interface(name, pwd)
if tag:
print(msg)
name_oline['name'] = name
break
else:
print(msg)
def register():
while True:
name = input('请输入注册名').strip()
pwd = input('请输入注册密码').strip()
re_pwd = input('请确认密码').strip()
if re_pwd != pwd:
print('密码不一致请重新输入')
tag, msg = user.register_interface(name, pwd)
if tag:
print(msg)
break
else:
print(msg)
@common.auth
def check_balance():
res = bank.check_balance_interface(name_oline['name'])
print('您的余额为%s' % res)
@common.auth
def transfer():
while True:
to_name = input('请输入对方用户名').strip()
money = input('请输入转账金额').strip()
if not money.isdigit():
print('请输入数字金额')
continue
money = int(money)
tag, msg = bank.transfer_interface(name_oline['name'], to_name, money)
if tag:
print(msg)
break
else:
print(msg)
@common.auth
def repay():
while True:
money = input('请输入还款金额').strip()
if not money.isdigit():
print('请输入数字')
continue
money = int(money)
bank.repay_interface(name_oline['name'], money)
print('还款成功')
@common.auth
def withdraw():
while True:
money = input('请输入提现金额').strip()
if not money.isdigit():
print('请输入数字')
continue
money = int(money)
tag, msg = bank.withdraw_interface(name_oline['name'], money)
if tag:
print(msg)
break
else:
print(msg)
@common.auth
def check_flow():
res = bank.check_flow_interface(name_oline['name'])
if res:
for i in res:
print(i)
else:
print('暂无流水')
@common.auth
def shopping():
balance = bank.check_balance_interface(name_oline['name'])
cost = 0
cart = {}
goods_list = [
['coffee', 10],
['chicken', 20],
['iphone', 8000],
['macPro', 15000],
['car', 100000]
]
while True:
for i, good in enumerate(goods_list):
print('编号:%s,商品:%s' % (i, good))
choice = input('请输入商品或输入q结账退出').strip()
if choice == 'q':
if cost == 0:
break
else:
print(cart)
config = input('是否结账Y,N')
if config == 'Y':
tag, msg = shop.shopping_interface(name_oline['name'], cost, cart)
if tag:
print(msg)
break
else:
print(msg)
continue
elif config == 'N':
print('未购买商品')
break
else:
print('输入有误请重新输入')
continue
if not choice.isdigit():
print('请输入商品或输入q结账退出')
continue
if int(choice) > (len(goods_list) - 1):
print('请输入商品或输入q结账退出')
continue
good_name = goods_list[int(choice)][0]
good_price = goods_list[int(choice)][1]
if balance < good_price:
print('账户余额不足,请重新选择商品,或者q结账退出')
continue
if good_name in cart:
cart[choice]['count'] += 1
else:
cart[choice] = {'good_price': good_price, 'count': 1}
cost += good_price
balance -= good_price
@common.auth
def check_cart():
res = shop.check_cart_interface(name_oline['name'])
if res:
print(res)
else:
print('购物车为空')
def logout():
name_oline['name']=None
l = {
'1': login,
'2': register,
'3': check_balance,
'4': transfer,
'5': repay,
'6': withdraw,
'7': check_flow,
'8': shopping,
'9': check_cart,
'10': logout
}
def run():
while True:
print("""
1.登录
2.注册
3.查看余额
4.转账
5.还款
6.取款
7.查看流水
8.购物
9.查看购买商品
10.注销
""")
choice = input('请输入您选择功能编码').strip()
if choice in l:
lchoice
else:
print('请输入有效指令')
db文件:
import os
from conf import settings
import json
def select(name):
user_path =os.path.join(settings.DB_PATH,'%s.json'%name)
if os.path.exists(user_path):
with open(user_path,'r',encoding='utf8')as f:
dic =json.load(f)
return dic
else:
return None
def save(dic):
user_path = os.path.join(settings.DB_PATH, '%s.json' % dic['name'])
with open(user_path,'w',encoding='utf8')as f:
json.dump(dic,f,ensure_ascii=False)
interface--bank:
from db import db_handler
from lib import common
bank_logger =common.get_logger('bank')
def check_balance_interface(name):
dic = db_handler.select(name)
return dic['balance']
def transfer_interface(from_name, to_name, money):
from_dic = db_handler.select(from_name)
to_dic = db_handler.select(to_name)
if not to_dic:
return False, '对方用户不存在'
if from_dic['balance'] < money:
return False, '余额不足,转账失败'
from_dic['balance'] -= money
to_dic['balance'] += money
from_dic['bankflow'].append('您向%s转账%s' % (to_name, money))
to_dic['bankflow'].append('%s向您转账%s' % (from_name, money))
db_handler.save(from_dic)
db_handler.save(to_dic)
bank_logger.info('%s向%s转账%s'%(from_name,to_name,money))
return True, '转账成功'
def repay_interface(name, money):
dic = db_handler.select(name)
dic['balance'] += money
dic['bankflow'].append('还款%s' % money)
bank_logger.info('还款%s' % money)
def withdraw_interface(name, money):
dic = db_handler.select(name)
if dic['balance'] < money1.05:
return False, '余额不足'
dic['balance'] -= money1.05
dic['bankflow'].append('提款%s' % money)
bank_logger.info('提款%s' % money)
db_handler.save(dic)
return True, '提款成功'
def check_flow_interface(name):
dic = db_handler.select(name)
flow = dic['bankflow']
return flow
def pay_interface(name, money):
dic = db_handler.select(name)
if dic['balance'] < money:
return False, '余额不足'
dic['balance'] -= money
dic['bankflow'].append('扣款%s' % money)
bank_logger.info('扣款%s'% money)
db_handler.save(dic)
return True, '扣款成功'
interface--shop:
from db import db_handler
from interface import bank
from lib import common
shop_logger =common.get_logger('shop')
def shopping_interface(name,cost,cart):
tag,msg=bank.pay_interface(name,cost)
if tag:
dic = db_handler.select(name)
dic['shopcart']=cart
db_handler.save(dic)
shop_logger.info('购买成功')
return True,'购买成功'
else:
return False,'扣款失败'
def check_cart_interface(name):
dic = db_handler.select(name)
shop_logger.info('查看购物车')
return dic['shopcart']
interface--user:
from db import db_handler
from lib import common
user_logger =common.get_logger('user')
def register_interface(name,pwd,balance=15000):
dic = db_handler.select(name)
if dic:
return False,'用户已存在'
else:
dic={'name':name,'pwd':pwd,'balance':balance,'credit':balance,'lock':False,'bankflow':[],'shopcart':{}}
db_handler.save(dic)
user_logger.info('注册成功')
return True,'注册成功'
def login_interface(name,pwd):
dic = db_handler.select(name)
if not dic:
return False,'用户名不存在'
if dic['pwd']==pwd:
user_logger.info('登陆成功')
return True,'登陆成功'
else:
user_logger.info('密码错误')
return False,'密码错误'
lib文件夹:
from core import crs
from conf import settings
import logging.config
def auth(func):
def inner(args,**kwargs):
if crs.name_oline['name']:
res = func(args,**kwargs)
return res
else:
crs.login()
return inner
def get_logger(user):
logging.config.dictConfig(settings.LOGGING_DIC)
logger =logging.getLogger(user)
return logger
start.py
import os
import sys
from core import crs
BASE_PATH = os.path.dirname(file)
sys.path.append(BASE_PATH)
if name == 'main':
crs.run()
配置文件:
import os
BASE_PATH = os.path.dirname(os.path.dirname(file))
DB_PATH = os.path.join(BASE_PATH,'db')
logging的配置信息
"""
logging配置
"""
定义三种日志输出格式 开始
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'
定义日志输出格式 结束
****************注意1: log文件的目录
BASE_PATH = os.path.dirname(os.path.dirname(file))
logfile_dir = os.path.join(BASE_PATH, 'log')
print(logfile_dir)
****************注意2: log文件名
logfile_name = 'atm.log'
如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
os.mkdir(logfile_dir)
log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)
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': 102410245, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
#logging.getLogger(name)拿到的logger配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': True, # 向上(更高level的logger)传递
},
},
}