1.Python 练习 ATM + 购物车

0.ATM + 购物车 讲解

模拟ATM+购物商城

1.开发模式

1.开发项目的模式
	1.瀑布模式
        项目开发完成之后,一并提测
	2.敏捷开发
		开发一个功能,测试一个功能

2.项目要求

0.额度15000 或自定义
1.购物商城 ,买东西 添加到购物车 调用信用卡接口结账
2.提现 手续费5%
3.支持多用户登入
4.用户之间转账
5.记录每日流水
6.提供还款接口
7.ATM操作记录
8.提供管理接口,添加账户,用户额度 冻结账户等
9.用户认证装饰器
10.退出系统

3.程序设计或架构设计

1.语言选择
2.需求转功能
    1.注册功能
    2.登入功能 装饰器 日志
    3.存款功能 流水 日志
    4.取款功能 流水 日志
    5.转账功能 流水 日志
    6.查询账单  日志
    # 购物车
    7.购物功能  日志
    8.看购物车  日志
    9.购物结账 流水 日志
    10.退出系统 
3.分任务模块开发
4.测试
5.上线

4.软件目录创建

写了一个自动创建目录的程序,在执行文件所在目录创建项目,
项目的名称是 Project + num,num起始为1,文件存在num+1.
Project1
|--bin           
|	|--start.py       启动程序
|--conf
|    |--setting.py    配置文件
|--core
|    |--src.py        核心文件
|---db
|    |--admin.json    数据文件
|--lib
|    |--common.py     公用文件
|--log
|    |--log.log       日志文件
|--readme.txt         项目说明
|--requirements.txt   项目需要的第三方库
import os

# 1.获取执行文件所在目录
BASE_DIR = os.path.dirname(__file__)
print(BASE_DIR)
# 2.查看当前目录下所有文件/文件夹名称
dir_list = os.listdir(BASE_DIR)
print(dir_list)
# 拼接目录


# 起始是1
num = 1
while True:
    # 项目的名称是 Project + num ,如果文件存在则  num += 1
    join_path = os.path.join(BASE_DIR, 'Project' + str(num))

    if not os.path.exists(join_path):
        os.mkdir(join_path)
        print('创建的项目名字为%s' % 'Project' + str(num))
        break
    num += 1

    
# 以项目目录为基础
BASE_DIR = os.path.join(BASE_DIR, 'Project' + str(num))
# 创建文件夹
dir_list = ['bin', 'conf', 'core', 'db', 'lib', 'log']  # 6个文件夹

for dir_name in dir_list:
    dir_path = os.path.join(BASE_DIR, dir_name)
    if not os.path.exists(dir_path):
        os.mkdir(dir_path)

        
# 文件夹内对应的py文件以及txt,log 文件
file_internal_list = ['start.py', 'setting.py', 'src.py', 'admin.json', 'common.py', 'log.log']

for file, dire in zip(file_internal_list, dir_list):
    dir_path = os.path.join(BASE_DIR, dire, file)
    if not os.path.isfile(dir_path):
        with open(dir_path, mode='w', encoding='utf8') as f0:
            pass

        
# 项目文件 和 安装第三方库文件
file_list = ['readme.txt', 'requirements.txt']

for file in file_list:
    dir_path = os.path.join(BASE_DIR, file)
    if not os.path.isfile(dir_path):
        with open(dir_path, mode='w', encoding='utf8') as f1:
            pass

5.启动文件

bin ---> start.py        启动文件
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)

在这个文件中将项目所在的路径添加到sys.path中,
不然在交互式环境下使用form语句导模块会找不到模块.

pycharm会自动添加这个语句.
import os
import sys

"""
__file__ 执行文件当时所有的路径
os.path.dirname()获取某个文件的目录
__file__ 为start.py的绝对路径, os.path.dirname 拿到 start.py 的目录 bin的绝对路径
在套一层 拿到 ATM的的绝对路径
"""
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)

# 导入主程序
from core.src import main


# 启动程序
if __name__ == '__main__':
    main()

6.核心文件

core ---> src.py

1.函数      --->   功能
2.功能字典  --->   存函数名
3.主程序    --->   功能入口
函数名可以容器类型的元素.
函数名加括号进行调用.

func_dic = {
    
     '1': ['注册功能', registered_user], ```}
编号作为键,输入1,字符串类型

if '1' in 字典{
    
    '1'} 输入'1' - '10' 就按键取值,值是一个列表 ['', registered_user]
列表索引0是要打印的信息         func_dic[][索引0]
列表索引1是需要加括号调用的函数  func_dic[][索引1]()
# 1.注册用户
def registered_user():
    while True:
        print('注册用户'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志
        pass
        if input('按下(q)退出注册,否则任意输入继续注册\n请输入>>>:') == 'q':
            break


# 2.登入功能
def login_function():
    while True:
        print('登入功能'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志
        pass
        if input('按下(q)退出登入,否则任意输入继续登入\n请输入>>>:') == 'q':
            break


# 3.存款功能
def deposit_function():
    while True:
        print('存款功能'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志&流水
        pass
        if input('按下(q)退出存款,否则任意输入继续存款\n请输入>>>:') == 'q':
            break


# 4.取款功能
def withdrawal_function():
    while True:
        print('取款功能'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志&流水
        pass
        if input('按下(q)退出取款,否则任意输入继续取款\n请输入>>>:') == 'q':
            break


# 5.转账功能
def transfer_function():
    while True:
        print('转账功能'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志&流水
        pass
        if input('按下(q)退出转账,否则任意输入继续转账\n请输入>>>:') == 'q':
            break


# 6.查询账单
def check_bill():
    while True:
        print('查询账单'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志
        pass
        if input('按下(q)退出查询,否则任意输入继续查询\n请输入>>>:') == 'q':
            break


# 7.购物功能
def shopping_function():
    while True:
        print('购物功能'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志
        pass
        if input('按下(q)退出购物,否则任意输入继续购物\n请输入>>>:') == 'q':
            break


# 8.看购物车
def see_shopping_cart():
    while True:
        print('查看购物车'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志
        pass
        if input('按下(q)退出查看,否则任意输入继续查看\n请输入>>>:') == 'q':
            break


# 9.购物结账
def shopping_checkout():
    while True:
        print('购物结账'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志&流水
        pass
        if input('按下(q)退出结账,否则任意输入继续结账\n请输入>>>:') == 'q':
            break


# 10.退出系统
def exit_system():
    while True:
        print('退出系统'.center(30, '-'))
        # 业务逻辑
        pass
        # 日志
        pass
        if input('按下(q)退出系统,否则任意输入返回功能面板\n请输入>>>:') == 'q':
            break


# 功能字典
func_dic = {
    
    
    # AMT
    '1': ['注册功能', registered_user],
    '2': ['登入功能', login_function],
    '3': ['存款功能', deposit_function],
    '4': ['取款功能', withdrawal_function],
    '5': ['转账功能', transfer_function],
    '6': ['查询账单', check_bill],
    # 购物车
    '7': ['购物功能', shopping_function],
    '8': ['看购物车', see_shopping_cart],
    '9': ['购物结账', shopping_checkout],
    '10': ['退出系统', exit_system]
}


# 主程序
def main():
    while True:
        print('我的小商店'.center(30, '-'))
        # 展示功能面板
        for func in func_dic:
            print('({}) - - - > {}'.format(func, func_dic[func][0]))

        # 功能选择
        func_key = input('输入功能编号>>>:').strip()

        # 判断输入是否存在
        if func_key in func_dic:
            # 键 存在则 执行键对应的函数
            func_dic[func_key][1]()
        # 键 不存在
        else:
            print('该功能未开放!,请重新选择!')
主要功能

image-20211201173100177

展示

image-20211201173001081

7.注册功能

7.1代码

core --> src.py  核心文件
用户注册 用户信息存在字典中,在通过json模块转为json格式字符串存入文件中.
注意:数据中有中文时,使用json模块中文会转为unicode编码.(\u开头)
{
    
    'user': '', 'pwd': '', }
# core --> src.py
import time
from conf.setting import join_path, create_log
from lib.common import writer_file


# 1.注册用户
def registered_user():
    while True:
        print('注册用户'.center(30, '-'))
        # 业务逻辑
        """
         存储数据存储的格式 
         用户名         密码        存款           冻结账户标识       账单        收藏-->购物车
        {'name': '', 'pwd': '', 'deposit': 15000, 'freeze': False , 'bill': [], collect: {}}
        """

        name = input('请输入用户名称>>>:').strip()

        """
        调用函数进行 路径拼接
        将用户名作为参数传给变量,进行路径拼接并判断文件是否存在
        返回:
        is_exist 为布尔值 路径存在为 True
        user_path 用户名称拼接的文件路径
        """
        is_exist, user_path = join_path(name)
        if is_exist:
            print('用户已经存在,请重新输入!')
            continue

        pwd = input('请输入用户密码>>>:').strip()
        user_info_dic = {
    
    'name': name, 'pwd': pwd, 'deposit': 15000, 'freeze': False, 'bill': [], 'collect': {
    
    }}

        """
        调用函数  -->  写入数据 
        之前就通过判断文件是否存在,做好了文件的绝对路径
        """
        writer_file(user_path, user_info_dic)

        # 日志
        logger1 = create_log('注册用户')
        logger1.info('用户%s注册成功!' % name)
        # 睡一秒,等日志展示,先展示
        time.sleep(1)
        if input('按下(q)退出注册,否则任意输入继续注册\n请输入>>>:') == 'q':
            break
 conf ---> setting.py 存配置文件
#  conf ---> setting.py
import os
import logging
import logging.config

# 获取项目目录
BASE_DIR = os.path.dirname(os.path.dirname(__file__))


# 以名称拼接db下的用户路径
def join_path(name):
    """
    传入用户名称拼接路径

    判断用户是否存在
    用户数据文件是以用户的名字命令
    思路:将用户的名字进行拼接,
    通过判断文件是否存在而得出用户名时候被使用

    """
    user_path = os.path.join(BASE_DIR, 'db', '%s.json' % name)
    is_exist = os.path.exists(user_path)
    return is_exist, user_path

"""
日志文文件
向 终端输出一份  简单格式
向: logfile_path = os.path.join(BASE_DIR, 'db', 'log.log') 写一份  标准格式
只修改 logfile_path的路径就好其它的cv大法就好了
"""

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

# 简单格式
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]  信息: %(message)s'

# 日志的路径
logfile_path = os.path.join(BASE_DIR, 'log', 'log.log')

# 配置字典
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'  # 使用的格式
        },
        # 打印到文件的日志,收集DEBUG及以上的日志
        'default': {
    
    
            'level': 'DEBUG',  # 级别
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',  # 使用的格式
            'filename': logfile_path,  # 日志文件的路径使用外部变量
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,  # 五个5M的文件 第五个满了 把最开始的第一个文件干掉
            'encoding': 'utf8',  # 日志文件的编码,避免乱码了
        },
    },

    # 记录
    'loggers': {
    
    
        # logging.getLogger(__name__)拿到的logger配置  空字符串作为键 能够兼容所有的日志
        '': {
    
    
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)传递
        },  # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
    },
}


# 使用配置字典
def create_log(name):
    """
    :param name: 函数名字
    :return: logger1
    使用: logger1 = create_log('功能的名字')
    logger1.DEBUG('描述信息')
   
    """
    logging.config.dictConfig(LOGGING_DIC)  # 自动加载字典中的配置
    logger1 = logging.getLogger(name)
    return logger1  # 在使用处 logger.级别('信息')

lib --> common.py  公用文件
# lib --> common.py
# 模块
import json


# 依据路径写入用户的信息
def writer_file(user_path, user_info_dic):
    with open(user_path, mode='w', encoding='utf8') as f:
        json.dump(user_info_dic, f)

# 依据路径读取用户的信息
def read_file(user_path):
    with open(user_path, mode='r', encoding='utf8') as f1:
        user_info_dic = json.load(f1)
        return user_info_dic

7.2测试

测试输入

image-20211201204158933

生成两个文件
{
    
    "name": "kid", "pwd": "123", "deposit": 15000, "freeze": false, "bill": [], "collect": {
    
    }}
[INFO][2021-12-01 20:41:42,964][MainThread:8388][func:注册用户][src.py:42][message:用户kid注册成功!]

8.登入功能

8.1代码

# 用户登入状态字典
user_login = {
    
    
    'user': '',
    'is_login': False
}


# 2.登入功能
def login_function():
    if not user_login['is_login']:
        while True:
            print('登入功能'.center(30, '-'))
            name = input('用户名称>>>:')
            pwd = input('用户密码>>>:')
    
            # 调用函数判断用户是否存在
            is_exist, user_path = join_path(name)
            # 判断文件是否存在
            if is_exist:
                # 读取文件检验密码
                user_info_dic = read_file(user_path)
                # 判断密码是否正确
                if pwd == user_info_dic.get('pwd'):
                    # 修改用户登入状态字典
                    user_login['user'] = name
                    user_login['is_login'] = True
                    # 日志
                    time.sleep(1)
                    logger1 = create_log('登入功能')
                    logger1.debug('用户%s登入成功' % name)
                    break
                else:
                    print('用户名或密码错误')
            else:
                print('用户名或密码错误')

            if input('按下(q)退出登入,否则任意输入继续登入\n请输入>>>:') == 'q':
                break
    else:
        print('已经有用户登入!可以先退出程序在次启动进行登入!')

8.2登入装饰器

# 2.1登入装饰器
def login_decor(func):
    def inner(*args, **kwargs):
        # 查看登入状态 为True 则说明用户已经登入了直接执行被装饰的函数
        if user_login['is_login']:
            # 进入函数的日志
            logger1 = create_log(run_func['run'])
            logger1.debug('登入 %s' % run_func['run'])
            time.sleep(1)
            res = func(*args, **kwargs)
            logger1 = create_log(run_func['run'])
            # 退出函数的日志
            logger1.debug('退出 %s' % run_func['run'])
            time.sleep(1)
            return res
        # 否则直接进入登入函数
        else:
            print('还没有用户登入请先登入'.center(30, '-'))
            login_function()
            # 如果登入成功 则执行上次选择的函数
            if user_login['is_login']:
                # 进入函数的日志
                logger1 = create_log(run_func['run'])
                logger1.debug('登入 %s' % run_func['run'])
                time.sleep(1)
                res = func(*args, **kwargs)
                # 退出函数的日志
                logger1.debug('退出 %s' % run_func['run'])
                time.sleep(1)
                return res
            # 如在没有登入成功是按q结束来登入程序 则直接return放回界面
            else:
                return

    return inner

8.3添加装饰器

为功能 3-10 添加装饰器
# 记录运行的函数名字 装饰器使用
run_func = {
    
    'run': ''}

# 主程序
def main():
    while True:
        print('我的小商店'.center(30, '-'))
        # 展示功能面板
        for func in func_dic:
            print('({}) - - - > {}'.format(func, func_dic[func][0]))

        # 功能选择
        func_key = input('输入功能编号>>>:').strip()

        # 判断输入是否存在
        if func_key in func_dic:
            # 键 存在则 执行键对应的函数

            # 记录运行的函数名字 装饰器使用
            run_func['run'] = func_dic[func_key][0]

            # 加装饰器执行
            if int(func_key) > 2:
                @login_decor
                def func():
                    """
                    定义一个函数为 功能 3-10 添加装饰器
                    """
                    func_dic[func_key][1]()
                func()
            else:
                # 不加装饰器执行
                func_dic[func_key][1]()
        # 键 不存在
        else:
            print('该功能未开放!,请重新选择!')

9.存款功能

9.1代码

# 3.存款功能
def deposit_function():
    while True:
        print('存款功能'.center(30, '-'))
        # 获取输入
        money = input('存款的金额为>>>:').strip()
        # 存数字判断
        if not money.isdigit():
            # 输入不合法
            continue
        # 路径拼接
        is_exist, user_path = join_path(user_login['user'])
        # 读文件 拿到用户的数据
        user_info_dic = read_file(user_path)

        # 钱 += 钱
        user_info_dic['deposit'] += int(money)
        # 流水 存储格式 时间
        new_time = time.strftime('%Y-%m-%d %X')
        info_str = '%s 用户%s存款%s元.' % (new_time, user_login['user'], money)
        user_info_dic['bill'].append(info_str)
        # 覆写文件
        writer_file(user_path, user_info_dic)

        # 日志
        logger1 = create_log(user_login['user'])
        logger1.debug(info_str)
        time.sleep(1)
        if input('按下(q)退出存款,否则任意输入继续存款\n请输入>>>:') == 'q':
            break

9.2测试

输入功能编号>>>:3
---------还没有用户登入请先登入----------
-------------登入功能-------------
用户名称>>>:kid
用户密码>>>:123
[DEBUG][2021-12-02 15:44:21,123][src.py:80]  信息: 用户kid登入成功
[DEBUG][2021-12-02 15:44:22,123][src.py:117]  信息: 登入 存款功能
-------------存款功能-------------
存款的金额为>>>:1500
[DEBUG][2021-12-02 15:44:27,342][src.py:158]  信息: 2021-12-02 15:44:27 用户kid存款1500.
按下(q)退出存款,否则任意输入继续存款
请输入>>>:q
[DEBUG][2021-12-02 15:44:29,871][src.py:121]  信息: 退出 存款功能

10.取款

10.1代码

# 4.取款功能
def withdrawal_function():
    while True:
        # 获取输入
        money = input('取款的金额为>>>:').strip()
        # 存数字判断
        if not money.isdigit():
            # 输入不合法
            print('输入不合法')
            continue
        # 路径拼接
        is_exist, user_path = join_path(user_login['user'])
        # 读文件 拿到用户的数据
        user_info_dic = read_file(user_path)

        if user_info_dic['deposit'] >= (int(money) * 1.05):
            # 钱 -= 钱
            user_info_dic['deposit'] += (int(money) * 1.05)
            # 流水 存储格式
        
            new_time = time.strftime('%Y-%m-%d %X')
            info_str = '%s 用户%s取款%s元, 手续费%s元' % (new_time, user_login['user'], money, (int(money) * 0.05))
            user_info_dic['bill'].append(info_str)
            # 覆写文件
            writer_file(user_path, user_info_dic)

            # 日志
            logger1 = create_log(user_login['user'])
            logger1.debug(info_str)
            time.sleep(1)
        else:
            print('余额不足')
        if input('按下(q)退出取款,否则任意输入继续取款\n请输入>>>:') == 'q':
            break

10.2测试

输入功能编号>>>:4
---------还没有用户登入请先登入----------
-------------登入功能-------------
用户名称>>>:kid
用户密码>>>:123
[DEBUG][2021-12-02 15:45:16,493][src.py:80]  信息: 用户kid登入成功
[DEBUG][2021-12-02 15:45:17,507][src.py:117]  信息: 登入 取款功能
取款的金额为>>>:4
[DEBUG][2021-12-02 15:45:19,682][src.py:193]  信息: 2021-12-02 15:45:19 用户kid取款4, 手续费0.2
按下(q)退出取款,否则任意输入继续取款
请输入>>>:q
[DEBUG][2021-12-02 15:45:32,184][src.py:121]  信息: 退出 取款功能

11.转账功能

11.代码

# 5.转账功能
def transfer_function():
    while True:
        print('转账功能'.center(30, '-'))
        # 业务逻辑
        to_user = input('输入对方的账户>>>:').strip()
        # 对方账户的路径
        to_is_exist, to_user_path = join_path(to_user)
        # 对方账户是否存在
        if not to_is_exist:
            print('对方账户不存在,请重新输入>>>:')
            continue

        # 转账的金额
        money = input('输入转账的金额>>>:').strip()
        if not money.isdigit():
            print('输入的不是纯数字!')
            continue

        # 当前账户的路径
        my_is_exist, my_user_path = join_path(to_user)
        # 当前账户的数据
        my_info_dic = read_file(my_user_path)
        # 判断余额是否够
        if not my_info_dic['deposit'] >= int(money):
            print('余额不足!')
            continue
        # 对方账户的数据
        to_info_dic = read_file(to_user_path)

        # 我减 他加
        my_info_dic['deposit'] -= int(money)
        to_info_dic['deposit'] += int(money)

        # 流水 存储格式 时间
        new_time = time.strftime('%Y-%m-%d %X')
        my_info_str = '%s 用户%s向用户%s转账%s元.' % (new_time, user_login['user'], to_user, money)
        to_info_str = '%s 用户%s收到用户%s转账%s元.' % (new_time, user_login['user'], to_user, money)

        # 添加账单
        my_info_dic['bill'].append(my_info_str)
        to_info_dic['bill'].append(to_info_str)

        # 将数据写入文件
        writer_file(my_user_path, my_info_dic)
        writer_file(to_user_path, to_info_dic)

        # 日志
        logger1 = create_log(user_login['user'])
        logger1.debug(my_info_str)
        time.sleep(1)
        if input('按下(q)退出转账,否则任意输入继续转账\n请输入>>>:') == 'q':
            break

11.2测试

输入功能编号>>>:5
---------还没有用户登入请先登入----------
-------------登入功能-------------
用户名称>>>:kid
用户密码>>>:123
[DEBUG][2021-12-02 15:46:46,697][src.py:80]  信息: 用户kid登入成功
[DEBUG][2021-12-02 15:46:47,698][src.py:117]  信息: 登入 转账功能
-------------转账功能-------------
输入对方的账户>>>:qq
输入转账的金额>>>:123
[DEBUG][2021-12-02 15:46:53,739][src.py:250]  信息: 2021-12-02 15:46:53 用户kid向用户qq转账123.
按下(q)退出转账,否则任意输入继续转账
请输入>>>:q
[DEBUG][2021-12-02 15:46:56,633][src.py:121]  信息: 退出 转账功能

12.查询账单

12.1代码

# 6.查询账单
def check_bill():
    while True:
        print('查询账单'.center(30, '-'))
        # 获取路径
        is_exist, user_path = join_path(user_login['user'])
        # 显示当前登入用户的账单
        user_info_dic = read_file(user_path)

        # for 遍历日志
        for log in user_info_dic['bill']:
            print(log)
        # 日志
        new_time = time.strftime('%Y-%m-%d %X')
        my_info_str = '%s 用户%s查看账单.' % (new_time, user_login['user'])
        logger1 = create_log(user_login['user'])
        logger1.debug(my_info_str)
        time.sleep(1)
        if input('按下(q)退出查询,否则任意输入继续查询\n请输入>>>:') == 'q':
            break

12.2测试

输入功能编号>>>:6
---------还没有用户登入请先登入----------
-------------登入功能-------------
用户名称>>>:kid
用户密码>>>:123
[DEBUG][2021-12-02 15:45:55,922][src.py:80]  信息: 用户kid登入成功
[DEBUG][2021-12-02 15:45:56,933][src.py:117]  信息: 登入 查询账单
[DEBUG][2021-12-02 15:45:57,947][src.py:272]  信息: 2021-12-02 15:45:57 用户kid查看账单.
-------------查询账单-------------
2021-12-02 15:40:19 用户kid存款15.
2021-12-02 15:44:27 用户kid存款1500.
2021-12-02 15:45:19 用户kid取款4, 手续费0.2
按下(q)退出查询,否则任意输入继续查询
请输入>>>:q
[DEBUG][2021-12-02 15:46:00,940][src.py:121]  信息: 退出 查询账单

13.购物功能

13.1代码

# 7.购物功能
def shopping_function():
    # 定义一个购物车
    shopping_cart = {
    
    }
    while True:
        print('购物功能'.center(30, '-'))
        # 业务逻辑
        # 定义一个商品字典
        goods = {
    
    
            '1': ['苹果', 4.5],
            '2': ['香蕉', 3.0],
            '3': ['菠萝', 3.5],
            '4': ['梨子', 3.6],
            '5': ['李子', 3.2],
            '6': ['桃子', 5.2],
            '7': ['葡萄', 15.6],
            '8': ['榴莲', 23.60],
            '9': ['椰子', 30.05],
            '10': ['西瓜', 32.26]
        }

        # 展示商品
        for key in goods:
            print('({}) ---> {}  价格: {} 元.'.format(key, goods[key][0], goods[key][1]))
        choice = input('输入商品的编号进行购物>>>:')

        if choice in goods:
            if choice in shopping_cart:
                shopping_cart[choice][2] += 1
                # 显示购物车
                print(shopping_cart)
            else:
                shopping_cart[choice] = goods[choice]
                shopping_cart[choice].append(1)
                # 显示购物车
                print(shopping_cart)

        if input('按下(q)退出购物,否则任意输入继续购物\n请输入>>>:') == 'q':
            # 将数据写入文件

            # 获取路径
            is_exist, user_path = join_path(user_login['user'])

            # 显示当前登入用户的账单
            user_info_dic = read_file(user_path)
            # 修改文件中 购物车 的数据
            user_info_dic['collect'] = shopping_cart

            # 写入文件
            writer_file(user_path, user_info_dic)

            # 日志
            new_time = time.strftime('%Y-%m-%d %X')
            my_info_str = '%s 用户%s收藏购物车商品.' % (new_time, user_login['user'])
            logger1 = create_log(user_login['user'])
            logger1.debug(my_info_str)
            time.sleep(1)
            break

13.2测试

-------------登入功能-------------
用户名称>>>:kid
用户密码>>>:123
[DEBUG][2021-12-02 16:34:21,729][src.py:80]  信息: 用户kid登入成功
[DEBUG][2021-12-02 16:34:22,737][src.py:117]  信息: 登入 购物功能
输入商品的编号进行购物>>>:1
{
    
    '1': ['苹果', 4.5, 1]}
---
输入商品的编号进行购物>>>:2
{
    
    '1': ['苹果', 4.5, 1], '2': ['香蕉', 3.0, 1]}
----
输入商品的编号进行购物>>>:2
{
    
    '1': ['苹果', 4.5, 1], '2': ['香蕉', 3.0, 2]}
---
输入商品的编号进行购物>>>:3
{
    
    '1': ['苹果', 4.5, 1], '2': ['香蕉', 3.0, 2], '3': ['菠萝', 3.5, 1]}
按下(q)退出购物,否则任意输入继续购物
请输入>>>:q
[DEBUG][2021-12-02 16:34:47,219][src.py:333]  信息: 2021-12-02 16:34:47 用户kid收藏购物车商品.
[DEBUG][2021-12-02 16:34:48,226][src.py:121]  信息: 退出 购物功能

14.查看购物车功能

14.1代码

# 8.看购物车
def see_shopping_cart():
    while True:
        print('查看购物车'.center(30, '-'))
        # 查看购物车
        # 获取路径
        is_exist, user_path = join_path(user_login['user'])

        # 显示当前登入用户的账单
        user_info_dic = read_file(user_path)
        # 读取 购物车 的数据
        collect = user_info_dic['collect']
        # 判断购物车是否为空
        if collect:
            for key in collect:
                print('({}) ---> {}  价格: {} 元  数量: {}.'.format(key, collect[key][0], collect[key][1],
                                                               collect[key][2]))
        else:
            print('购物车为空!')

        # 日志
        new_time = time.strftime('%Y-%m-%d %X')
        my_info_str = '%s 用户%s查看购物车商品.' % (new_time, user_login['user'])
        logger1 = create_log(user_login['user'])
        logger1.debug(my_info_str)
        time.sleep(1)
        if input('按下(q)退出查看,否则任意输入继续查看\n请输入>>>:') == 'q':
            break

14.2测试

输入功能编号>>>:8
---------还没有用户登入请先登入----------
-------------登入功能-------------
用户名称>>>:kid
用户密码>>>:123
[DEBUG][2021-12-02 16:45:56,554][src.py:80]  信息: 用户kid登入成功
[DEBUG][2021-12-02 16:45:57,562][src.py:117]  信息: 登入 看购物车
------------查看购物车-------------
[DEBUG][2021-12-02 16:45:58,574][src.py:358]  信息: 2021-12-02 16:45:58 用户kid查看购物车商品.
(1) ---> 苹果  价格: 4.5   数量: 1.
(2) ---> 香蕉  价格: 3.0   数量: 2.
(3) ---> 菠萝  价格: 3.5   数量: 1.
按下(q)退出查看,否则任意输入继续查看
请输入>>>:q
[DEBUG][2021-12-02 16:46:42,591][src.py:121]  信息: 退出 看购物车

15.结账功能

15.1代码

# 9.购物结账
def shopping_checkout():
    # 总价格
    count_price = 0
    while True:
        print('购物结账'.center(30, '-'))
        # 获取路径

        is_exist, user_path = join_path(user_login['user'])

        # 显示当前登入用户的账单
        user_info_dic = read_file(user_path)
        # 读取 购物车 的数据
        collect = user_info_dic['collect']

        # 购物车是否为空的
        if collect:
            # 计算购物车内物品的价格
            for key in collect:
                price = collect[key][1] * collect[key][2]
                count_price += price
            print('总价格为%s元.' % count_price)
            if input('按下(y)结账,否则任意输入退出结账\n请输入>>>:') == 'y':
                # 判断钱够不够
                if user_info_dic['deposit'] < count_price:
                    print('余额不足!请充值')
                    return
            # 扣钱
            user_info_dic['deposit'] -= count_price

            # 清空购物车
            user_info_dic['collect'] = {
    
    }

            # 流水 存储格式 时间
            new_time = time.strftime('%Y-%m-%d %X')
            info_str = '%s 用户%s购买商品,花费%s元.' % (new_time, user_login['user'], count_price)

            # 添加流水
            user_info_dic['bill'].append(info_str)

            # 写入文件
            writer_file(user_path, user_info_dic)

            # 日志
            logger1 = create_log(user_login['user'])
            logger1.debug(info_str)
            time.sleep(1)
        else:
            print('购物车为空!')
        return

15.2测试

输入功能编号>>>:9
---------还没有用户登入请先登入----------
-------------登入功能-------------
用户名称>>>:kid
用户密码>>>:123
[DEBUG][2021-12-02 17:06:38,898][src.py:80]  信息: 用户kid登入成功
[DEBUG][2021-12-02 17:06:39,905][src.py:117]  信息: 登入 购物结账
-------------购物结账-------------
总价格为14.0.
按下(y)结账,否则任意输入退出结账
请输入>>>:y
[DEBUG][2021-12-02 17:06:48,232][src.py:411]  信息: 2021-12-02 17:06:48 用户kid购买商品,花费14.0.
[DEBUG][2021-12-02 17:06:49,241][src.py:121]  信息: 退出 购物结账

16.退出系统

16.1代码

# 10.退出系统
def exit_system():
    while True:
        print('退出系统'.center(30, '-'))
        if input('按下(y)退出系统,否则任意输入返回功能面板\n请输入>>>:') == 'q':
            sys.exit()
        else:
            break

16.2测试

-------------退出系统-------------
按下(q)退出系统,否则任意输入返回功能面板
请输入>>>:q

Process finished with exit code 0

17.代码包

地址: 链接: https://pan.baidu.com/s/1kws1Y7lCy430gKBa5g0xQA 提取码: r6pc 
复制这段内容后打开百度网盘手机App,操作更方便哦 
--来自百度网盘超级会员v5的分享

猜你喜欢

转载自blog.csdn.net/qq_46137324/article/details/121682318