ATM项目

目录

一、项目开发流程

​ 1.项目需求分析

​ 产品经理 (客户)-- 架构师 -- 开发经理

​ 1 架构师 开发经理提前构思大致方案

​ 2 引导客户提出合理要求(避免不合理的请求)

​ 3 记录会议内容

​ 2.项目架构设计

​ 架构师

​ 1 项目所需编程语言(根据项目的业务选择)

​ 2 项目整体框架

​ 框架、数据库服务(主库、从库)

​ 3 项目报价

​ 3.项目分组开发

​ 架构师 开发经理 程序员

​ 1 任务拆分,分组开发

​ 4.项目提交测试

​ 1 程序员自己要提前测试一下

​ 2 测试部门专业测试

​ 5.项目交付上线

​ 运维人员负责

二、ATM项目需求分析

该项目的核心不仅在于引领初学者快速入门python项目开发,更是站在项目架构的角度教你如何在程序开发之初合理且优雅地设计程序的架构,从而极大地提升程序的开发效率与可扩展性
"""
- 额度15000或自定义
- 支持多账户登录
- 可以查看账户余额
- 可以提现(可自定义手续费比例)
- 提供还款接口
- 支持账户间转账
- 记录每月日常消费流水
- 实现购物商城,买东西加入购物车,调用信用卡接口结账
- 提供管理接口,包括添加账户、用户额度,冻结账户等
- ATM记录操作日志
- 用户认证功能
"""
1.注册功能
2.登录功能
3.查看余额
4.提现功能
5.充值功能
6.转账功能
7.查看流水
8.添加购物车
9.结算购物车
10.管理员功能
	10.1.冻结账户
 	10.2.删除账户

三、项目架构设计(重点)

1.三层架构设计案例

1)百度

​ 以百度登录功能为例,分步执行步骤

​ 1.在浏览器页面上获取用户名和密码

​ 计算机本地:展示数据给用户看,获取用户数据(只要是基于逻辑判断的条件,都不在本地)

​ 2.基于网络发送给百度服务器

​ 百度服务端:核心业务逻辑代码

​ 3.服务端连接数据库服务

​ 数据库服务:做数据的增删改查

image-20221028095244737

三层架构的特点:

优点:

1 每层分工明确,安全性有保障

2 数据库可以变化

3 第一层不做核心逻辑,只做数据展示和简单的数据获取

4 扩展性强

5 方便管理

但是三层架构彼此之间的关系固定不能改变

2)淘宝

​ 以淘宝买商品为例

​ 1 在浏览器页面展示商品总价

​ 2 基于网络发送给淘宝服务端再次计算总价

​ 3 调用数据库服务完成金额操作

2.三层架构逻辑

第一层:只做数据展示和简单的数据获取

​ cmd终端、浏览器页面、手机app页面

第二层:真正的核心业务逻辑和处理(代码)

​ 编写代码的py文件、目录、框架

第三层:数据操作

​ 文件夹读写操作、py文件、数据库软件

四、ATM架构设计

image-20221028101829956

1.bin目录:项目的启动目录,存放项目的启动文件

start.py文件:项目的启动文件

base_dir 先确定了当前项目的根目录

sys.path.append(base_dir)
将项目的根目录添加为环境变量,这样在后续导入模块的时候,就不会出现找不到模块文件的问题

if __name__ == "__main__":
from core import src

src.run()

判断文件作为项目的启动文件时候,才开始执行src文件中的run函数

2.conf目录:项目配置目录

settings.py项目配置文件

import os

# db目录的路径,在一个项目中不改变,则可以放在配置文件中
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DB_DIR = os.path.join(BASE_DIR, 'db')
if not os.path.exists(DB_DIR):
    os.mkdir(DB_DIR)

# 提现手续费,在提现中是固定的比率,则可以放在配置文件中
MONEY_RATE = 0.05



# 自定义文件路径,拼接路径获得项目的日志目录和日志文件路径
LOG_DIR = os.path.join(BASE_DIR, 'log')
if not os.path.isdir(LOG_DIR):
    os.mkdir(LOG_DIR)
LOGFILE_PATH = os.path.join(LOG_DIR, 'ATM.log')

# log配置字典
.......
"""日志文件的固定配置字典,选择配置后不会变化,则放在项目的配置文件settings.py中"""

3.core核心功能目录(架构第一层)

Src.py项目的核心功能列举文件

在三层架构中属于第一层

1.导入的模块

(1)导入了interface接口文件,其中接口文件根据针对业务的逻辑不同,划分了不同的文件

​ 1)用户接口:user_interface

​ 2)银行接口:bank_interface

​ 3)购物接口:shop_interface

(2)导入了lib文件中的公共功能的文件common

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

2.保存用户登录状态功能的字典

​ 用于获得用户的用户名,同时可以记录用户的登录状态,用户登录后则可以将当前登录的用户添加为字典中 键username的值 。

​ 记录登录状态的功能在现实中,比如浏览器中的cookies也是属于框架第一层。

is_login = {
    'username': ''
}

3.注册register

​ 三层框架的第一层register

​ (1) 获取注册用户的用户名和密码,已经确认密码

​ (2) 简单判断两次密码是否输入一致,不必传入第二层

​ (3) 调用第二层接口 user_interface 文件中的 register_interface,传入获取的用户名和密码

def register():
    # 1.获取用户相关数据
    username = input('请输入您的用户名>>>:').strip()
    password = input('请输入您的密码>>>:').strip()
    confirm_pwd = input('请确认您的密码>>>:').strip()
    # 2.判断两次密码是否一致
    if not password == confirm_pwd:
        print('两次密码不一致 请重新输入')
        return
    # 直接调用用户注册接口
    flag, msg = user_interface.register_interface(username, password)
    print(msg)

4.登录login

​ 三层框架的第一层login

​ (1) 获取想要登录的用户的用户名和密码

​ (2) 调用第二层接口 user_interface 文件中的 login_interface,传入获取的用户名和密码

​ (3) 记录用户的登录状态,将当前登录用户的用户名传入字典中

def login():
    # 1.获取用户相关数据
    username = input('请输入您的用户名>>>:').strip()
    password = input('请输入您的密码>>>:').strip()
    # 2.直接调用用户登录接口
    flag, msg = user_interface.login_interface(username, password)
    '''登录接口返回的数据值有两个 为了保证接口调用返回值的一致性 应该让所有的接口函数返回值个数保持一致 都应该变成两个'''
    # 3.修改登录的状态,记录当前登录的用户名
    if flag:
        is_login['username'] = username
    print(msg)

*校验用户是否登录的装饰器

​ 除了注册登录的功能,其他功能都需要登录后才能使用,所以需要添加校验用户是否登录的装饰器,因为其属于公共功能,将其放在common.py文件中

def login_auth(func_name):
    def inner(*args, **kwargs):
        if src.is_login.get('username'):
            res = func_name(*args, **kwargs)
            return res
        else:
            print('您暂未登录 请先去登录')
            src.login()

    return inner

5.查看余额check_balance

​ (1) 调用第二层接口 bank_interface 文件中的 check-balance_interface,传入获取登录用户的用户名,查看当前用户余额

@common.login_auth
def check_balance():
    # 直接调用查看账户余额的接口
    flag, msg = bank_interface.check_balance_interface(is_login.get('username'))
    print(msg)

6.提现功能withdraw

​ (1) 获取用户提现的金额

​ (2)调用第二层接口 bank_interface 文件中的 withdraw_interface,传入获取登录用户的用户名username和提现的金额target_money,查看当前用户余额

   由于输入的金额可以是小数,所以在判断用户的输入的时候,只用isdigit()只能判断是否输入的是否是整数,而还可能输入的小数。
   可以用异常处理来判断:
# 判断获取的数字是否是小数或者整数
# 如果输入的字符串可以转换为浮点型的数据,则说明其是小数或者整数,否则会返回异常提示用户‘请输入小数或者整数’
def get_num(target_money):
    try:
        target_money = float(target_money)
    except ValueError:
        return False, '请输入整数或者小数'
    else:
        return True, target_money

@common.login_auth
def withdraw():
    # 1.获取用户想要提现的具体金额即可
    target_money = input('请输入您想要提现的金额>>>:').strip()
    # 2.判断用户输入的是否是整数或者小数 100 123.23  正则表达式、代码处理
    '''转数字的操作 也可以封装成函数放到common.py中'''
    # 3.调用银行接口完成提现操作
    flag, msg = bank_interface.withdraw_interface(is_login.get('username'), target_money)
    print(msg)

7.充值功能pay_back

​ (1) 获取用户想充值的金额

​ (2)调用第二层接口 bank_interface 文件中的 pay_back_interface,传入获取登录用户的用户名username和充值金额target_money

涉及获取金额问题,都需要考虑判断输入的是小数还是整数

@common.login_auth
def pay_back():
    # 1.直接获取用户想要充值的钱数
    target_money = input('请输入您想要充值的金额>>>:').strip()
    # 2.还需要判断是否是整数或者小数
    flag, msg = bank_interface.pay_back_interface(is_login.get('username'), target_money)
    print(msg)



8.转账transfer

​ (1) 获取用户转账的用户名

​ (2) 获取用户想转账的金额

​ (3)调用第二层接口 bank_interface 文件中的 transfer_interface,传入获取登录用户的用户名username和转账的用户target_user、想转账的金额target_money

@common.login_auth
def transfer():
    # 1.获取想要转账的用户名
    target_user = input('请输入您想要转账的用户>>>:').strip()
    # 2.获取想要转账的金额
    target_money = input('请输入您想要转账的金额>>>:').strip()
    # 3.直接调用转账的接口
    flag, msg = bank_interface.transfer_interface(is_login.get('username'), target_user, target_money)
    print(msg)

9.查看流水功能check_flow

​ (1)调用第二层接口 bank_interface 文件中的 check_flow_interface,传入获取登录用户的用户名username

@common.login_auth
def check_flow():
    # 直接调用查看流水的接口即可
    flag, msg = bank_interface.check_flow_interface(is_login.get('username'))
    if flag:  # msg = ['','','']
        for data in msg:
            print(data)
    else:
        print(msg)

10.添加购物车add_shop_car

​ (1)调用第二层接口 shop_interface 文件中的 add_shop_car_interface,传入获取登录用户的用户名username

@common.login_auth
def add_shop_car():
    """
    1.先获取商品数据
    2.打印商品数据并让用户选择
    3.用户一旦退出 调用接口完成购物车数据更新
    :return:
    """
    # 1.直接调用添加购物车接口
    flag, msg = shop_interface.add_shop_car_interface(is_login.get('username'))
    print(msg)

​ 1.先获取商品数据
​ 2.打印商品数据并让用户选择
​ 3.用户一旦退出 调用接口完成购物车数据更新

11.查看购物车功能check_shop_car

​ (1)调用第二层接口 shop_interface 文件中的 check_shop_car_interface,传入获取登录用户的用户名username

​ (2)循环获取购物车中的商品信息,打印展示给用户

@common.login_auth
def check_shop_car():
    # 1.直接调用查看购物车接口
    flag, msg = shop_interface.check_shop_car_interface(is_login.get('username'))
    if flag:  # msg = {'商品名称':[个数,单价]}
        for name, data_list in msg.items():
            print(f"商品:{name} | 商品个数:{data_list[0]} | 商品单价:{data_list[1]}")
    else:
        print(msg)

12.结算购物车pay_shop_car

​ (1)调用第二层接口 shop_interface 文件中的 pay_shop_car_interface,传入获取登录用户的用户名username

@common.login_auth
def pay_shop_car():
    flag, msg = shop_interface.pay_shop_car_interface(is_login.get('username'))
    print(msg)

13.管理员功能

@common.login_auth
def admin():
    pass

14.功能字典和选择功能函数

# 功能字典,供run函数调用对应编号的功能
func_dict = {
    '1': register,
    '2': login,
    '3': check_balance,
    '4': withdraw,
    '5': pay_back,
    '6': transfer,
    '7': check_flow,
    '8': add_shop_car,
    '9': check_shop_car,
    '10': pay_shop_car,
    '11': admin
}

# 供start.py文件运行的run函数
def run():
    while True:
        print("""
        ====================ATM+购物车==================
        1.注册功能
        2.登陆功能
        3.查看余额
        4.提现功能
        5.还款功能
        6.转账功能
        7.查看流水
        8.添加购物车
        9.查看购物车
        10.结算购物车
        11.管理员功能
        ==============================================
        """)
        choice_num = input('请输入功能编号>>>:').strip()
        if choice_num in func_dict:
            func_dict.get(choice_num)()
        else:
            print('暂无该功能编号')

3.db数据库目录

存放数据库相关文件,包括用户的信息数据

db_handler.py:数据的增删改查功能

1.导入的模块

​ 由于数据的增删改查设计到数据库文件的路径问题

json模块负责将json格数的字符串与py文件的数据进行交互

os模块负责路径的获取拼接

settings配置文件中保存着一些文件的固定路径

import json
import os
from conf import settings

2.数据的保存和修改

​ (1)负责保存用户字典信息,以json格式字符串的形式保存

​ (2)w模式只写模式下,将user_dict写入单用户单文件,以用户名命名其json格式数据信息文件

def save(user_dict):
    username = user_dict.get('username')
    # 5.拼接路径完成用户注册
    user_file_path = os.path.join(settings.DB_DIR, f'{username}.json')
    with open(user_file_path, 'w', encoding='utf8') as f:
        json.dump(user_dict, f, ensure_ascii=False)

3.数据的查询

​ (1)r模式只读模式下,将用户字典信息user_dict,从以用户名命名其json格式数据信息文件中换成dict形式

def select(username):
    user_file_path = os.path.join(settings.DB_DIR, f'{username}.json')
    if os.path.exists(user_file_path):
        # 为了功能的完善 这里如果路径存在则直接返回用户字典
        with open(user_file_path, 'r', encoding='utf8') as f:
            return json.load(f)

4.interface目录:存放接口文件(架构第二层)

1 user_interface.py文件

存放与用户功能相关的接口文件

1.导入的模块

​ (1)db_handler架构的第三层,将数据库中获得数据进行逻辑判断后返回给架构第一层src.py

​ (2)common.py中获取公共功能函数

​ (3)logger添加日志功能

from db import db_handler
from lib import common

logger = common.get_logger('用户模块')

2.register_interface注册功能接口

​ (1)db_handler.select(传入的username)获取用户字典user_dict

​ (2)判断字典是否有值,有值则说明想注册的用户名已经存在

​ (3)加密传入的密码password

​ (4)构造用户字典user_dict

​ (5)将注册用户的默认字典写入用户名.json文件中

​ (6)记录日志:用户注册

​ (7)返回给架构第一层:第二层逻辑判断的结果

def register_interface(username, password):
    # 3.校验用户名是否已存在
    user_dict = db_handler.select(username)
    if user_dict:
        return False, f'用户名{username}已存在'
    # 密码加密处理
    hash_pwd = common.get_hash(password)
    # 4.构造用户字典
    user_dict = {
        'username': username,
        'password': hash_pwd,
        'balance': 15000,
        'shop_car': {},
        'is_lock': False,
        'water_flow': []
    }
    db_handler.save(user_dict)
    logger.info(f'用户{username}注册功能')
    return True, f'用户{username}注册功能'

3.login_interface登录接口

​ (1)db_handler.select(传入的username)获取用户字典user_dict

​ (2)判断字典是否有值,无值则说明想登录的用户名不存在

​ (3)加密传入的密码password

​ (4)判断用户字典user_dict中的密码和登录填写的密码是否一致

​ (5)一致则登录成功

​ (6)记录日志:用户登录

​ (7)返回给架构第一层:第二层逻辑判断的结果

def login_interface(username, password):
    # 1.先查询是否有当前用户名对应的用户数据
    user_dict = db_handler.select(username)
    if not user_dict:
        return False, f'当前用户{username}不存在 无法完成登录'
    # 2.用户名正确 比对密码是否一致
    hash_pwd = common.get_hash(password)
    if user_dict.get('password') == hash_pwd:
        logger.info(f'{username}登录成功')
        return True, '登录成功'
    return False, '密码错误'

2 bank_interface.py文件

1.导入的模块

​ (1)db_handler架构的第三层,将数据库中获得数据进行逻辑判断后返回给架构第一层src.py

​ (2)settings.py中获取配置信息

​ (3)common.py中获取公共功能函数

​ (4)导入time模块,记录流水信息

​ (5)logger添加日志功能,记录‘银行模块’日志

from db import db_handler
from conf import settings
from lib import common
import time

logger = common.get_logger('银行模块')

2.check_balance_interface查询余额接口

​ (1)db_handler.select(传入的username)获取用户字典user_dict

​ (2)获取用户字典user_dict中的余额balance信息

​ (3)记录日志:用户查询账户余额

​ (4)返回给架构第一层:第二层逻辑判断的结果

def check_balance_interface(username):
    # 1.查询当前登录用户的字典数据
    user_dict = db_handler.select(username)
    # 2.从字典中获取余额信息并返回给第一层
    user_balance = user_dict.get('balance')
    logger.debug(f'用户{username}查看了自己的账户余额')
    return True, f'尊敬的{username},您目前的账户余额为{user_balance}'

3.withdraw_interface提现功能接口

​ (1)判断提现金额target_money是否是整数或者小数,调用common.py文件中的get_num判断功能

​ (2)db_handler.select(传入的username)获取用户字典user_dict

​ (3)获取用户余额并判断是否满足提现要求,并收取手续费

​ (4)添加账户流水信息

​ (5)记录日志:用户提现

​ (6)返回给架构第一层:第二层逻辑判断的结果

def withdraw_interface(username, target_money):
    flag, value = common.get_num(target_money)
    if not flag:
        return False, '请输入符合要求的金额数字'
    # 1.获取当前登录用户的字典数据
    user_dict = db_handler.select(username)
    # 2.获取用户余额并判断是否满足提现要求  还应该收取手续费
    user_balance = user_dict.get('balance')
    if user_balance >= value * (1 + settings.MONEY_RATE):
        user_dict['balance'] -= value * (1 + settings.MONEY_RATE)
        # 添加账户流水信息
        ctime = time.strftime('%Y-%m-%d %H:%M:%S')
        user_dict['water_flow'].append(f'时间{ctime}:账户提现了{value},收取了手续费{value * settings.MONEY_RATE}')
        db_handler.save(user_dict)

        logger.debug(f'用户{username}提现了{value}')

        return True, f'尊敬的客户{username},您已经提现了{value},手续费{value * settings.MONEY_RATE},账户余额{user_dict.get("balance")}'
    return False, f'尊敬的客户{username}您的账户不够提现哦,请先充值!'

4.pay_back_interface充值功能接口

​ (1)判断提现金额target_money是否是整数或者小数,调用common.py文件中的get_num判断功能

​ (2)db_handler.select(传入的username)获取用户字典user_dict

​ (3)添加账户流水信息

​ (4)保存用户数据

​ (5)记录日志:用户提现

​ (6)返回给架构第一层:第二层逻辑判断的结果

def pay_back_interface(username, target_money):
    flag, value = common.get_num(target_money)
    if not flag:
        return False, '请输入符合要求的金额数字'
    # 1.获取用户字典数据
    user_dict = db_handler.select(username)
    # 2.直接添加余额
    user_dict['balance'] += value
    # 添加流水记录
    ctime = time.strftime('%Y-%m-%d %H:%M:%S')
    user_dict['water_flow'].append(f'时间{ctime}:账户充值了{value},该阶段账户余额{user_dict.get("balance")}')
    # 3.保存用户数据
    db_handler.save(user_dict)

    logger.debug(f'用户{username}充值了{value}')

    return True, f'尊敬的用户{username},您充值了{value},目前账户余额{user_dict.get("balance")}'

5.transfer_interface转账功能接口

​ (1)校验要转账的用户target_user是否存在

​ (2)判断提现金额target_money是否是整数或者小数,调用common.py文件中的get_num判断功能

​ (3)db_handler.select(传入的username)获取当前登录用户的数据user_dict

​ (4)判断当前用户余额是否充足

​ (5)记录账户扣钱的流水

​ (6)记录账户加钱的流水

​ (7)保存当前登录账户的的用户字典current_user_dict

​ (8)保存转账账户的的用户字典target_user_dict

​ (9)记录日志:用户转账的记录

​ (10)返回给架构第一层:第二层逻辑判断的结果

def transfer_interface(current_user, target_user, target_money):
    # 1.先校验目标用户是否存在
    target_user_dict = db_handler.select(target_user)
    if not target_user_dict:
        return False, f'目标用户{target_user}不存在'
    # 2.再校验用户输入的金额是否是整数或者小数
    flag, value = common.get_num(target_money)
    if not flag:
        return False, '请输入符合要求的金额数字'
    # 3.获取当前登录用户的数据
    current_user_dict = db_handler.select(current_user)
    # 4.判断当前用户余额是否充足
    if current_user_dict.get('balance') >= value:
        current_user_dict['balance'] -= value
        # 记录账户扣钱的流水
        ctime = time.strftime('%Y-%m-%d %H:%M:%S')
        current_user_dict['water_flow'].append(f'时间{ctime}:给{target_user}账户转了{value}')
        target_user_dict['balance'] += value
        # 记录账户加钱的流水
        target_user_dict['water_flow'].append(f'时间{ctime}:收{current_user}账户转过来的钱{value}')
        db_handler.save(current_user_dict)
        db_handler.save(target_user_dict)

        logger.debug(f'用户{current_user}给{target_user}账户转了{value}')

        return True, f'尊敬的用户{current_user},您给{target_user}账户转了{value},您目前账户余额为{current_user_dict.get("balance")}'
    return False, '您当前余额不够转账'

3 shop_interface.py文件

1.导入的模块

​ (1)db_handler架构的第三层,将数据库中获得数据进行逻辑判断后返回给架构第一层src.py

​ (2)common.py中获取公共功能函数

​ (3)导入time模块,记录流水信息

​ (4)logger添加日志功能,记录‘购物车模块’日志

from db import db_handler
from lib import common
import time

logger = common.get_logger('购物车模块')

2.add_shop_car_interface添加购物车接口

​ (1)构造临时字典存储商品信息

while 循环:

​ (2)获取商品信息good_list

​ (3)循环打印商品信息供用户选择

​ (4)获取用户输入的商品编号

​ (5)添加退出添加购物车,保存购物车信息

​ 1)获取当前登录用户的字典数据

​ 2)获取字典中的old_shop_car

​ 3)循环获取临时购物车temp_shop_car中的商品信息,并判断临时购物车中的商品是否在用户字典中的old_shop_car中重复了,重复了则相加数量,不存在则新增商品与信息

​ 4)更新购物车信息,保存进用户字典user_data_dict中

​ 5)将用户字典user_data_dict传给数据库保存db_handler.save

​ 6)添加日志:用户添加购物车

​ (6)判断编号是否是纯数字

​ (7)判断编号是否是超出范围

​ (8)根据商品编号获取商品信息

​ (9)获取想要购买的商品个数

​ (10)判断本次添加的商品是否在用户字典中的temp_shop_car中重复了,重复了则相加数量,不存在则新增商品与信息

def add_shop_car_interface(username):
    # 8.构造临时小字典存储商品信息
    temp_shop_car = {}
    while True:
        # 1.获取商品信息(目前是写死的 后期可以动态获取)
        good_list = [
            ['挂壁面', 3],
            ['印度飞饼', 22],
            ['极品木瓜', 666],
            ['土耳其土豆', 999],
            ['伊拉克拌面', 1000],
            ['董卓戏张飞公仔', 2000],
            ['仿真玩偶', 10000]
        ]
        # 2.循环打印商品信息供用户选择
        for num, good_data in enumerate(good_list):  # 0 []
            print(f"商品编号:{num}      |       商品名称:{good_data[0]}     |     商品单价:{good_data[1]}")
        # 3.获取用户输入的商品编号
        choice_num = input('请输入您想要购买的商品编号(q)>>>:').strip()
        '''10.添加结束标志 用于保存购物车数据'''
        if choice_num == 'q':
            # 11.获取当前登录用户的字典数据
            user_data_dict = db_handler.select(username)
            old_shop_car = user_data_dict.get('shop_car')  # {'印度飞饼':[10, 22]}
            # 12.保存购物车数据
            for g_name, g_list in temp_shop_car.items():
                if g_name in old_shop_car:
                    old_shop_car[g_name][0] += temp_shop_car[g_name][0]
                else:
                    old_shop_car[g_name] = g_list
            user_data_dict['shop_car'] = old_shop_car
            db_handler.save(user_data_dict)
            logger.info(f'{username}用户添加购物车成功')
            return True, '添加购物车成功 欢迎下次再来'
        # 4.判断编号是否是纯数字
        if not choice_num.isdigit():
            print('商品编号必须是纯数字')
            continue
        choice_num = int(choice_num)
        # 5.判断数字是否超出范围
        if choice_num not in range(len(good_list)):
            print('商品编号不在已存在的商品编号内 无法选择购买')
            continue
        # 6.根据商品编号获取商品信息
        target_good_list = good_list[choice_num]  # ['印度飞饼', 22]
        # 7.获取想要购买的商品个数
        good_num = input(f'请输入您想要购买的{target_good_list[0]}的商品数量>>>:').strip()
        if not good_num.isdigit():
            print('商品数量必须是纯数字')
            continue
        good_num = int(good_num)
        # 9.写入临时小字典中
        good_name = target_good_list[0]

        if good_name in temp_shop_car:
            temp_shop_car.get(good_name)[0] += good_num
        else:
            temp_shop_car[good_name] = [good_num, target_good_list[1]]

2.check_shop_car_interface查看购物车接口

​ (1)db_handler.select(传入的username)获取当前登录用户的数据user_data_dict

​ (2)获取当前用户购物车数据

​ (3)判断当前用户购物车是否为空

​ (4)记录日志:用户查看了购物车数据

​ (5)返回给架构第一层:第二层逻辑判断的结果

def pay_shop_car_interface(username):
    user_data_dict = db_handler.select(username)
    # 3.获取当前用户购物车数据及账户余额
    shop_car = user_data_dict.get('shop_car')  # {'印度飞饼':[10, 22],'公仔':[100, 100]}
    if not shop_car:
        return False, '购物车空空如也'
    current_balance = user_data_dict.get('balance')
    # 4.统计购物车商品总价
    total_money = 0
    for g_list in shop_car.values():  # [10, 22]     [100, 100]
        total_money += g_list[0] * g_list[1]
    # 5.比较余额是否充足
    if total_money > current_balance:
        return False, '你个穷逼 账户余额不够 再想办法 噶腰子去!!!'
    user_data_dict['balance'] -= total_money
    ctime = time.strftime('%Y-%m-%d %X')
    user_data_dict['water_flow'].append(f'时间{ctime}:购物消费了{total_money}')
    # 6.清空购物车
    user_data_dict['shop_car'] = {}
    logger.info(f'{username}疯狂消费了{total_money}')
    db_handler.save(user_data_dict)
    return True, f'尊敬的{username} 您本次消费{total_money} 卡上余额剩余{user_data_dict.get("balance")} 欢迎下次再来挥霍!!!'

3.pay_shop_car_interface结算功能接口

​ (1)db_handler.select(传入的username)获取当前登录用户的数据user_data_dict

​ (2)获取当前用户购物车数据

​ (3)判断当前用户购物车是否为空

​ (4)获取当前账户余额

​ (5)统计购物车商品总价

​ (6)比较余额是否充足

​ (7)记录用户流水:用户消费的商品总价

​ (8)清空购物车

​ (9)记录日志:用户消费金额

​ (10)保存user_data_dict更新进用户文件

​ (11)返回给架构第一层:第二层逻辑判断的结果

def pay_shop_car_interface(username):
   user_data_dict = db_handler.select(username)
   # 3.获取当前用户购物车数据及账户余额
   shop_car = user_data_dict.get('shop_car')  # {'印度飞饼':[10, 22],'公仔':[100, 100]}
   if not shop_car:
       return False, '购物车空空如也'
   current_balance = user_data_dict.get('balance')
   # 4.统计购物车商品总价
   total_money = 0
   for g_list in shop_car.values():  # [10, 22]     [100, 100]
       total_money += g_list[0] * g_list[1]
   # 5.比较余额是否充足
   if total_money > current_balance:
       return False, '你个穷逼 账户余额不够 再想办法 噶腰子去!!!'
   user_data_dict['balance'] -= total_money
   ctime = time.strftime('%Y-%m-%d %X')
   user_data_dict['water_flow'].append(f'时间{ctime}:购物消费了{total_money}')
   # 6.清空购物车
   user_data_dict['shop_car'] = {}
   logger.info(f'{username}疯狂消费了{total_money}')
   db_handler.save(user_data_dict)
   return True, f'尊敬的{username} 您本次消费{total_money} 卡上余额剩余{user_data_dict.get("balance")} 欢迎下次再来挥霍!!!'

5.lib目录:项目公共功能目录

common.py项目公共功能文件

import hashlib  # 加密模块
from core import src  # 获取登录用户的用户名
import logging  # 日志模块
import logging.config
from conf import settings  # 配置文件的固定路径


# 加密功能函数
def get_hash(msg):
    md5 = hashlib.md5()
    md5.update(msg.encode('utf8'))
    return md5.hexdigest()

  
# 校验用户登录功能装饰器
def login_auth(func_name):
    def inner(*args, **kwargs):
        if src.is_login.get('username'):
            res = func_name(*args, **kwargs)
            return res
        else:
            print('您暂未登录 请先去登录')
            src.login()

    return inner


# 判断输入的是否为整数和小数  
def get_num(target_money):
    try:
        target_money = float(target_money)
    except ValueError:
        return False, '请输入整数或者小数'
    else:
        return True, target_money


# 记录日志功能      
def get_logger(msg):
    logging.config.dictConfig(settings.LOGGING_DIC)  # 自动加载字典中的配置
    logger1 = logging.getLogger(msg)
    return logger1

posted @ 2022-10-31 21:02  Duosg  阅读(49)  评论(0编辑  收藏  举报