ATM+购物车
实现功能事项:
用户视图层:
与用户进行交互,接收用户处理输入的数据,交给接口层进行处理,接口层最终会将一个结果
返回给用户视图层展示给用户
逻辑接口层
相当于用户视图层与数据处理层的桥梁
专门复测接收用户视图层传过来的数据,并进行“核心的逻辑”校验,校验过程中
,会去访问"数据层“进行数据的增删改查,通过或不通过会返回一个结果给用户视图层进行展示
--日志的添加、流水的添加都是在这层
数据处理层:
职责:接收到接口层传递过来的参数,进行数据的处理
1.增加数据
2.查看数据
3.删除数据
4.更新数据
common通用组件
-----------------------------------
-----------------------------------
搭建项目的目录规范:
-ATM项目根目录
-readme.md 项目说明书
-start.py 项目启动文件
-conf 配置文件夹
-settings.py
-lib 公共方法文件
-common.py
-core [用户视图层]存放用户视图层代码文件
-src.py
-interface [逻辑接口层] 存放核心业务逻辑代码
-user_interface.py 用户相关的接口
-bank_interface.py 银行相关的接口
-shop_interface.py 购物相关的接口
-db [数据处理层] 存放数据与数据处理代码
-db_handler.py 数据处理层代码
-user_data 用户数据
-log 存放日志文件
```
入口函数
1.start.py
```python
"""
程序的入口,主程序入口
"""
import os
import sys
# python 环境下使用sys.path.append(path)添加相关的路径,
# 但在退出python环境后自己添加的路径就会自动消失了!
# 添加解析器的环境变量
sys.path.append(os.path.dirname(__file__))
from core import src
if __name__ == '__main__':
src.run() # 执行用户视图层的函数
```
2.core/src.py
```pyton
"""
核心代码区,用户视图层
"""
from interface import user_interface
from lib import common
from interface import bank_interface
# 全局变量,记录用户是否已登录
login_user=None
#1.注册功能
def register():
while True:
#1.让用户输入用户名和密码进行校验
username=input("请输入用户名:").strip()
password=input("请输入密码:").strip()
re_password=input("请再次输入密码:").strip()
# 很小的逻辑处理,比较两次密码是否一致
if password==re_password:
#2)调用接口层的注册接口
# flag,msg--->(flag--->False,msg--->'用户名已经存在!)
# (True,用户注册成功)(False,注册失败)
flag,msg=user_interface.register_interface(username,password)
#3)根据flag判断用户注册是否成功,
if flag:
print(msg)
break
else:
print(msg)
# 2.登录功能
def login():
# 登录视图
while True:
# 1)让用户输入用户名与密码
username=input("请输入用户名:").strip()
password=input("请输入密码:").strip()
#2)调用接口层,将数据传给登录接口
#True,f'用户:{username}登录成功!'
#return False,'密码错误'
#return False,'用户不存在,请重新输入'
flag,msg=user_interface.login_interface(username,password)
if flag:
print(msg)
global login_user
login_user=username #标记登录的用户
break
else:
print(msg)
# 3.查看余额
# @common.login_auth
def check_balance():
# 1.直接调用查看余额接口,获取用户余额
balance=user_interface.check_bal_interface(login_user)
print(f'用户{login_user}账户余额为:{balance}')
# 4.提现功能
# @common.login_auth
def withdraw():
while True:
# 1)让用户输入提现金额
input_money=input("请输入提现金额:").strip()
# 2)判断用户输入的金额是否是数字
if not input_money.isdigit():
print("请重新输入")
continue
#3)用户提现金额,将提现的金额交付给接口层来处理
flag,msg=bank_interface.withdraw_interface(login_user,input_money)
if flag:
print(msg)
break
else:
print(msg)
# 5.还款功能
# @common.login_auth
def repay():
"""
银行卡还款,无论信用卡或者储蓄卡,是否能充任意大小的金额
:return:
"""
while True:
# 1.让用户输入还款金额
input_money=input("请输入需要还款的金额:").strip()
# 2.判断用户输入的是否是数字
if not input_money.isdigit():
print("请输入正确的金额")
continue
input_money=int(input_money)
# 3)判断用户输入的金额大于0
if input_money>0:
# 4)调用还款接口
flag,msg=bank_interface.repay_interface(login_user,input_money)
if flag:
print(msg)
break
else:
print("输入的金额不能小于0")
# 6.转账功能
# @common.login_auth
def transfer():
"""
1.接收用户输入的转账目标用户
2.接收永不输入的转账金额
:return:
"""
while True:
#1)让用户输入转账用户与金额
to_user=input("请输入转账目标用户").strip()
money=input("请输入转账金额:").strip()
#2)判断用户输入的金额是否是数字或>0
if not money.isdigit():
print("请输入正确的金额")
continue
money=int(money)
if money>0:
#3)调用庄重接口 #当前用户 目标用户 转账金额
flag,msg=bank_interface.transfer_interface(login_user,to_user,money)
if flag:
print(msg)
break
else:
print(msg)
else:
print("请输入正确的金额!")
# 7.查看流水
# @common.login_auth
def check_flow():
# 直接调用查看流水接口
flow_list=bank_interface.check_flow_interface(login_user)
if flow_list:
for flow in flow_list:
print(flow)
else:
print("当前用户没有流水")
# 8.购物功能
# @common.login_auth
def shopping():
pass
# 9.查看购物车
# @common.login_auth
def check_shop_car():
pass
# 10.管理员功能
def admin():
pass
func_dict={
'1':register,
'2':login,
'3':check_balance,
'4':withdraw,
'5':repay,
'6':transfer,
'7':check_flow,
'8':shopping,
'9':check_shop_car,
'10':admin,
}
# 视图层 主程序
def run():
while True:
print("""
1.注册功能
2.登录功能
3.查看余额
4.提现功能
5.还款功能
6.转账功能
7.查看流水
8.购物功能
9.查看购物车
10.管理员功能
""")
choice=input("请输入功能编号:").strip()
if choice not in func_dict:
print("请输入正确的功能编号!")
continue
func_dict.get(choice)() #相当于func_dic.get("1")()--->register
if __name__ == '__main__':
run()
```
2.1core/admin.py
```python
from core import src
from interface import admin_interface
#添加用户
def add_user():
src.register() #调用添加账户信息
#修改用户额度
def change_balance():
while True:
#1)输入需要修改的账户名
chang_user=input("请输入需要修改额度的用户:").strip()
#2)修改的用户用户额度
money=input("请输入需要修改的用户额度:").strip()
if not money.isdigit():
continue
#3)调用修改额度接口
flag,msg=admin_interface.change_balance_interface(chang_user,money)
if flag:
print(msg)
break
else:
print(msg)
#冻结用户
def lock_user():
while True:
#1)输入要冻结的用户名
change_user=input("请输入需要冻结的账户:").strip()
flag,msg=admin_interface.lock_user_interface(change_user)
if flag:
print(msg)
break
else:
print(msg)
#
#管理员功能字典
admin_func={
'1':add_user,
'2':change_balance,
'3':lock_user,
}
def admin_run():
while True:
print("""
1.添加账户
2.修改额度
3.冻结账户
""")
choice=input("请输入管理员功能编号:").strip()
if choice not in admin_func:
print("请输入正确编号!")
continue
admin_func.get(choice)()
```
3.interface接口
3.1bank_intrface.py
```python
"""
银行相关业务的接口
"""
from db import db_handler
#提现接口(手续费5%,就是每次提现都是花费5%)
def withdraw_interface(username,money):
#1)先获取用户字典
user_dic=db_handler.select(username)
#账户中的金额
balance=int(user_dic.get('balance'))
#提现本金+手续费
money2=int(money)*1.05
#判断用户金额是否足够
if balance>=money2:
#2)修改用户字典中的金额
balance-=money2
user_dic['balance']=balance
#3) 记录流水
flow=f'用户[{username}]体现金额[{money}$]成功,手续费用为[{money2-float(money)}]'
user_dic['flow'].append(flow)
# 3.1)在保存数据,或者更新数据
db_handler.save(user_dic)
return True,f'用户[{username}]提取金额[{money}]成功,手续费为:{money2-float(money)}$'
return False,f'提现金额不足,请重新输入!'
# 还款接口
def repay_interface(username,money):
"""
1.获取用户的金额
2.给用户的金额做加钱的操作
:return:
"""
# 1.获取用户字典
user_dic=db_handler.select(username)
#2.直接做加钱操作
# user_dic["balance"]----->int
user_dic['balance']+=money
#3.记录流水
flow=f'用户:[{username}] 还款[{money}]成功!'
user_dic['flow'].append(flow)
#3.调用数据处理层,将修改后的数据更新
db_handler.save(user_dic)
return True,f'用户:[{username}] 还款:[{money}]成功,当前额度为:{user_dic["balance"]}'
# 转账接口
def transfer_interface(login_user,to_user,money):
"""
1.获取“当前用户”数据
2.获取“目标用户”数据
3.获取转账金额
:param login_user:
:param to_user:
:param money:
:return:
"""
#1)获取 当前用户 字典
login_user_dic=db_handler.select(login_user)
#2)获取“目标用户:字典
to_user_dic=db_handler.select(to_user)
#3)判断目标用户是否存在
if not to_user_dic:
return False,"目标用户不存在"
#4若用户存在,则判断“当前用户的转账金额”是否足够
if login_user_dic['balance']>=money:
#5)若足够,则开始给目标用户转账
#5.1)给当前用户的数据,做减钱的操作
login_user_dic['balance']-=money
#5.2)给目标用户的数据,做加钱的操作
to_user_dic["balance"]+=money
#5.3记录当前用户与目标用户的流水
#当前用户流水
login_user_flow=f'用户[{login_user}]给用户:[{to_user}]转账:[{money}]成功'
login_user_dic['flow'].append(login_user_flow)
# 给目标用户流水
to_user_flow = f'用户[{to_user}]接收用户:[{login_user}]转账:[{money}]成功'
to_user_dic['flow'].append(to_user_flow)
#6.保存用户数据
#6.1)调用数据处理层的save功能,保存当前用户数据
db_handler.save(login_user_dic)
#6.2)给调用数据处理层的save功能,保存目标用户数据
db_handler.save(to_user_dic)
return True,f'用户:[{login_user}]给用户[{to_user}]转账:[{money}]元,成功!'
return False,"当前用户转账金额不足!"
#查看流水接口
def check_flow_interface(login_user):
user_dic=db_handler.select(login_user)
return user_dic.get('flow') #返回一个list列表
#支付接口
def pay_interface(login_user,cost):
user_dic=db_handler.select(login_user)
#判断用户金额是否足够
if user_dic.get('balance')>=cost:
# 足够就是减钱
user_dic['balance']-=cost
#记录消费流水
flow=f"用户消费金额:[{cost}]"
user_dic['flow'].append(flow)
#保存数据
db_handler.save(user_dic)
# return True,或者false 交给购物接口来处理
return True
return False
```
3.2shop_intrface.py
```python
"""
购物商城接口
"""
from db import db_handler
#商品准备结算接口
def shopping_interface(login_user,shopping_car):
#1)计算消费总额
#{‘商品名称’:["价格","数量"]}
cost=0
for price_number in shopping_car.values():
price,number=price_number
cost+=(price*number)
#导入银行接口
from interface import bank_interface
#逻辑校验成功后,再调用银行的支付接口
flag=bank_interface.pay_interface(login_user,cost)
if flag:
return True,"支付成功,准备发货!"
return False,"支付失败,金额不足!"
#购物车添加接口
def add_shop_car_interface(login_user,shopping_car):
#1)获取当前用户的购物车
user_dic=db_handler.select(login_user)
#获取用户文件中的商品的数据
shop_car=user_dic.get("shop_car")
#2)添加购物车
#2.1)判断当前用户选择的商品是否已经存在
# shopping_car--->{'商品名':["商品价格,商品数量"]}
for shop_name,price_number in shopping_car.items():
#每个商品的数量
number=price_number[1]
#2.2)若有商品重复,则累加商品数量
if shop_name in shop_car:
user_dic['shop_car'][shop_name][1]+=number
else:
#2.3)若不是重复的,更新到商品字典中
user_dic['shop_car'].update({shop_name:price_number})
#保存用户数量
db_handler.save(user_dic)
return True,"添加购物车成功!"
#查看购物车接口
def check_shop_car_interface(login_user):
pass
```
3.3user_intrface.py
```python
"""
逻辑接口层
用户接口
"""
from db import db_handler
from lib import common
# 注册接口
def register_interface(username,password,balance=15000):
#2)查看用户是否存在
#2.1)调用数据处理层中的select函数,会返回用户字典或者None
user_dic=db_handler.select(username)
#{user:user,pwd:pwd...} or None
# 若用户存在则return ,告诉用户重新输入
if user_dic:
# return(False,'用户名已经存在!')
return False,'用户名已存在!'
#3)若用户不存在,则保存用户数据
#做密码加密
password=common.get_pwd_md5(password)
#3.1 组织用户的数据的字典信息
user_dict={
'username':username,
'password':password,
'balance':balance,
# 用于记录用户流水的列表
'flow':[],
# 用于记录用户购物车
'shop_car':{},
#locked 用于记录用户是否被冻结
#False:未冻结 True:已经被冻结
#
'locked':False
}
#3.2 保存数据
db_handler.save(user_dict)
return True,f'{username}注册成功!'
# 登录接口
def login_interface(username,password):
#1)先查看当前用户数据是否存在
#{用户数据字典} or None
user_dict=db_handler.select(username)
#用户判断用户是否存在
#若有冻结用户 则需要判断是否被锁定
if user_dict.get("locked"):
return False,"当前用户已被锁定"
#2)判断用户是否存在
if user_dict:
#给用户输入的密码做一次加密
password=common.get_pwd_md5(password)
#3)校验密码是否一致
if password==user_dict.get('password'):
return True,f'用户:{username}登录成功!'
else:
return False,'密码错误'
return False,'用户不存在,请重新输入'
#查看余额接口
def check_bal_interface(username):
user_dic=db_handler.select(username)
return user_dic['balance']
```
3.4interface/admin.py接口
```python
from db import db_handler
# 修改额度接口
def change_balance_interface(username,money):
user_dic=db_handler.select(username)
if user_dic:
#修改额度
user_dic["balance"]=int(money)
#保存修改后的用户数据
db_handler.save(user_dic)
return True,"额度修改成功!"
return False,"修改额度用户不存在!"
#冻结账户接口
def lock_user_interface(username):
user_dic=db_handler.select(username)
if user_dic:
#将locked的默认值修改为True
user_dic['lcoker']=True
db_handler.save(user_dic)
return True,f"用户{username}冻结成功!"
return False,"冻结用户不存在"
```
4.lib
lib/common.py
```python
"""
存放公共方法
"""
import hashlib
#md5加密
def get_pwd_md5(password):
md5_obj=hashlib.md5()
md5_obj.update(password.encode('utf-8'))
#加盐操作
salt='我是加盐操作123456!'
md5_obj.update(salt.encode('utf-8'))
return md5_obj.hexdigest()
# 登录认证装饰器模板
# def login_authmobao(func):
# def inner(*args,**kwargs):
# res=func(*args,**kwargs)
# return res
#
# return inner()
# 登录认证装饰器
# 装饰器的使用,为其他函数进行装饰。
def login_auth(func):
from core import src #在这里导入的好处是,避免重复导入问题
def inner(*args,**kwargs):
if src.login_user:
res=func(*args,**kwargs)
return res
else:
print("用户未登录,无法使用功能,请登录!")
src.login()
return inner()
```
5.db数据存储
下面两个,一个是文件夹“”user_data",存放用户*.json数据,还有一个db_handler.py--->这个主要是进行数据的存储处理
db_handler.py
```python
"""
数据处理层
-专门用户处理数据的
"""
import json
import os
from conf import settings
#查看数据
def select(username):
# 1)接收层传过来的username用户名,拼接用户json文件路径,如果穿过来的用户是
# 是’张三‘那么本地就是存储为"张三.json"文件
user_path=os.path.join(
settings.USER_DATA_PATH,f'{username}.json'
)
# 2)校验用户json文件是否存在
if os.path.exists(user_path):
#3)打开数据,并返回给接口层
with open(user_path,'r',encoding='utf-8')as f:
use_dict=json.load(f)
return use_dict
# 3)不return,默认return None
# 保存数据
def save(user_dict):
# 1)拼接用户的数据字典
username=user_dict.get('username')
user_path=os.path.join(settings.USER_DATA_PATH,f'{username}.json')
# 2)保存用户数据
with open(user_path,'w',encoding='utf-8')as f:
#ensure_ascii=False),让保存到jsoon文件的中文,显示为中文而不是16进制
json.dump(user_dict,f,ensure_ascii=False)
```
6.配置文件conf文件夹
conf/settings.py---->数据文件的配置事项
```python
"""
保存配置信息
"""
import os
#获取项目根目录路径
BASE_PATH=os.path.dirname(os.path.dirname(__file__))
# 获取user_data文件夹的目录路径
USER_DATA_PATH=os.path.join(
BASE_PATH,'db','user_data'
)
# print(USER_DATA_PATH)
```
7.sstart.py--->启动文件
```python
"""
程序的入口,主程序入口
"""
import os
import sys
# python 环境下使用sys.path.append(path)添加相关的路径,
# 但在退出python环境后自己添加的路径就会自动消失了!
# 添加解析器的环境变量
sys.path.append(os.path.dirname(__file__))
from core import src
if __name__ == '__main__':
src.run() # 执行用户视图层的函数
```