——ATM项目 叠加未完善

 

1.项目的架构图

 

二 程序的架构设计

 1、程序设计的好处

1)思路清晰
2)不会出现写一半代码时推翻重写
3)方便自己或以后的同事更好维护

 2、三层架构设计的好处

1)把每个功能都分层三部分,逻辑清晰
2)如果用户更换不同的用户界面或不同,
的数据储存机制都不会影响接口层的核心
逻辑代码,扩展性强。
3)可以在接口层,准确的记录日志与流水。

 3、三层架构

一 用户视图层
用于与用户交互的,可以接受用户的输入,打印接口返回的数据。

二 逻辑接口层
接受 用户视图层 传递过来的参数,根据逻辑判断调用数据层加以处理,
并返回一个结果给 用户视图层。

三 数据处理层
接受接口层传递过来的参数,做数据的
- 保存数据 save()
- 查看数据 select()
- 更新数据
- 删除数据

 三.项目各功能具体流程

1.在用户视图层,接收用户输入的数据,交给接口层处理

2.逻辑接口层接收到用户视图层传来的数据,进行核心逻辑校验

3.在2的校验过程中,数据处理层会接到逻辑接口层传来的阐述,并对数据进行增删改查

4.数据处理层将处理完的数据传回给逻辑接口层并完成校验

5.完成校验的逻辑接口层将结果返回给用户视图层给用户一个回应

 

以登录功能为例:

1.用户输入用户名和密码,用户视图层将得到数据传给逻辑接口层进行判断

2.逻辑层查询数据层查看用户名是否存在,若存在则继续校验密码,不存在则返回结果给用户视图层,让用户重新输入

3.逻辑层继续校验密码,查询数据层数据,判断该用户名的密码与输入的密码是否一致,若不一致则返回密码不一致,若一致则返回登陆成功

 

四.ATM部分代码

 用户视图层

from interface import user_interface
from interface import bank_interface
from interface import shop_interface
from lib import common

have_login = 0


# 注册功能
def register():
    while True:
        user_name = input('请输出账号').strip()
        password = input('请输出密码').strip()
        password_two = input('请再次输入密码输出密码').strip()
        if not password.isdigit():
            print('密码请输入数字哦')
        elif password == password_two:

            flag, msg = user_interface.register_interface(user_name, password)
            if flag:
                print(msg)
                break
            else:
                print(msg)
        print('再来一次')


# 登录功能
def login():
    while True:
        user_name = input('请输出账号').strip()
        password = input('请输出密码').strip()
        flag, msg = user_interface.user_login(user_name, password)
        if flag:
            global have_login
            have_login = user_name
            print(msg)
            break
        else:
            print(msg)


# 查看余额
@common.logins
def check_balance():
    check=user_interface.check_money(have_login)
    print(f'{have_login},余额为{check}')


# 提现功能
@common.logins
def withdraw():
    while True:
        money=input('请输入提现的金额')

        flag,msg=bank_interface.takemoney(have_login,money)
        if flag:
            print(msg)
            break
        else:
            print(msg)


# 还款功能
@common.logins
def repay():
    money=input('请输入你想还款的数额')
    msg=bank_interface.up_interface(have_login,money)
    print(msg)



# 转账功能
@common.logins
def transfer():
    to_name=input('请输入需要转移账户的姓名')
    to_money=input('请输入转账的金额')
    flag,msg=bank_interface.transfer_money(have_login,to_name,to_money)
    if flag:
        print(msg)
    else:
        print(msg)


# 查看流水
@common.logins
def check_flow():
    flow=bank_interface.check_funwater(have_login)
    if flow:
        for i in flow:
            print(i)
    else:
        print('当前用户无流水')



# 购物功能
shopping_car = {}  # {‘商品名字‘:[’价格','数量']}
@common.logins
def shopping():
    res_list=[
        ['涛哥抱枕',10000],
         ['macbook',10000],
         ['雷克萨斯',30000]
    ]

    while True:
        global shopping_car
        for index,shop in enumerate(res_list):
            shop_name,shop_price=shop
            print(''
             
                  f'商品编号{index}',
                  f'商品名称{shop_name}',
                  f'商品单价{shop_price}'
           
            '')
        #初始化购物车
        choice=input('请输入商品编号').strip()
        choice_pay_or_addcar=input('添加购物车y:直接支付:n')

        if not choice.isdigit():
            print('请输入数字')
        choice=int(choice)
         #判断choice是否存在列表中
        if choice not in range(len(res_list)):
            print('请输入正确编号')
            continue
        #获取名称单价
        shop_name,shop_price=res_list[choice]  #------>   0-->['涛哥抱枕',10000],1-->['macbook',10000],2--->['雷克萨斯',30000](直接解压出来)
        #加入购物车------》y
        # 判断用户选择的商品是否重复添加添加过购物车否则默认为一     # {‘商品名字‘:[’价格','数量']}
        if choice_pay_or_addcar == "y":

                msg=shop_interface.add_car_interface(have_login,shopping_car)                                   #有问题
                shopping_car = {}  # {‘商品名字‘:[’价格','数量']}
                print(msg)
                break

        #进支付功能接口
        if choice_pay_or_addcar == 'n':
            if shop_name in shopping_car:
                shopping_car.get("shop_car")[shop_name][1]+=1
                shopping_car[shop_name]=[shop_price,1]
                flag,msg=shop_interface.pay_interface(have_login,shopping_car)
                if flag:
                    shopping_car = {}  # {‘商品名字‘:[’价格','数量']}
                    print(msg)
                    break
                else:
                    print(msg)
                    break




# 查看购物车
@common.logins
def review_shopping_car():
    msg=shop_interface.get_shopcar(have_login)
    print(msg)

# 管理员
def admin():
    pass


new_dic = {
    '0': exit,
    '1': register,
    '2': login,
    '3': check_balance,
    '4': withdraw,
    '5': repay,
    '6': transfer,
    '7': check_flow,
    '8': shopping,
    '9': review_shopping_car,
    '10': admin,
}


def run():
    while True:
        print('''
             0、退出
             1、注册功能
             2、登录功能
             3、查看余额
             4、提现功能
             5、还款功能
             6、转账功能
             7、查看流水
             8、购物功能
             9、查看购物车
             10、管理员功能   
        ''')
        choice = input('请输入编号').strip()
        if not choice.isdigit():
            print('请输入正确数字')
            continue
        elif choice not in new_dic:
            print('你输入的数字有误')
        else:
            new_dic[choice]()

逻辑接口层

银行接口
from db import db_handler
from lib import common
bank_log=common.add_log("用户银行")

# 取钱
def takemoney(username, money):
user_dic = db_handler.judeg(username)
# 判断取钱的数量账户余额是否充足
account_mony = user_dic.get('balance')
number = int(money) * 1.05
haha = int(money) * 0.05
if account_mony >= number:
account_mony -= int(number)
user_dic['balance'] = account_mony
#记录流水
bank_log.info(f'{username}提取成功{money},手续费{int(haha)}')
res=f'{username}提取成功{money},手续费{int(haha)}'
user_dic.get('flow').append(res)
db_handler.save(user_dic)
return True, res
else:
return False, '账户余额不足请及时充值'


# 还款
def up_interface(username, money):
user_dic = db_handler.judeg(username)
if user_dic:
user_dic = db_handler.top_up(user_dic, money)
bank_log.info(f'{username},充值{money}成功')
res=f'{username},充值{money}成功'
user_dic.get('flow').append(res)
db_handler.save(user_dic)
return res


# 金钱转移
def transfer_money(usnaem, to_name, to_money):
user_dic = db_handler.judeg(usnaem)
to_user_dic = db_handler.judeg(to_name)
if to_user_dic:
user_money = user_dic.get('balance')
if eval(to_money) <= user_money:
user_money -= eval(to_money)
user_dic['balance'] = user_money
to_user_dic['balance'] += eval(to_money)

res=f'用户{usnaem}转账{to_name}金额{to_money}成功',f'用户{to_name}获得转账金额{to_money}成功'
bank_log.info(res)
user_dic.get('flow').append(res)
db_handler.save(user_dic)
db_handler.save(to_user_dic)
return True,res
else:
return False,f'金额不足请及时充值'
else:

return False,f'您转账的用户不存在'


#流水接口
def check_funwater(user):
user_dic=db_handler.judeg(user)
user_dic.get('flow')
return user_dic.get('flow')
购物接口

'''
购物接口interface
'''
from db import db_handler
from lib import common
shop_log=common.add_log('用户交易')
# 购物支付接口

def pay_interface(user_name,shopping_car): #{‘商品名字‘:[’价格','数量']}
'''
结账功能
:param user_name:
:param shopping_car:
:return:
'''

user_dic=db_handler.judeg(user_name)
for i in shopping_car:
res=shopping_car[i]
price=res[0]*res[1]
if user_dic["balance"] >= price:
user_dic['balance']-=price
shop_log.info(f'{user_name}购买{i}支付成功{price}元')
res = f'{user_name}购买{i}支付成功{price}元'
user_dic.get('flow').append(res)
db_handler.save(user_dic)
return True,res
else:
return False,'余额不足'
#添加购物车
def add_car_interface(username,shopping_car):
user_dic=db_handler.judeg(username)
user_dic.get('shop_car').update(shopping_car)
shop_log.info('添加购物车成功')
db_handler.save(user_dic)
return '添加购物车成功'


#查询购物车接口
def get_shopcar(usernaem):
user_dic=db_handler.judeg(usernaem)
res=user_dic.get("shop_car")
return res




用户接口

from db import db_handler
from lib import common
user_log=common.add_log('用户注册')


#用户注册
def register_interface(user_name,password,balance=15000):
user_dic=db_handler.judeg(user_name)

if user_dic:
return False,'用户存在'
#加密操作

password=common.pwd_md5(password)

user_dic = {
'username': user_name,
'password': password,
'balance': balance,
# 用于记录用户流水
'flow': [],
# 用于记录购物车
'shop_car': {},
# locked:用于记录用户是否被冻结
# false:未冻结
'locked': False
}
db_handler.save(user_dic)
user_log.info(f'{user_name}用户注册成功')
return True,f'{user_name}用户注册成功'


#用户登录
def user_login(username,password):
user_dic=db_handler.judeg(username)
if user_dic:
password=common.pwd_md5(password)
if password==user_dic.get("password"):
user_log.info(f'{username}登录成功')
return True,f'{username}登录成功'
else:
return False,'账号密码错误'

return False,'用户不存在'

#用户余额查询
def check_money(username):
user_dic=db_handler.judeg(username)
res=user_dic.get("balance")
return res


 

数据处理层

|--user_data(用户数据)

    |----|--------用户数据文件.json

    |----|--------用户数据文件.json

    |-----|--------用户数据文件.json

db_handle

import json
import os
from conf import settings


#查看用户是否存在(存在返回字典用于今后调用此接口的能拿到字典内容  不存在自动返回None   其他都是返回True)
def judeg(user_naem):
    user_path=os.path.join(settings.USER_PATH,f'{user_naem}.json')
    if os.path.exists(user_path):
        with open(user_path,mode='r',encoding='utf8')as f:
            res=json.load(f)
            return res



#保存数据
def save(user_dic):
    username=user_dic.get('username')
    userpath=os.path.join(settings.USER_PATH,f'{username}.json')
    with open(userpath,mode='w',encoding='utf8')as f:
        json.dump(user_dic,f,ensure_ascii=False)#字典内就可以输入中文了

#还款
def top_up(user_dic,money):
    user_dic['balance']+=int(money)
    return user_dic

lib公用方法

common

import hashlib
import logging.config
from conf import settings
# 登入认证装饰器
def logins(func):
from core import src
def wrapper(*args,**kwargs):
if src.have_login:
res=func(*args,**kwargs)
return res
else:
print('您还未登入无法享受服务请登录吧')
src.login()
return wrapper

#加密加盐
def pwd_md5(password):
res=hashlib.md5()
res.update('天王盖地虎'.encode('utf8'))#记得编编码处理uodate() md5今晚再练习几遍
res.update(password.encode('utf8'))
res.update('宝塔阵河妖'.encode('utf8'))
return res.hexdigest() #提取追后全部列表结果的加密程序

#添加日志功能

def add_log(user_type):
'''
各个接口添加日志
:param user_type:
:return:
'''
# 加载日志配置信息
logging.config.dictConfig(
settings.LOGGING_DIC
)
# 获取日志对象
logger=logging.getLogger(user_type)
print(logger)
return logger

日志log

conf \ settings

import os

#文件基础路劲
BASE_PATH=os.path.dirname(os.path.dirname(__file__))

#获取文件数据库路径
USER_PATH=os.path.join(BASE_PATH,'db','user_data')

"""
logging配置
"""

import os

# 1、定义三种日志输出格式,日志中可能用到的格式化串如下
# %(name)s Logger的名字
# %(levelno)s 数字形式的日志级别
# %(levelname)s 文本形式的日志级别
# %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
# %(filename)s 调用日志输出函数的模块的文件名
# %(module)s 调用日志输出函数的模块名
# %(funcName)s 调用日志输出函数的函数名
# %(lineno)d 调用日志输出函数的语句所在的代码行
# %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
# %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
# %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
# %(thread)d 线程ID。可能没有
# %(threadName)s 线程名。可能没有
# %(process)d 进程ID。可能没有
# %(message)s用户输出的消息

# 2、强调:其中的%(name)s为getlogger时指定的名字
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

test_format = '%(asctime)s] %(message)s'

BASE_DIR = os.path.dirname(os.path.dirname(__file__))  # log文件的目录   
LOG_PATH = os.path.join(BASE_DIR,'log','a1.log')
LOG_PATH_TWO=os.path.join(BASE_DIR,'log','a2.log')

# 3、日志配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    #设置日志的格式
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
        'test': {
            'format': test_format
        },
    },
    'filters': {},
     # handlers是日志的接收者,不同的handler会将日志输出到不同的位置
    'handlers': {
        #打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        #打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,日志轮转
            'formatter': 'standard',
            # 可以定制日志文件路径
            'filename':LOG_PATH,  # 日志文件
            'maxBytes': 1024*1024*5,  # 日志大小 5M
            'backupCount': 5,#指定文件最多备份几份
            'encoding': 'utf-8',# 日志文件的编码,再也不用担心中文log乱码了
        },
        'other': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'formatter': 'test',
            'filename': LOG_PATH_TWO,
            'encoding': 'utf-8',
        },
    },
     # loggers是日志的产生者,产生的日志会传递给handler然后控制输出
    'loggers': {
        #logging.getLogger(__name__)拿到的logger配置
        '用户交易': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
            'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
        },
        '': {
            'handlers': ['default','other'],
            'level': 'DEBUG',
            'propagate': False,
        },
    },
}

log下

  a1

  a2   #等日志文件

 

start(开始文件)

from core import src



if __name__ == '__main__':
    src.run()

readme

#**项目说明书**
##项目:ATM+购物车

# 项目需求:
    1.额度15000或自定义     -->  注册功能
    2.实现购物商城,买东西加入购物车,调用信用卡接口结账  --> 购物功能、支付功能
    3.可以提现,手续费5%   --> 提现功能
    4.支持多账户登录  --> 登录功能
    5.支持账户间转账  --> 转账功能
    6.记录日常消费 -->  记录流水功能
    7.提供还款接口 -->  还款功能
    8.ATM记录操作日志 --> 记录日志功能
    9.提供管理接口,包括添加账户、用户额度,冻结账户等。。。 ---> 管理员功能
    10.用户认证用装饰器  --> 登录认证装饰器
    

## "用户视图层" 展示给用户选择的功能
    1、注册功能
    2、登录功能
    3、查看余额
    4、提现功能
    5、还款功能
    6、转账功能
    7、查看流水
    8、购物功能
    9、查看购物车
    10、管理员功能

# 一个项目是如何从无到有
## 一 需求分析
    1.拿到项目,会先在客户那里一起讨论需求,
    商量项目的功能是否能实现,周期与价格,得到一个需求文档。
    
    2.最后在公司内部需要开一次会议,最终得到一个开发文档,
    交给不同岗位的程序员进行开发。
        - Python: 后端,爬虫
        
        - 不同的岗位:
            - UI界面设计:
                - 设计软件的布局,会分局软件的外观切成一张张图片。
            
            - 前端:
                - 拿到UI交给他的图片,然后去搭建网页面。
                - 设计一些页面中,哪些位置需要接收数据,需要进行数据交互。
            
            - 后端:
                - 直接核心的业务逻辑,调度数据库进行数据的增删查改。
            
            - 测试:
                - 会给代码进行全面测试,比如压力测试,界面测试(CF卡箱子)。
            
            - 运维:
                - 部署项目。
        
        
        
    
## 二 程序的架构设计
### 1、程序设计的好处
    1)思路清晰
    2)不会出现写一半代码时推翻重写
    3)方便自己或以后的同事更好维护
    
### 2、三层架构设计的好处
    1)把每个功能都分层三部分,逻辑清晰
    2)如果用户更换不同的用户界面或不同,
    的数据储存机制都不会影响接口层的核心
    逻辑代码,扩展性强。
    3)可以在接口层,准确的记录日志与流水。
    
### 3、三层架构
#### 一 用户视图层
    用于与用户交互的,可以接受用户的输入,打印接口返回的数据。
    
#### 二 逻辑接口层
    接受 用户视图层 传递过来的参数,根据逻辑判断调用数据层加以处理,
    并返回一个结果给 用户视图层。
    
#### 三 数据处理层
    接受接口层传递过来的参数,进行数据处理
        - 保存数据  save()
        - 查看数据  select()
        - 更新数据
        - 删除数据

## 三 分任务开发
## 四 测试
## 五 上线



# 统计代码
file ---> settings ---> Plugins ---> 
文件说明书
A-用户视图层  B-逻辑接口层  C-数据处理层

注册功能:
    A接受用户输入数据,进行小逻辑判断,判断俩次密码输入是否一致,不一致让用户重新输,一致就将用户名和密码传给B,
B把数据传给C,C进行数据查找,有就返回给B字典,没就返回None,B根据返回的结果进行处理,如果返回的是字典就将用
户已经存在的结果返回给A,A打印结果给用户;如果是None就让C把用户数据进行保存,然后返回将结果返回给A,A打印给
用户结果。

登录功能:
    A接受用户输入数据,将数据传给B,B将数据传给C,C进行数据查找返回结果给B,如果是None,B就将结果返回给A,A打印结果
给用户,如果返回是字典,就判断密码是否一致,然后将结果返回给A,A打印结果给用户

查询余额:
    因为有登录装饰器,能使用该功能的用户已经登录,使用该功能时,A将全局变量的中的用户名传给B,B把数据传给C进行数据
查找,查找完的结果给B,B将用户的金额返回给A,A打印结果给用户

提现功能:
    因为有登录装饰器,能使用该功能的用户已经登录,A接受用户传入的数据后给B,B通过把登录的用户传给C进行数据的查找,将
查找的结果返回给B,B过去用户金额,和提现金额进行比对,若用户提现金额加手续费大于用户余额,则返回给A用户金额不足;若
用户余额大于用户提现金额加手续费,则进行数据处理,将余额减去提现金额加手续费,让后将数据传给C,让C进行保存覆盖以前的
数据,B还将结果返回给A,A打印给用户结果
文件编写逻辑

 

 

 

 

 

 

posted @ 2021-03-26 18:11  欧阳锦涛  阅读(41)  评论(0)    收藏  举报
TOP 底部