欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pythonATM,购物车项目实战9-全部代码

程序员文章站 2022-03-04 17:54:12
...

 

 源码下载地址

https://download.csdn.net/download/wtt234/62410156
购物车





架构说明:

```
本项目采用“MVC”架构,
三层架构:
一 用户视图层
二 逻辑接口层
三 数据处理层

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

-----------------------------------
-----------------------------------
ATM+购物车

1.注册功能
2.登录功能
3.查看余额
4.提现功能
5.还款功能
6.转账功能
7.查看流水
8.购物功能
9.查看购物车
10.管理员功能

-----------------
实现功能事项:



用户视图层:
    与用户进行交互,接收用户处理输入的数据,交给接口层进行处理,接口层最终会将一个结果
    返回给用户视图层展示给用户


逻辑接口层
    相当于用户视图层与数据处理层的桥梁

    专门复测接收用户视图层传过来的数据,并进行“核心的逻辑”校验,校验过程中
    ,会去访问"数据层“进行数据的增删改查,通过或不通过会返回一个结果给用户视图层进行展示

    --日志的添加、流水的添加都是在这层

 数据处理层:
    职责:接收到接口层传递过来的参数,进行数据的处理

    1.增加数据
    2.查看数据
    3.删除数据
    4.更新数据


 common通用组件
-----------------------------------
-----------------------------------
搭建项目的目录规范:

-ATM项目根目录
    -readme.md  项目说明书
    -start.py  项目启动文件
    -conf 配置文件夹
        -settings.py
    -lib  公共方法文件
        -common.py

    -core [用户视图层]存放用户视图层代码文件
        -src.py

    -interface [逻辑接口层] 存放核心业务逻辑代码
        -user_interface.py 用户相关的接口
        -bank_interface.py 银行相关的接口
        -shop_interface.py 购物相关的接口

    -db [数据处理层] 存放数据与数据处理代码
        -db_handler.py 数据处理层代码
        -user_data  用户数据
    -log  存放日志文件
```

入口函数

1.start.py

```python
"""
程序的入口,主程序入口
"""


import os
import sys

# python 环境下使用sys.path.append(path)添加相关的路径,
# 但在退出python环境后自己添加的路径就会自动消失了!
# 添加解析器的环境变量
sys.path.append(os.path.dirname(__file__))

from core import src


if __name__ == '__main__':
    src.run()     # 执行用户视图层的函数
```

2.core/src.py

```pyton

"""
核心代码区,用户视图层
"""

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

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

#1.注册功能
def register():
    while True:
        #1.让用户输入用户名和密码进行校验
        username=input("请输入用户名:").strip()
        password=input("请输入密码:").strip()
        re_password=input("请再次输入密码:").strip()

        # 很小的逻辑处理,比较两次密码是否一致
        if password==re_password:

            #2)调用接口层的注册接口
            # flag,msg--->(flag--->False,msg--->'用户名已经存在!)
            # (True,用户注册成功)(False,注册失败)
            flag,msg=user_interface.register_interface(username,password)

            #3)根据flag判断用户注册是否成功,

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




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

        #2)调用接口层,将数据传给登录接口
        #True,f'用户:{username}登录成功!'
        #return False,'密码错误'
        #return 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():

    # 1.直接调用查看余额接口,获取用户余额
    balance=user_interface.check_bal_interface(login_user)

    print(f'用户{login_user}账户余额为:{balance}')

# 4.提现功能
# @common.login_auth
def withdraw():
    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():
    """
    银行卡还款,无论信用卡或者储蓄卡,是否能充任意大小的金额
    :return:
    """
    while True:
        # 1.让用户输入还款金额
        input_money=input("请输入需要还款的金额:").strip()
        # 2.判断用户输入的是否是数字
        if not input_money.isdigit():
            print("请输入正确的金额")
            continue
        input_money=int(input_money)

        # 3)判断用户输入的金额大于0
        if input_money>0:
            # 4)调用还款接口
            flag,msg=bank_interface.repay_interface(login_user,input_money)

            if flag:
                print(msg)
                break
        else:
            print("输入的金额不能小于0")





# 6.转账功能
# @common.login_auth
def transfer():
    """
    1.接收用户输入的转账目标用户
    2.接收永不输入的转账金额
    :return:
    """
    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():
    # 直接调用查看流水接口
    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():
    pass

# 9.查看购物车
# @common.login_auth
def check_shop_car():
    pass

# 10.管理员功能
def admin():
    pass

func_dict={
    '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("""
        1.注册功能
        2.登录功能
        3.查看余额
        4.提现功能
        5.还款功能
        6.转账功能
        7.查看流水
        8.购物功能
        9.查看购物车
        10.管理员功能

        """)

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

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

        func_dict.get(choice)()    #相当于func_dic.get("1")()--->register


if __name__ == '__main__':
    run()
    
```

2.1core/admin.py

```python
from core import src
from interface import admin_interface




#添加用户
def add_user():
    src.register()    #调用添加账户信息

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

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

        if not money.isdigit():
            continue

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

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


#冻结用户

def lock_user():
    while True:
        #1)输入要冻结的用户名
        change_user=input("请输入需要冻结的账户:").strip()
        flag,msg=admin_interface.lock_user_interface(change_user)

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




#

#管理员功能字典

admin_func={
    '1':add_user,
    '2':change_balance,
    '3':lock_user,
}

def admin_run():
    while True:
        print("""
        1.添加账户
        2.修改额度
        3.冻结账户
        
        """)

        choice=input("请输入管理员功能编号:").strip()
        if choice not in admin_func:
            print("请输入正确编号!")
            continue

        admin_func.get(choice)()
```



3.interface接口

3.1bank_intrface.py

```python


"""
银行相关业务的接口
"""
from db import db_handler


#提现接口(手续费5%,就是每次提现都是花费5%)
def withdraw_interface(username,money):

    #1)先获取用户字典
    user_dic=db_handler.select(username)

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

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

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

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


        # 3.1)在保存数据,或者更新数据
        db_handler.save(user_dic)


        return True,f'用户[{username}]提取金额[{money}]成功,手续费为:{money2-float(money)}$'

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


# 还款接口
def repay_interface(username,money):
    """
    1.获取用户的金额
    2.给用户的金额做加钱的操作
    :return:
    """
    # 1.获取用户字典
    user_dic=db_handler.select(username)

    #2.直接做加钱操作
    # user_dic["balance"]----->int
    user_dic['balance']+=money

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

    #3.调用数据处理层,将修改后的数据更新
    db_handler.save(user_dic)

    return True,f'用户:[{username}] 还款:[{money}]成功,当前额度为:{user_dic["balance"]}'



# 转账接口

def transfer_interface(login_user,to_user,money):
    """
    1.获取“当前用户”数据
    2.获取“目标用户”数据
    3.获取转账金额
    :param login_user:
    :param to_user:
    :param money:
    :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:
        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'用户[{login_user}]给用户:[{to_user}]转账:[{money}]成功'
        login_user_dic['flow'].append(login_user_flow)

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

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

        #6.2)给调用数据处理层的save功能,保存目标用户数据
        db_handler.save(to_user_dic)

        return True,f'用户:[{login_user}]给用户[{to_user}]转账:[{money}]元,成功!'

    return False,"当前用户转账金额不足!"


#查看流水接口
def check_flow_interface(login_user):
    user_dic=db_handler.select(login_user)
    return user_dic.get('flow')   #返回一个list列表


#支付接口
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,或者false 交给购物接口来处理
        return True

    return False



```

3.2shop_intrface.py

```python
"""
购物商城接口
"""

from db import db_handler

#商品准备结算接口
def shopping_interface(login_user,shopping_car):
    #1)计算消费总额
    #{‘商品名称’:["价格","数量"]}
    cost=0
    for price_number in shopping_car.values():
        price,number=price_number
        cost+=(price*number)

    #导入银行接口
    from interface import bank_interface
    #逻辑校验成功后,再调用银行的支付接口
    flag=bank_interface.pay_interface(login_user,cost)

    if flag:
        return True,"支付成功,准备发货!"
    return False,"支付失败,金额不足!"


#购物车添加接口
def add_shop_car_interface(login_user,shopping_car):
    #1)获取当前用户的购物车
    user_dic=db_handler.select(login_user)

    #获取用户文件中的商品的数据
    shop_car=user_dic.get("shop_car")

    #2)添加购物车
    #2.1)判断当前用户选择的商品是否已经存在
    # shopping_car--->{'商品名':["商品价格,商品数量"]}

    for shop_name,price_number in shopping_car.items():
        #每个商品的数量
        number=price_number[1]

        #2.2)若有商品重复,则累加商品数量

        if shop_name in shop_car:
            user_dic['shop_car'][shop_name][1]+=number

        else:
            #2.3)若不是重复的,更新到商品字典中
            user_dic['shop_car'].update({shop_name:price_number})

    #保存用户数量
    db_handler.save(user_dic)

    return True,"添加购物车成功!"


#查看购物车接口
def check_shop_car_interface(login_user):
    pass





```



3.3user_intrface.py

```python
"""
逻辑接口层
    用户接口
"""


from db import db_handler
from lib import common

# 注册接口

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)



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

    #3.2 保存数据
    db_handler.save(user_dict)

    return True,f'{username}注册成功!'



# 登录接口

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

    #用户判断用户是否存在

    #若有冻结用户 则需要判断是否被锁定
    if user_dict.get("locked"):
        return False,"当前用户已被锁定"



    #2)判断用户是否存在
    if user_dict:
        #给用户输入的密码做一次加密
        password=common.get_pwd_md5(password)
        #3)校验密码是否一致
        if password==user_dict.get('password'):
            return True,f'用户:{username}登录成功!'
        else:
            return False,'密码错误'

    return False,'用户不存在,请重新输入'

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


```



3.4interface/admin.py接口

```python
from db import db_handler

# 修改额度接口

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)

        return True,"额度修改成功!"

    return False,"修改额度用户不存在!"



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

    if user_dic:
        #将locked的默认值修改为True
        user_dic['lcoker']=True

        db_handler.save(user_dic)

        return True,f"用户{username}冻结成功!"
    return False,"冻结用户不存在"















```





4.lib

lib/common.py

```python
"""
存放公共方法
"""
import hashlib

#md5加密

def get_pwd_md5(password):
    md5_obj=hashlib.md5()
    md5_obj.update(password.encode('utf-8'))
    #加盐操作
    salt='我是加盐操作123456!'
    md5_obj.update(salt.encode('utf-8'))

    return md5_obj.hexdigest()


# 登录认证装饰器模板

# def login_authmobao(func):
#     def inner(*args,**kwargs):
#         res=func(*args,**kwargs)
#         return res
#
#     return inner()

 # 登录认证装饰器
 # 装饰器的使用,为其他函数进行装饰。
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()


```

5.db数据存储

下面两个,一个是文件夹“”user_data",存放用户*.json数据,还有一个db_handler.py--->这个主要是进行数据的存储处理

db_handler.py

```python
"""

数据处理层
    -专门用户处理数据的
"""

import json
import os
from conf import settings


#查看数据

def select(username):
    #     1)接收层传过来的username用户名,拼接用户json文件路径,如果穿过来的用户是
    # 是’张三‘那么本地就是存储为"张三.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,'r',encoding='utf-8')as f:
            use_dict=json.load(f)
            return use_dict

    # 3)不return,默认return None


# 保存数据
def save(user_dict):
    # 1)拼接用户的数据字典
    username=user_dict.get('username')

    user_path=os.path.join(settings.USER_DATA_PATH,f'{username}.json')

    # 2)保存用户数据

    with open(user_path,'w',encoding='utf-8')as f:
        #ensure_ascii=False),让保存到jsoon文件的中文,显示为中文而不是16进制
        json.dump(user_dict,f,ensure_ascii=False)


```

6.配置文件conf文件夹

conf/settings.py---->数据文件的配置事项

```python

"""

保存配置信息
"""

import os

#获取项目根目录路径

BASE_PATH=os.path.dirname(os.path.dirname(__file__))


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

7.sstart.py--->启动文件

```python
"""
程序的入口,主程序入口
"""


import os
import sys

# python 环境下使用sys.path.append(path)添加相关的路径,
# 但在退出python环境后自己添加的路径就会自动消失了!
# 添加解析器的环境变量
sys.path.append(os.path.dirname(__file__))

from core import src


if __name__ == '__main__':
    src.run()     # 执行用户视图层的函数
```