ATM+shopping

项目的说明书

项目: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()
- 更新数据
- 删除数据

直奔主题

1.程序入口
创建一个start.py,在这里我们运行,然后到用户层执行

import os
import sys
# 项目目录加入到环境变量中
sys.path.append(os.path.dirname(__file__))
# 导入用户功能层中的src.py文件
from  core import scr

if __name__ == '__main__':
    # 执行src中的run方法启动程序
    scr.ran()

2.注册

2.1从start.py进入src.py中,创建一个字典func_dic这个是存放我们主页面功能函数的地址,register()调用函数
2.2在src.py中创建一个register函数,输入注册用户和密码,输入两次密码是否一直,不一致重新输入,调用注册的接口user_interface.register_interface(username, password, )查询用户是否存在,存在return False 请重新注册,True注册成功
2.3在功能层中调用db文件db_handler.select(username)(数据层),如果用户存在返回给功能层用户存在的信息Flase,有功能层返回给用户层,如果不存在就将用户注册的信息给保存起来,返回True
2.4用户注册的信息放在db里面,用db_hanlder里面的函数save将数据以文件的形式保存起来,以用户名的命名文件名,将用户的信息用字典的形式以json数据存储起来。

用户功能层:src.py

def register():
    while True:
        # 输入信息
        username = input('请输入账号:').strip()
        password = input('请输入密码:').strip()
        re_password = input('请确认密码:').strip()
        if password == re_password:
            # 调用注册接口
            flag, msg = user_interface.register_interface(username, password, )
            # 返回注册信息
            if flag:
                print(msg)
                break
            else:
                print(msg)

注册接口层:user_interface.py

# 注册接口
def register_interface(username, password, balance=15000):
    # 查看用户是否存在,调用select返回结果
    user_dic = db_hanlder.select(username)
    # 若已存在,告诉用户存在,请重新输入
    if user_dic:
        return False, '用户已存在'
    # 给用户密码加密
    password = common.get_pwd_md5(password)

    user_dic = {
        'username': username,
        'password': password,
        'balance': 15000,
        'flow': [],
        'shop_car': {},
        'locked': False
    }
    
    db_hanlder.save(user_dic)
    return True, f'{username}注册成功!'

数据处理层:db_hanlder.py


from conf import settings
import os
import json
from interface import user_interface

# 查看数据
def select(username):
    # 接受接口传来的username用户名,拼接用户json文件路径
    user_path = os.path.join(settings.USER_DATA_PATH, f'{username}.json')
    # 校验用户json文件是否存在
    if os.path.exists(user_path):
        # 打开数据,并传给接口层
        with open(user_path, 'r', encoding='utf-8')as f:
            user_dic = json.load(f)
            return user_dic

# 保存数据
def save(user_dic):
    #拼接用户的数据字典
    username=user_dic.get('username')
    user_path = os.path.join(settings.USER_DATA_PATH, f'{username}.json')
    # 保存用户数据
    with open(user_path, 'w', encoding='utf-8')as f:
        json.dump(user_dic, f, ensure_ascii=False)

配置文件:setting.py

import os

# 获取项目根目录reader_sys根目录
BASE_PATH = os.path.dirname(os.path.dirname(__file__))

USER_DATA_PATH=os.path.join(BASE_PATH,'db','user_data')

3 登录

3.1 在src.py中创建login(),输入账号和密码,调user_interface.login_interface(username,password)判断用户是否登录成功True,定义一个全局变量login_user,失败False密码错误,在否则的话返回用户False不存在
3.2在功能层user_interface.py中创建登录接口login_interface(),调用db文件db_handler.select(username)(数据层),等待数据的返回。
3.3db_handler.select(username) 查询用户的数据处理查询用户是否存在,存在校验密码,返回True登录成功,失败返回失败原因。

用户层:

# 登录功能
def login():
    while True:
        username=input('请输入账号:').strip()
        password=input('请输入密码:').strip()

        # 调用登录接口
        flag,msg=user_interface.login_interface(username,password)
        # 返回登录信息
        if flag:
            print(msg)
            global login_user
            login_user = username
            break
        else:
            print(msg)

接口层:

# 登录接口
def login_interface(username, password):
    user_dic = db_hanlder.select(username)
    if user_dic:
        password = common.get_pwd_md5(password)
        if password == user_dic.get('password'):

            return True, f'用户{username}登陆成功!'
        else:
            return False, '密码错误!'
    return False, '用户不存在!,请重新输入!'

4 登录认证

后面的功能提现,转账等功能我们要登录之后,才能操作,所以我们要写一个登录认证,这样的话,后续只要我们登录之后,无需在登陆,所以这是一个公共功能,我们要写一个装饰器

def login_auth(func):
    from core import scr
    def inner(*args,**kwargs):
        if scr.login_user:
            res=func(*args,**kwargs)
            return res
        else:
            print('请先登录,funny mud pee!')
            scr.login()
    return inner

5 查询余额

5.1 在src.py中创建一个check_balance()输入用户的信息,调用user_interface.check_bal_interface(login_user)查询余额,等待接口的返回信息
5.2 在user_interface接口层创建check_bal_interface(),然后调用db文件db_handler.select(username)(数据层),等待结果
5.3 db_handler.select(username)查询用户的余额,返回结果给接口,接口返回信息给check_balance()

用户层:

@common.login_auth
def check_balance():
    balance=user_interface.check_bal_interface(login_user)
    print(f'用户:{login_user} 账户余额:{balance}')


接口层:

# 查看余额接口
def check_bal_interface(username):
    user_dic = db_hanlder.select(username)
    return user_dic.get('balance')

6 转账

6.1在transfer方法上加登入认证装饰器,保证用户是登入状态。在src.py中创建withdraw(),输入提现的金额,然后判断是否是数字,不是的重新输入,是调用接口bank_interface.withdraw_interface(login_user,intput_money)

2. 在src.py(用户功能层)transfer方法中调用interface文件夹下的bank.transfer_interface()方法,(接口层,因为这里和钱相关我们把这个接口写在了bank文件中),等待接口返回数据,如果返回False则失败并打印错误原因。如果返回True则转账成功。
3 .在interface文件夹下的bank文件中transfer_interface(f)方法调用db文件夹下的db_handle文件中的selec方法,获取用户的信息,如果没有则返回False,"要转账的用户不存在",如果存在,则调用db文件夹下的db_handle文件中的selec方法,获取login_user用户的信息,判断要转账的金额是不是大于当前会员的余额,如果大于则返回False,"余额不足",如果余额充足,将扣减当前用户的余额,增加login_user用户的余额,并将流水记入到两个用户的信息中,然后做用户信息的保存,并返回True,"转账成功"。

用户层:

#提现
@common.login_auth
def withdraw():
    while True:
        intput_money=input('请输入提现金额:').strip()
        # 判断用户是否输入的是数字
        if not intput_money.isdigit():
            print('请重新输入')
            continue
        # 调用提现接口
        flag,msg=bank_interface.withdraw_interface(login_user,intput_money)
        if flag:
            print(msg)
            break
        else:
            print(msg)

接口层:


def withdraw_interface(username, money):
    # 获取用户字典
    user_dic = db_hanlder.select(username)
    # 账户中的金额
    balance = int(user_dic.get('balance'))
    # 提现+手续费
    money2 = int(money) * 1.05
    if balance >= money2:
        balance -= money2

        user_dic['balance'] = balance
        # 提现完成,更新数据
        db_hanlder.save(user_dic)
        return True, f'用户:{username} 提现金额【{money}元】,手续费为:{money2 - float(money)}元'
    return False, '你可真是穷鬼啊!!'

posted @ 2020-04-02 21:32  小子,你摊上事了  阅读(96)  评论(0)    收藏  举报