ATM+购物车

Posted 2722127842qq-123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ATM+购物车相关的知识,希望对你有一定的参考价值。

项目的说明书

项目: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的卡箱子BUG)。
        
        - 运维:
            - 部署项目。

?
?
?

二 程序的架构设计

1、程序设计的好处

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

2、三层架构设计的好处

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

3、三层架构

一 用户视图层

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

二 逻辑接口层

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

三 数据处理层

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

三 分任务开发

四 测试

五 上线

统计代码

file  ==>  settings  ==>  Plugins  ==>  Statistic  ==>  Installer
单击左下角:Statistic  ==>  单击:py
    Total Lines:总代码行数
    Sources Code Lines:纯代码行数
    Sources Code Lines[%]:纯代码行数百分比
    Comment Lines:注释行数
    Comment Lines[%]:注释行数百分比
    Blank Lines:空白行数
    Blank Lines[%]:空白行数百分比

 

架构图的思路

技术图片

 

ATM三层架构思路:

启动文件的实现

首先,创建一个start.py作为整个项目启动的启动文件。
然后导入os和sys模块,从core中导入src,也就是用户视图层。
然后添加解释器的环境变量,再开始执行项目函数。
src.py 用户视图层中,先写好各个功能函数名,然后创建一个函数功能字典。
然后就是视图层的主程序,打印选择列表让用户选择,根据选择的编号来调用不同的功能函数。

配置信息的实现

conf的setting.py中,编写配置文件。
写好项目的根目录路径BASE_PATH。
写好商品信息路径GOODS_PATH。
写好用户信息路径USER_DATA_PATH
然后写上日志配置(日志格式可以复制粘贴过来)

公共方法的实现

lib的common.py中存放公共方法。
导入conf的settings配置。
写上用户的登录认证装饰器。
导入hashlib模块,写上密码的md5加密,以json格式存储密码。
导入logging.config,添加日志功能,在接口层使用。

商品信息的实现

在db的goods_list.json中编写商品数据,以json的格式存储:
{
  "0": {"goods_name": "logitech-G703", "price": 549},
  "1": {"goods_name": "Antec-HCG750W", "price": 799},
  "2": {"goods_name": "ROG-M11E-Z390", "price": 6999},
  "3": {"goods_name": "G.SKILL-16G-RGB", "price": 769},
  "4": {"goods_name": "Intel-i9-9900KF", "price": 3599},
  "5": {"goods_name": "SAMSUNG-970Pro-1T", "price": 2699},
  "6": {"goods_name": "Segotep-K1(ATX3.0)", "price": 499},
  "7": {"goods_name": "ROG-RTX-2080Ti-11G", "price": 11999},
  "8": {"goods_name": "CHERRY-MX6.0-BLUE RGB", "price": 1399},
  "9": {"goods_name": "ASUS-ROG-360mm-RGB Aura", "price": 2299},
  "10": {"goods_name": "SAMSUNG-27inch-Space-2K/144Hz", "price": 3499}
}

 

数据处理层的实现

在db的db_handler.py 数据处理层中,导入json和os模块,从conf中导入settings配置。
编写查看数据函数,接收接口层传过来的username用户名,拼接用户json文件路径。
校验用户json文件,打开数据,并返回给接口层。
编写保存数据函数,用于添加新数据或者更新数据。
拼接用户的数据字典,保存用户数据。
编写获取商品数据函数,用于获取商品数据。
商品数据也是以json格式读取的。

注册功能的实现

编写interface的user_interface.py的注册接口。
查看用户是否存在,若存在,返回“用户名已存在!”
若不存在,就编写一个用户字典保存为“用户名.json”。
其中,如果用户名是“admin”,就是管理员,字典信息中的“is_admin”为“True”。
然后调用数据处理层的db_handler的save功能进行保存。
在core的src.py 用户视图层中,编写注册函数。
先定义一个全局遍历login_user = None,用来记录用户是否已登录。
让用户输入用户名和密码进行注册,2次密码必须相同。
调用接口层的注册接口,将用户名与密码交给接口层来进行处理。
输入的用户名如果是admin,就是管理员,其余是普通用户。
根据flag判断用户注册是否成功,flag控制break的结束。

登录功能的实现

编写interface的user_interface.py的登录接口。
先调用数据处理层的db_handler的select功能查看当前用户数据是否存在。
如果存在,就继续执行,如果不存在,就输出“用户不存在,请重新输入!”
再根据get用户字典的‘locker’的True或False判断用户是否被冻结。
然后给用户的密码做一次加密,和取过来的加密的用户密码比对,查看是否一致。
如果一致,就登录成功;如果不一致,登录失败。
在core的src.py 用户视图层中,编写登录函数。
让用户输入用户名和密码。
调用接口层的登录接口,将用户名与密码交给接口层来进行处理。
输入的用户名如果是admin,就是管理员,其余是普通用户。
根据flag判断用户注册是否成功,flag控制break的结束。

查看余额功能的实现

编写interface的user_interface.py的查看余额接口。
编写user_dic调用数据处理层的db_handler的select功能查看当前用户的余额。
返回给用户视图层。
core的src.py 用户视图层中,编写查看余额函数。
只有登录的用户才能查看。
调用接口层的查看余额接口,传入当前登录的用户名。
打印用户名和用户金额。

提现功能的实现

编写interface的user_interface.py的查看提现接口。
编写user_dic调用数据处理层的db_handler的select功能查看当前用户的余额。
把当前余额变成整型,然后计算手续费。
判断用户金额是否足够,如果足够,就修改用户字典中的金额,如果不足够,就退出并提示“余额不足!”
记录流水,调用数据处理层的db_handler的save和update功能保存并更新数据。
将结果返回给用户视图层。
core的src.py 用户视图层中,编写提现函数。
只有登录的用户才能提现。
让用户输入提现金额,判断用户输入的金额是否是数字,如果不是,就重新输入。
用户提现金额,将提现的金额交付给接口层来处理,传入当前登录的用户名。
调用接口层的查看余额接口,传入当前登录的用户名。
打印用户名和提现信息和余额信息。

还款功能的实现

编写interface的user_interface.py的查看还款接口。
编写user_dic调用数据处理层的db_handler的select功能查看当前用户的余额。
把当前余额变成整型,然后计算还款额。
记录流水,调用数据处理层的db_handler的save和update功能保存并更新数据。
将结果返回给用户视图层。
core的src.py 用户视图层中,编写还款函数。
只有登录的用户才能提现。
让用户输入提现金额,判断用户输入的金额是否是数字,如果不是,就重新输入。
用户还款金额,将还款的金额交付给接口层来处理,传入当前登录的用户名。
调用接口层的查看余额接口,传入当前登录的用户名。
打印用户名和还款信息和余额信息。

转账功能的实现

编写interface的bank_interface.py的转账接口。
编写login_dic和to_user_dic调用数据处理层的db_handler的select功能。
获取“当前用户”和“目标用户”字典,判断目标用户是否存在,若用户存在,则判断“当前用户转账金额”是否足够。
若足够,给当前用户的数据,做减钱操作;给目标用户的数据,做加钱操作,然后记录双方流水。
调用数据处理层的db_handler的save功能保存数据。
将结果返回给用户视图层。
core的src.py 用户视图层中,编写转账函数。
只有登录的用户才能提现。
判断用户输入金额是否是数字或者>0,如果不是,就重新输入。
让用户输入转账的用户和金额。将输入的信息交付给接口层来处理,传入当前登录的用户名、对方用户名、金额。
调用接口层的,打印用户名和还款信息和余额信息。

流水功能的实现

编写interface的bank_interface.py的查看流水接口。
编写user_flow_dic字典,调用调用数据处理层的db_handler的select功能,传入当前用户。
将结果返回给用户视图层。
core的src.py 用户视图层中,编写查看流水函数。
调用interface的bank_interface.py接口,传入当前用户。
调用流水接口,输出流水信息。

购物功能的实现

编写interface的shop_interface.py的购物接口。
编写goods_dic字典,调用数据处理层的db_handler的select_goods功能查看商品信息。
将结果返回给用户视图层。
编写interface的shop_interface.py的add_shop_car_interface购物车添加接口。
将用户视图层传来的视频信息存入字典。
如果商品不在购物车中则直接加入,商品在购物车中,修改商品数量以及总价。
将结果返回给用户视图层。
core的src.py 用户视图层中,编写购物函数。
调用interface的bank_interface.py接口,获取全部商品信息并打印。
将对应编号的商品加入购物车,调用add_shop_car_interface购物车添加接口。
调用购物车添加接口,已经入购物车的信息。

购物车结算功能的实现

编写interface的shop_interface.py的查看购物车接口。
编写user_dic字典,调用调用数据处理层的db_handler的select功能,传入当前用户。
编写shop_car_dic字典,取出user_dic字典中的"shop_car",然后记录流水信息。
将结果返回给用户视图层。
在core的src.py 用户视图层中,编写查看购物车函数。
调用interface的shop_interface.py接口,获取用户字典里的"shop_car"。
打印购物车内的信息,让用户选择要购买的购物车内的商品ID,输入c清空购物车,输入q退出该界面。
如果ID不存在,就跳过本次循环,输出信息“商品不存在”。
获取选择付款商品的商品信息并打印。

管理员功能的实现

编写interface的admin_interface.py的查看管理员接口。
编写4种功能:添加用户直接调用注册函数;修改额度调用用户字典直接修改,冻结和解冻用户修改用户字典的“locker”的bool值。
将结果返回给用户视图层。
在core下单独编写一个admin.py。
编写4个功能函数,调用各个接口。
编写管理员功能字典:
admin_dic = {
    ‘1‘: add_user,
    ‘2‘: change_balance,
    ‘3‘: lock_user,
    ‘4‘: unlock_user
}
编写管理员视图和功能选项,打印选择列表让用户选择,根据选择的编号来调用不同的功能函数。
core的src.py 用户视图层中,编写管理员函数。
直接调用core下的admin.py的admin.run()函数执行功能。
如果用户名是admin的话,就是管理员,如果不是,就是普通用户,没有资格使用该功能。

conf:

settings.py

# 存放配置信息

import os

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


# goods_list文件目录路径
GOODS_PATH = os.path.join(BASE_PATH, db, goods_list.json)

# 获取 user_data 文件夹的 目录路径
USER_DATA_PATH = os.path.join(
    BASE_PATH, db, user_data
)


"""
logging配置
"""

# 定义三种日志输出格式 开始
standard_format = [%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]                   [%(levelname)s][%(message)s]  # 其中name为getlogger指定的名字
simple_format = [%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s

id_simple_format = [%(levelname)s][%(asctime)s] %(message)s

# 定义日志输出格式 结束
# ****************注意1: log文件的目录
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
logfile_dir = os.path.join(BASE_PATH, log)
# print(logfile_dir)

# ****************注意2: log文件名
logfile_name = log.log

# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)

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
        },
        # 打印到文件的日志,收集info及以上的日志
        default: {
            level: DEBUG,
            class: logging.handlers.RotatingFileHandler,  # 保存到文件
            formatter: standard,
            filename: logfile_path,  # 日志文件
            maxBytes: 1024 * 1024 * 5,  # 日志大小 5M
            backupCount: 5,
            encoding: utf-8,  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    loggers: {
        # logging.getLogger(__name__)拿到的logger配置
        ‘‘: {
            handlers: [default, console],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            level: DEBUG,
            propagate: True,  # 向上(更高level的logger)传递
        },
    },
}

 

core:

admin.py

from core import src
from interface import admin_interface


# 添加用户
def add_user():
    src.register()


# 修改用户额度
def change_balance():
    while True:
        # 1.输入修改的用户名
        change_user = input(请输入需要修改额度的用户:).strip()

        # 2.输入修改用户额度
        money = input(请输入需要修改的用户额度:).strip()
        if not money.isdigit():
            continue

        # 3.调用修改额度接口
        flag, msg = admin_interface.change_balance_interface(
            change_user, money
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 冻结用户
def lock_user():
    while True:
        # 1.输入懂的用户名
        to_lock_user = input(请输入需要冻结的用户:).strip()

        # 2.调用冻结用户接口
        flag, msg = admin_interface.lock_user_interface(
            to_lock_user
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 解冻用户
def unlock_user():
    while True:
        # 1.输入懂的用户名
        to_unlock_user = input(请输入需要解冻的用户:).strip()

        # 2.调用冻结用户接口
        flag, msg = admin_interface.unlock_user_interface(
            to_unlock_user
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 管理员功能字典
admin_dic = {
    1: add_user,
    2: change_balance,
    3: lock_user,
    4: unlock_user
}


def admin_run():
    while True:
        print(‘‘‘
        ======== 管理员功能 ========
        |       1.添加账户         |
        |       2.修改额度         |
        |       3.冻结账户         |
        |       4.解冻账户         |
        ========= THE END =========
            ‘‘‘)
        choice = input(请输入管理员功能编号(按q退出):).strip()

        if choice.lower() == q:
            break

        # 判断功能编号是否存在
        if choice not in admin_dic:
            print(请输入正确的功能编号!)
            continue

        # 调用用于选择的功能函数
        admin_dic.get(choice)()  # admin_dic.get(‘1‘)() ---> add_user()

 

src.py

‘‘‘
用户视图层
‘‘‘
from interface import user_interface
from interface import bank_interface
from interface import shop_interface
from lib import common

# 全局变量,记录用户是否已登录
login_user = None


# 1.注册功能
def register():
    print(注册功能执行中...)
    while True:
        # 1.让用户输入用户名与密码进行校验
        username = input(请输入用户名: ).strip()
        password = input(请输入密码: ).strip()
        re_password = input(请确认密码: ).strip()
        # 可以输入自定义的金额

        # 小的逻辑处理: 比如两次密码是否一致
        if password == re_password:
            # 2.调用接口层的注册接口,将用户名与密码交给接口层来进行处理

            # res ---> (False, ‘用户名已存在!‘)
            # res = user_interface.register_interface(
            # flag, msg ---> (flag---> False, msg --> ‘用户名已存在!‘)

            # (True, 用户注册成功),  (False, 注册失败)
            flag, msg = user_interface.register_interface(
                username, password
            )

            # 3.根据flag判断用户注册是否成功,flag控制break的结束
            if flag:
                print(msg)
                break

            else:
                print(msg)


# 2.登录功能
def login():
    print(登录功能执行中...)
    # 登录视图
    while True:
        # 1.让用户输入用户名与密码
        username = input(请输入用户名: ).strip()
        password = input(请输入密码: ).strip()

        # 2.调用接口层,将数据传给登录接口
        # (True, f‘用户: [{username}] 登录成功!‘),
        # (return False, ‘密码错误‘), (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():
    print(查看余额功能执行中...)
    # 1.直接调用查看余额接口,获取用户余额
    balance = user_interface.check_bal_interface(
        login_user
    )

    print(f用户[{login_user}] 账户余额为: [{balance}元]!)


# 4.提现功能
@common.login_auth
def withdraw():
    print(提现功能执行中...)
    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():
    print(还款功能执行中...)
    while True:
        # 1.让用户输入还款金额
        input_money = input(请输入还款金额: ).strip()

        # 2.判断用户输入的金额是否是数字
        if not input_money.isdigit():
            print(请重新输入)
            continue

        input_money = int(input_money)
        if input_money > 0:
            # 3.用户还款金额,将还款的金额交付给接口层来处理
            flag, msg = bank_interface.repay_interface(
                login_user, input_money
            )

            if flag:
                print(msg)
                break
            else:
                print(msg)

        else:
            print(输入的金额不能小于等于0!)


# 6.转账功能
@common.login_auth
def transfer():
    print(转账功能执行中...)
    ‘‘‘
    1.接收用户输入的 转账目标用户
    2.接收用户输入的 转账金额
    ‘‘‘
    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():
    print(查看流水功能执行中...)
    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():
    print(购物功能执行中...)
    while True:
        # 获取全部商品信息并打印
        goods_dic = shop_interface.get_goods_interface()
        print(=================== Welcome To Hardware World ===================
)
        for number, goods_info in goods_dic.items():
            print(f| 编号:[{number}] 商品名:[{goods_info.get("goods_name")}] 价格:[{goods_info.get("price")}]元)
        print(‘‘)
        print("============================ THE END ============================")
        goods_id = input("请输入要购买的商品编号(按q返回上一层):").strip()
        if goods_id.lower() == q:
            break
        count = input("请输入购买的数量:").strip()
        if not count.isdigit() or count == 0:
            print("输入错误")
            continue
        if goods_id not in goods_dic:
            print(该商品不存在)
            continue
        # 将对应编号的商品加入购物车
        shop_interface.add_shop_car_interface(goods_dic[goods_id], int(count))
        print(f"{goods_dic[goods_id][‘goods_name‘]}已加入购物车,请到购物车结算")


# 作业:清空购物车功能
# 清空购物车
def clean_shop_car():
    inp_clear = input("是否清空购物车?(Y/N):").strip()
    if inp_clear.lower() != y:
        print("清空购物车失败,用户取消操作")
        return False
    msg = shop_interface.clean_shop_car_interface(login_user)
    print(msg)
    return True


# 9.查看购物车
@common.login_auth
def check_shop_car():
    print(查看购物车功能执行中...)
    shop_car_dic = shop_interface.check_shop_car_interface(login_user)
    while True:
        shop_id = 0
        print("========================  购物车内容  =========================")
        print(‘‘)
        for goods_name, goods_info in shop_car_dic.items():
            print(f| ID:[{shop_id}] 商品名 {goods_name} 数量 {goods_info.get("count")}个 总价 {goods_info.get("total")}元)
            shop_id += 1
        print(‘‘)
        print("========================== THE END  ==========================")
        pay_id = input("请选择需要付款的商品ID(按q离开购物车,按c清空购物车):").strip()
        if pay_id.lower() == c:
            flog = clean_shop_car()
            if flog:
                return
            continue
        if pay_id.lower() == q:
            break
        if int(pay_id) not in range(len(shop_car_dic)):
            print("商品不存在")
            continue
        # 获取选择付款商品的商品信息并打印
        buy_goods_name = list(shop_car_dic.keys())[int(pay_id)]
        buy_goods_count = shop_car_dic[buy_goods_name].get(count)
        buy_goods_total = shop_car_dic[buy_goods_name].get(total)
        print(f"您将付款的商品为:{buy_goods_name},数量为:{buy_goods_count}个, 总价为:{buy_goods_total}元")
        # 付款
        inp_buy = input("确认付款(Y/n):").strip()
        if inp_buy.lower() == y:
            flog, msg = shop_interface.payment_interface(login_user, buy_goods_name, buy_goods_total)
            if flog:
                print(msg)
                break
            else:
                print(msg)
        print("付款失败,用户取消支付")


@common.login_auth
# 10.管理员功能
def admin():
    print(管理员功能执行中...)
    from core import admin
    if login_user == admin:
        admin.admin_run()
    else:
        print(你没有资格!)


# 创建函数功能字典
func_dic = {
    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(‘‘‘
        ======= ATM + 购物车 =======
        |       1.注册功能          |
        |       2.登录功能          |
        |       3.查看余额          |
        |       4.提现功能          |
        |       5.还款功能          |
        |       6.转账功能          |
        |       7.查看流水          |
        |       8.购物功能          |
        |       9.查看购物车        |
        |       10.管理员功能       |
        =========== END ===========
        ‘‘‘)

        choice = input(请输入功能编号: ).strip()

        if choice not in func_dic:
            print(请输入正确的功能编号!)
            continue

        func_dic.get(choice)()  # func_dic.get(‘1‘)() ---> register()

 

db:

userdata

用于存放用户信息

db_handler.py

‘‘‘
数据处理层
‘‘‘

import os
import json
from conf import settings


# 查看数据
def select(username):
    # 1.接收接口层传过来的username用户名,拼接用户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, mode=rt, encoding=UTF-8) as f:
            user_dic = json.load(f)
            return user_dic


# 保存数据(添加新数据或者更新数据)
def save(user_dic):
    # 1.拼接用户的数据字典
    username = user_dic.get(username)

    user_path = os.path.join(
        settings.USER_DATA_PATH, f{username}.json
    )
    # 2.保存用户数据
    with open(user_path, mode=wt, encoding=UTF-8) as f:
        # ensure_ascii=False让文件中的中文数据,显示更美观
        json.dump(user_dic, f, ensure_ascii=False)


# 获取商品数据
def select_goods():
    with open(settings.GOODS_PATH, mode=rt, encoding=UTF-8) as f:
        goods_dic = json.load(f)
        return goods_dic

 

goods_list.json

{
  "0": {"goods_name": "logitech-G703", "price": 549},
  "1": {"goods_name": "Antec-HCG750W", "price": 799},
  "2": {"goods_name": "ROG-M11E-Z390", "price": 6999},
  "3": {"goods_name": "G.SKILL-16G-RGB", "price": 769},
  "4": {"goods_name": "Intel-i9-9900KF", "price": 3599},
  "5": {"goods_name": "SAMSUNG-970Pro-1T", "price": 2699},
  "6": {"goods_name": "Segotep-K1(ATX3.0)", "price": 499},
  "7": {"goods_name": "ROG-RTX-2080Ti-11G", "price": 11999},
  "8": {"goods_name": "CHERRY-MX6.0-BLUE RGB", "price": 1399},
  "9": {"goods_name": "ASUS-ROG-360mm-RGB Aura", "price": 2299},
  "10": {"goods_name": "SAMSUNG-27inch-Space-2K/144Hz", "price": 3499}
}

 

interface:

admin_interface.py

from db import db_handler
from lib import common

# 根据不同的接口类型传入不同的日志对象
admin_logger = common.get_logger(log_type=admin)


# 修改额度接口
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)
        msg = f管理员修改用户: [{username}]额度修改成功!
        admin_logger.info(msg)

        return True, 额度修改成功!

    return False, 该用户不存在!


# 冻结接口
def lock_user_interface(username):
    user_dic = db_handler.select(username)

    if user_dic:
        if not user_dic[locked]:
            # 将locked的默认值改为True
            user_dic[locked] = True
            db_handler.save(user_dic)

            msg = f用户:[{username}]冻结成功!
            admin_logger.info(msg)
            return True, msg
        else:
            return False, 该用户已被冻结,无需再次冻结!

    return False, 冻结用户不存在!


# 解冻接口
def unlock_user_interface(username):
    user_dic = db_handler.select(username)

    if user_dic:
        if user_dic[locked]:
            # 将locked的默认值改为False
            user_dic[locked] = False
            db_handler.save(user_dic)

            msg = f用户:[{username}]解冻成功!
            admin_logger.info(msg)
            return True, msg
        else:
            return False, 该用户未被冻结,无需解冻!

    return False, 解冻用户不存在!

 

bank_interface.py

# 银行相关业务的接口
import time
from db import db_handler
from lib import common

# 根据不同的接口类型传入不同的日志对象
bank_logger = common.get_logger(log_type=bank)

# 记录当前操作的时间
start_time = time.strftime(%Y-%m-%d %H:%M:%S)


# 提现接口(手续费5%)
def withdraw_interface(username, money):
    # 1.先获取用户字典
    user_dic = db_handler.select(username)

    # 账户中的金额
    balance = int(user_dic.get(balance))

    # 提现本金 + 手续费
    money2 = int(money) * 1.05  # ---> float

    # 判断用户金额是否足够
    if balance >= money2:
        # 2.修改用户字典中的金额
        balance -= money2

        user_dic[balance] = balance

        # 3.记录流水
        flow = f{start_time} 用户:[{username}] 提现金额:[{money}元]成功,手续费为: [{money2 - float(money)}元]
        user_dic[flow].append(flow)

        # 4.再保存数据,或更新数据
        db_handler.save(user_dic)
        bank_logger.info(flow)
        return True, flow

    return False, 提现金额不足,请重新输入!


# 还款接口(无需手续费)
def repay_interface(username, money):
    # 1.先获取用户字典
    user_dic = db_handler.select(username)

    # 2.直接做加钱操作
    # user_dic[‘balance‘] ==> int
    user_dic[balance] += money
    new_money = user_dic[balance]

    # 3.记录流水
    flow = f{start_time} 用户:[{username}]  还款:[{money}]成功!
    user_dic[flow].append(flow)

    # 4.调用数据处理层,将修改后的数据更新
    db_handler.save(user_dic)
    bank_logger.info(f{start_time} 用户:{username} 还款成功,还款金额:[{money}]元)
    return True, flow


# 转账接口
def transfer_interface(login_user, to_user, money):
    ‘‘‘
    1.获取“当前用户”数据
    2.获取“目标用户”数据
    3.获取“转账金额”数据
    :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:
        bank_logger.warning(f{start_time} 用户:[{login_user}] 转账失败,用户:[{to_user}]不存在)
        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{start_time} 用户:[{login_user}] 给 用户:[{to_user}] 转账:[{money}元]
        login_user_dic[flow].append(login_user_flow)

        # 目标用户流水
        to_user_flow = f{start_time} 用户:[{to_user}] 接收 用户:[{login_user}] 转账:[{money}元]
        to_user_dic[flow].append(to_user_flow)

        # 6.调用数据处理层的save功能,保存用户数据
        # 6.1.保存当前用户数据
        db_handler.save(login_user_dic)

        # 6.2.保存目标用户数据
        db_handler.save(to_user_dic)
        bank_logger.info(f{login_user} 转账成功,对方用户:[{to_user}],转账金额[{money}]元)
        return True, login_user_flow

    else:
        bank_logger.warning(f{start_time} 用户:[{login_user}] 转账失败,余额不足)
        return False, 余额不足,转账失败!


# 查看流水接口
def check_flow_interface(login_user):
    user_flow_dic = db_handler.select(login_user)
    return user_flow_dic[flow]


# 支付接口
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 或者 return False 交给购物接口来操作
        return True

    return False

 

shop_interface.py

# 商品购买接口
import time
from db import db_handler
from lib import common

# 根据不同的接口类型传入不同的日志对象log_type=
shop_logger = common.get_logger(log_type=shop)

start_time = time.strftime(%Y-%m-%d %H:%M:%S)


# 获取商品信息接口
def get_goods_interface():
    goods_dic = db_handler.select_goods()
    return goods_dic


# 商品准备结算接口
def payment_interface(login_user, buy_goods_name, buy_goods_total):
    user_dic = db_handler.select(login_user)
    # 获取用户购物车字典
    shop_car_dic = user_dic[shop_car]
    # 获取用户余额
    balance = user_dic[balance]
    if buy_goods_total > balance:
        shop_logger.warning(f用户:[{login_user}] 支付失败,余额不足)
        return False, 支付失败,余额不足
    balance -= buy_goods_total
    shop_car_dic.pop(buy_goods_name)
    # 修改用户余额
    user_dic[balance] = balance
    # 删除已付款商品
    user_dic[shop_car] = shop_car_dic
    # 增加流水
    user_dic[flow].append(f{start_time} 用户:[{login_user}] 购买商品:[{buy_goods_name}] 消费:[{buy_goods_total}]元)
    # 更新用户数据
    db_handler.save(user_dic)
    shop_logger.info(f{start_time} 用户:{login_user} 付款成功! 商品:[{buy_goods_name}] 等待发货)
    return True, 支付成功


# 购物车添加接口
def add_shop_car_interface(goods_dic, count):
    from core import src
    total = goods_dic["price"] * count
    goods_name = goods_dic[goods_name]
    shop_dic = {
        f"{goods_name}": {"count": count, "total": total}
    }
    user_dic = db_handler.select(src.login_user)
    # 用户购物车内商品信息
    shop_car_dic = user_dic[shop_car]
    # 如果购物车为空则直接加入
    if user_dic.get(shop_car) == {}:
        user_dic[shop_car] = shop_dic
    else:
        # 如果商品不在购物车中则直接加入
        if goods_name not in shop_car_dic:
            shop_car_dic.update(shop_dic)
            user_dic[shop_car] = shop_car_dic
        else:
            # 商品在购物车中,修改商品数量以及总价
            user_dic[shop_car].get(goods_name)[count] += count
            user_dic[shop_car].get(goods_name)[total] += total
    db_handler.save(user_dic)
    shop_logger.info(f{start_time} 用户:{src.login_user} 添加商品:[{goods_name}]至购物车成功)

    return True, 添加购物车成功!


# 获取购物车信息接口
def check_shop_car_interface(login_user):
    user_dic = db_handler.select(login_user)
    shop_car_dic = user_dic["shop_car"]
    shop_logger.info(f{start_time} 用户:[{login_user}] 查看购物车)
    return shop_car_dic


# 清空购物车
def clean_shop_car_interface(login_user):
    user_dic = db_handler.select(login_user)
    user_dic[shop_car] = {}
    db_handler.save(user_dic)
    shop_logger.info(f{start_time} 用户:[{login_user}] 清空了购物车)
    return 清空购物车成功

 

userface_interface.py

# 逻辑接口层
#     用户接口

from db import db_handler
from lib import common

# 根据不同的接口类型传入不同的日志对象
user_logger = common.get_logger(log_type=user)


# 注册接口
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)

    if username == admin:
        user_dic = {
            username: username,
            password: password,
            balance: balance,
            # 用于记录用户流水的列表
            flow: [],
            # 用于记录用户购物车
            shop_car: {},
            # locked:用于记录用户是否被冻结
            # False: 未冻结   True: 已被冻结
            is_admin: True
            }

    # 3.1.组织用户的数据的字典信息
    user_dic = {
        username: username,
        password: password,
        balance: balance,
        # 用于记录用户流水的列表
        flow: [],
        # 用于记录用户购物车
        shop_car: {},
        # locked:用于记录用户是否被冻结
        # False: 未冻结   True: 已被冻结
        locked: False,
        is_admin: False

    }

    # 3.2.保存数据
    db_handler.save(user_dic)
    msg = f{username} 新用户注册成功, 初始额度为:{balance}元

    # 3.3.记录日志
    user_logger.info(msg)

    return True, msg


# 登录接口
def login_interface(username, password):
    # 1.先查看当前用户数据是否存在
    # {用户数据字典}  or  None
    user_dic = db_handler.select(username)

    # 2.判断用户是否存在
    if user_dic:
        # 若有冻结用户,则需要判断是否被锁定
        if user_dic.get(locked):
            return False, 当前用户已被冻结,好好反省一下自己做了什么!

        # 给用户输入的密码做一次加密
        password = common.get_pwd_md5(password)

        # 3.校验密码是否一致
        if password == user_dic.get(password):
            msg = f用户: [{username}] 登录成功!
            user_logger.info(msg)
            return True, msg

        else:

            msg = f用户: [{username}]密码错误!
            user_logger.warn(msg)
            return False, msg

    msg = f用户: [{username}]用户不存在,请重新输入!!
    return False, msg


# 查看余额接口
def check_bal_interface(username):
    user_dic = db_handler.select(username)
    return user_dic[balance]

 

lib:

common.py

# 存放公共方法

import hashlib
from conf import settings
import logging.config


# md5加密
def get_pwd_md5(password):
    md5_obj = hashlib.md5()
    md5_obj.update(password.encode(UTF-8))
    salt = 急急如律令!
    md5_obj.update(salt.encode(UTF-8))
    return md5_obj.hexdigest()


# 登录认证装饰器
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


# 添加日志功能: (日志功能在接口层 使用)
def get_logger(log_type):  # log_type ---> user
    ‘‘‘
    :param log_type: 比如是 user日志,bank日志,购物商城日志
    :return:
    ‘‘‘
    # 1.加载日志配置信息
    logging.config.dictConfig(
        settings.LOGGING_DIC
    )

    # 2.获取日志对象
    logger = logging.getLogger(log_type)

    return logger

 

log:

log.log

存放日志信息

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的卡箱子BUG)。
            
            - 运维:
                - 部署项目。
        
        
        
    
## 二 程序的架构设计
### 1、程序设计的好处
    1) 思路清晰
    2) 不会出现写一半代码时推翻重写
    3) 方便自己或以后的同事更好维护
    
### 2、三层架构设计的好处
    1) 把每个功能都分层三部分,逻辑清晰
    2) 如果用户更换不同的用户界面或不同,
    的数据储存机制都不会影响接口层的核心
    逻辑代码,扩展性强。
    3) 可以在接口层,准确的记录日志与流水。
    
### 3、三层架构
#### 一 用户视图层
    用于与用户交互的,可以接受用户的输入,打印接口返回的数据。
    
#### 二 逻辑接口层
    接受 用户视图层 传递过来的参数,根据逻辑判断调用数据层加以处理,
    并返回一个结果给 用户视图层。
    
#### 三 数据处理层
    接受接口层传递过来的参数,做数据的 
        - 保存数据  save()
        - 查看数据  select()
        - 更新数据  update()
        - 删除数据  delete()

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



# 统计代码
    file  ==>  settings  ==>  Plugins  ==>  Statistic  ==>  Installer
    单击左下角:Statistic  ==>  单击:py
        Total Lines:总代码行数
        Sources Code Lines:纯代码行数
        Sources Code Lines[%]:纯代码行数百分比
        Comment Lines:注释行数
        Comment Lines[%]:注释行数百分比
        Blank Lines:空白行数
        Blank Lines[%]:空白行数百分比

 

start.py:

# 程序的入口

import os
import sys
from core import src

# 添加解释器的环境变量
sys.path.append(
    os.path.dirname(__file__)
)

# 开始执行项目函数
if __name__ == __main__:

    # 1、先执行用户视图层
    src.run()

 

以上是关于ATM+购物车的主要内容,如果未能解决你的问题,请参考以下文章

ATM+购物车完整版

atm

新项目ATM机+商场系统逻辑

用java编写的ATM机源代码

ATM+购物车

python练习_module02-1-ATM+购物车