zoukankan      html  css  js  c++  java
  • ATM+购物车

    ATM+购物车

    1 需求

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

    2 功能

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

    3 目录结构

    ATM
    -bin
      -start.py
    -conf
      -settings.py
    -db
      -user_data
        -ccc.py
        ...
      -db_handler.py
    -interface
      -bank.py
      -user.py
      -shopping.py
    -lib
      -common.py
    -log
      -atm.log
    -view
      -src.py
    

    4 思路及步骤

    4.1 环境bin/start.py

    程序的入口

    4.1.1 将解释器添加到环境变量中

    import os
    import sys
    sys.path.append(os.path.dirname(os.path.dirname(__file__)))
    

    4.1.2 启动主程序

    from view import src
    if __name__ == '__main__':
        src.run()
    # 此时应该在view/src.py中定义主启动函数run()
    

    4.2 配置conf/settings.py

    存放配置信息

    4.2.1 获取项目根目录路径

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

    4.2.2 获取user_data目录路径

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

    4.2.3 获取log目录路径

    import os
    USER_LOG = os.path.join(BASE_PATH, 'log')
    

    4.3 数据处理db/db_handle.py

    数据处理层专门用来处理数据

    4.3.1 保存用户信息save

    import os
    import json
    from conf import settings
    
    def save(username, user_dic):
        user_path = os.path.join(settings.USER_DATA_PATH, f'{username}.json')
        with open(user_path, 'wt', encoding='utf-8') as f:
            json.dump(user_dic, f, ensure_ascii=False)
            f.flush()  # 强制刷入硬盘
    

    4.3.2 返回用户信息select

    import os
    import json
    from conf import settings
    
    def select(username):
        user_path = os.path.join(settings.USER_DATA_PATH, f'{username}.json')
        if os.path.exists(user_path):
            with open(user_path, 'rt', encoding='utf-8') as f:
            	user_dic = json.load(f)
            return user_dic
    

    4.4 视图层view/src

    用户视图层

    4.4.1 主启动函数run()

    func_dic = {
        "1": register,
        "2": login,
        "3": check_balance,
        "4": withdrawal,
        "5": repay,
        "6": transfer,
        "7": check_flow,
        "8": shop,
        "9": check_shopping_cart,
        "10": admin,
        "11": logout,
    }
    
    def run():
        while True:
            print(
            =======================
                 1.注册
    			2.登录
    			3.查看余额
    			4.提现
    			5.还款
    			6.转账
    			7.查看流水
    			8.购物
    			9.查看购物车
    			10.管理员
    			11.注销
            =======================
            )
            choice = input("请输入功能编号(按q退出程序):").strip()
            if choice == "q":break
            if choice not in func_dic:
                print("请输入正确的编号!")
                continue
            func_dic.get(choice)()  # 输入1相当于func_dic.get('1')()-->register()
    

    4.4.2 功能实现

    4.4.2.1 注册功能register()

    from interface import user
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    def register():
        while True:
            if not user_login['is_login']:
                username = input("请输入注册用户名(按q退出):").strip()
                if username == "q":break
                password = input("请输入密码:").strip()
                re_password = input("请再次输入密码:").strip()
                if password == re_password:
                    msg = user.register_interface(username, password)
                    print(msg)
                    break
                else:
                    print("两次密码不一致")
    		else:
                print("登陆状态不可再注册")
                break
    

    4.4.2.2 登录功能login()

    from interface import user
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    def login():
        count = 0
        while True:
            if not user_login['is_login']:
                username = input("请输入登录名(按q退出):").strip()
                if username == "q":break
                user_info = user.get_user_info_interface(username)
                if user_info:
                    if not user_info['locked']:
                        if count < 3:
                            password = input("请输入登录密码:").strip()
                            if password == user_info['password']:
                                user_login['is_login'] = True
                                user_login['username'] = username
                                print("登陆成功")
                                break
                            else:
                                count += 1
                                print("密码输入错误")
                        else:
                            user.locked_interface(username)
                            print("该用户密码错误输入次数过多,已被锁定")
                            break
                    else:
                        msg = user.unlocked_interface(username)
                        print(msg)
                else:
                    print("该用户不存在")
            else:
                print("登录状态下不可再次登录")
                break
                
                
    1、判断用户登录状态,非登录状态继续执行代码,否则告诉用户登录情况下不能再次登录
    2、用户输入登录名,判断输入是否为q,非q继续执行代码,否则退出
    3、判断用户名是否存在,不存在继续执行代码,存在则告诉用户该用户名不存在
    4、判断该用户是否被锁,没有则继续执行,被锁则调用解锁接口 等待解锁
    5、判断密码输入次数,小于三次则继续执行,否则调用锁定接口 锁定账号
    6、用户输入密码,判断密码是否正确,正确则登录,错误则输入次数加1
    

    4.4.2.3 查看余额功能check_balance()

    # 首先使用登录认证装饰器判断登陆状态
    from lib import common
    from interface import bank
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def check_balance():
        msg = bank.check_balance_interface(user_login['username'])
        print("%s的余额是%s元" % (user_login['username'], msg))
    

    4.4.2.4 提现功能withdrawal()

    from lib import common
    from interface import bank
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def withdrawal():
        while True:
            print("""
    =============================
            0) 退出
            1) 查看余额
            2) 提现
    =============================
            """)
            choice = input("请输入指令:").strip()
            if choice == "0":break
            elif choice == "1":
                msg = bank.check_balance_interface(user_login['username'])
                print(msg)
            elif choice == "2":
                money = input("请输入提现金额:").strip()
                if money.isdigit:
                    money = int(money)
                    msg = bank.withdrawal_interface(user_login['username'], money)
                    print(msg)
                    break
                else:
                    print("请输入正确的金额")
            else:
                print("请输入正确的提现指令")
                
    1、装饰器判断登录状态,未登录则执行登陆程序,登陆则继续
    2、用户选择功能,0->退出 1->查看余额 2->提现(循环功能)
    3、0直接退出 1调用余额接口
    4、2让用户输入提现金额,判断是否为数字,不为数字提示重新输入,为数字继续
    5、调用提现接口,打印返回值
    

    4.4.2.5 还款功能repay()

    from lib import common
    from interface import bank
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def repay():
        while True:
            choice = input("""
    =============================
            0) 退出
            1) 查询欠款金额
            2) 还款
    =============================
            请输入选项:""").strip()
            if choice == "0":break
            elif choice == "1":
                msg = bank.check_debt_interface(user_login['username'])
                print(msg)
            elif choice == "2":
                money = input("请输入还款金额:").strip()
                if money.isdigit():
                    money = int(money)
                    msg = bank.repay_interface(user_login['username'], money)
                    print(msg)
                    break
                else:
                    print("请输入正确的金额")
            else:
                print("请输入正确的选项")
                
    1、调用登录认证装饰器
    2、用户选择还款功能 0退出 1查询欠款金额 2还款
    3、1调用查询欠款接口查询
    4、2用户输入还款金额,判断是否为数字
    5、调用还款接口
    

    4.4.2.6 转账功能transfer()

    from lib import common
    from interface import bank
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def transfer():
        while True:
            print("""
    =============================
            0) 退出
            1) 查看余额
            2) 转账
    =============================
            """)
            choice = input("请输入功能选项:").strip()
            if choice == "0":break
            elif choice == "1":
                msg = bank.check_balance_interface(user_login['username'])
                print(msg)
            elif choice == "2":
                to_username = input("请输入被转帐用户名:").strip()
                if to_username == user_login['username']:
                    print("不能转账给自己")
                    continue
                if user.get_user_info_interface(to_username):
                    money = input("请输入转账金额:").strip()
                    if money.isdigit():
                        money = int(money)
                        msg = bank.transfer_interface(user_login['username'], to_username, money)
                        print(msg)
                        break
                    else:
                        print("请输入正确的金额数")
                else:
                    print("被转账用户不存在")
            else:
                print("请输入正确的选项")
                
    1、调用登录认证装饰器
    2、用户选择功能 0退出 1调用查看余额接口查看余额 2转账
    3、2输入被转账用户名,判断是否为自己
    4、调用提取信息接口判断用户是否存在,存在则继续,否则提示用户不存在
    5、用户输入金额,判断是否为数字,是继续,否则提示输入正确的金额
    6、调用转账接口
    

    4.4.2.7 查看流水功能check_flow()

    from lib import common
    from interface import bank
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def check_flow():
        flow_list = bank.check_flow_interface(user_login['username'])
        for line in flow_list:
            print(line)
    

    4.4.2.8 购物功能shop()

    from lib import common
    from interface import shopping
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def shop():
        good_list = [
            ['tesla', 10000],
            ['mac', 8000],
            ['thinkpad', 6000],
            ['火锅', 580],
            ['烧烤', 320],
            ['串串', 280],
            ['包子', 8],
            ['矿泉水',5]
        ]
        good_cart = {}
        balance = bank.check_balance_interface(user_login['username'])
        amount_spend = 0
        while True:
            for i,line in enumerate(good_list):
                print("%s 商品名:%s 单价:%s" % (i, line[0], line[1]))
            choice = input("请输入商品序号(按q退出并购买):").strip()
            if choice.isdigit():
                choice = int(choice)
                if 0 <= choice <= len(good_list)-1:
                    good_name = good_list[choice][0]
                    good_price = good_list[choice][1]
                    if balance >= good_price:
                        if good_name in good_cart:
                            good_cart[good_name]['count'] += 1
                        else:
                            good_cart[good_name] = {'price': good_price, 'count': 1}
                        amount_spend += good_price
                        balance -= good_price
                        print("%s已被加入购物车" % good_name)
                        print("目前购物车有:%s" % good_list)
                        print("余额:%s元" % balance)
                    else:
                        print("余额不足,剩余%s" % balance)
                else:
                    print("该商品尚未上架")
            elif choice == "q":
                while True:
                    choice = input("请输入 y)结算 或 n)退出:").strip()
                    if choice == "y":
                        if amount_spend > 0:
                            password = input("请输入密码:").strip()
                            file_password = user.get_user_info_interface(user_login['username'])['password']
                            if password == file_password:
                                msg = shopping.buy_goods_interface(user_login['username'], good_cart, amount_spend)
                                print(msg)
                                break
                            else:
                                print("密码错误")
                        else:
                            print("没买东西结什么账啊")
                            break
                    elif choice == "n":
                        print("白加这么多东西在购物车")
                        break
                    else:
                        print("请输入正确的选项")
                break
            else:
                print("请输入数字")
    

    4.4.2.9 查看购物车功能check_shopping_cart()

    from lib import common
    from interface import shopping
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def check_shopping_cart():
        msg = shopping.check_shopping_cart_interface(user_login['username'])
        print(msg)
    

    4.4.2.10 管理员功能admin()

    def admin():
        pass
    

    4.4.2.11 注销功能logout()

    from lib import common
    
    user_login = {
        'is_login': False,
        'username': None
    }
    
    @common.check_login
    def logout():
        if user_login['is_login']:
            user_login['is_login'] = False
            print("注销成功")
        else:
            print("请先登录")
    

    4.5 公共lib/common

    存放公共登陆方法,登录认证装饰器及日志模块

    4.5.1 登陆认证装饰器

    from view import src
    
    # 登录认证装饰器
    def check_login(func):
        def inner(*args, **kwargs):
            if src.user_login['is_login']:
                res = func(*args, **kwargs)
                return res
            else:
                print("暂未登录,请先登录后在使用本功能")
                src.login()
        return inner
    

    4.5.2 日志

    import os
    import logging.config
    from conf import settings
    
    # 日志模块
    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'
    
    # 定义日志输出格式 结束
    
    logfile_dir = settings.USER_LOG  # log文件的目录
    
    logfile_name = 'atm.log'  # log文件名
    
    # 如果不存在定义的日志目录就创建一个
    if not os.path.isdir(logfile_dir):
        os.mkdir(logfile_dir)
    
    # log文件的全路径
    logfile_path = os.path.join(logfile_dir, logfile_name)
    
    # 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'
            },
            # 打印到文件的日志,收集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)传递
            },
        },
    }
    
    
    def make_log(name):
        logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
        logger = logging.getLogger(name)  # 生成一个log实例
    
        return logger
    

    4.6 接口interface

    4.6.1 银行相关bank.py

    4.6.1.1 查看余额接口

    from db import db_handler
    from lib import common
    logger_bank = common.make_log('bank')
    
    # 查看余额接口
    def check_balance_interface(username):
        user_info = db_handler.select(username)
        res = user_info['balance']
        # 记录日志
        logger_bank.info("%s查看了余额" % username)
        return res
    

    4.6.1.2 提现接口

    from db import db_handler
    from lib import common
    logger_bank = common.make_log('bank')
    
    # 提现接口
    def  withdrawal_interface(username, money):
        user_info = db_handler.select(username)
        if user_info['balance'] >= money*1.05:
            user_info['balance'] -= money*1.05
            # 查看流水
            user_info['flow'].append("%s成功提现%s元,扣除手续费%s元" % (username, money, money*0.05))
            db_handler.save(username, user_info)
            # 记录日志
            logger_bank.info("%s成功提现%s元,扣除手续费%s元" % (username, money, money*0.05))
            return "%s成功提现%s元,扣除手续费%s元" % (username, money, money*0.05)
        else:
            return "%s账户余额不足" % username
    

    4.6.1.3 查询欠款接口

    from db import db_handler
    from lib import common
    logger_bank = common.make_log('bank')
    
    # 查询欠款接口
    def check_debt_interface(username):
        user_info = db_handler.select(username)
        res = user_info['credit'] - user_info['balance']
        if res > 0:
            # 记录日志
            logger_bank.info("%s查看了欠款" % username)
        	return "%s当前欠款%s元" % (username, res)
        else:
            return "%s当前并未欠款" % username
    

    4.6.1.4 还款接口

    from db import db_handler
    from lib import common
    logger_bank = common.make_log('bank')
    
    # 还款接口
    def repay_interface(username, money):
        user_info = db_handler.select(username)
        res = user_info['credit'] - user_info['balance']
        if res >= money:
            user_info['balance'] += money
            # 记录流水
            user_info['flow'].append("%s成功还款%s元" % (username, money))
            db_handler.save(username, user_info)
            # 记录日志
            logger_bank.info("%s成功还款%s元" % (username, money))
            return "%s成功还款%s元" % (username, money)
        else:
            return "还款金额超过欠款额度"
    

    4.6.1.5 转账接口

    from db import db_handler
    from lib import common
    logger_bank = common.make_log('bank')
    
    # 转账功能接口
    def transfer_interface(username, to_username, money):
        user_info = db_handler.select(username)
        to_user_info = db_handler.select(to_username)
        if user_info['balance'] >= money:
            user_info['balance'] -= money
            to_user_info['balance'] += money
            # 记录流水
            user_info['flow'].append("您向%s转账%s元" % (to_username, money))
            to_user_info['flow'].append("%s向您转账%s元" % (username, money))
            
            db_handler.save(username, user_info)
            db_handler.save(to_username, to_user_info)
            
            # 记录日志
            logger_bank.info("%s向%s转账%s元" % (username, to_username, money))
            return "%s向%s转账%s元" % (username, to_username, money)
        else:
            return "%s账户余额不足" % username
    

    4.6.1.6 查看流水接口

    from db import db_handler
    from lib import common
    logger_bank = common.make_log('bank')
    
    # 查看流水接口
    def check_flow_interface(username):
        user_info = db_handler.select(username)
        # 查看流水
        logger_bank.info("%s查看了流水" % username)
        return user_info['flow']
    

    4.6.1.7 消费接口

    from db import db_handle
    from lib import common
    logger_bank = common.make_log('bank')
    
    def consume_interface(username, money):
        user_info = db_handler.select(username)
        user_info['balance'] -= money
        # 记录流水
        user_info['flow'].append("%s消费了%s元" % (username, money))
        db_handler.save(username, user_info)
    	# 记录日志
        logger_bank.info("%s消费了%s元" % (username, money))
    

    4.6.2 购物相关shopping.py

    4.6.2.1 购买商品接口

    from db import db_handler
    from interface import bank
    from lib import common
    logger_shopping = common.make_log('shopping')
    
    def buy_goods_interface(username, good_cart, money):
        user_info = db_handler.select(username)
        bank.consume_interface(username, money)
        user_info['shopping_cart'] = good_cart
        db_handler.save(username, user_info)
        # 记录日志
        logger_shopping.info("%s成功购买%s" % (username, good_cart))
        return "%s成功购买%s" % (username, good_cart)
    

    4.6.2.2 查看购物车接口

    from db import db_handler
    from lib import common
    logger_shopping = common.make_log('shopping')
    
    def check_shopping_cart_interface(username):
        user_info = db_handler.select(username)
        res = user_info['shopping_cart']
        # 记录日志
        logger_shopping.info("%s查看了购物车" % username)
        return res
    

    4.6.3 用户相关user.py

    4.6.3.1 注册接口

    from db import db_handler
    from lib import common
    logger_user = common.make_log('user')
    
    # 注册接口
    def register_interface(username, password, balance=15000):
        user = db_handler.select(username)  # 取到user_info = user_dic
        if user:  # 判断该用户名是否存在
            return "该用户名已存在"
        else:
            user_dic = {
                'username': username,
                'password': password,
                'credit': balance,
                'balance': balance,
                'locked': False,
                'time': 0,
                'flow': [],
                'shopping_cart': {}
            }
            db_handler.save(username, user_dic)
            # 记录日志
            logger_user.info("%s注册成功" % username)
            return "%s注册成功" % username
    

    4.6.3.2 提取用户信息接口

    from db import db_handler
    
    # 提取用户信息
    def get_user_info_interface(username):
        user_info = db_handler.select(username)
        return user_info
    

    4.6.3.3 锁定用户接口

    import time
    from db import db_handler
    from lib import common
    logger_user = common.make_log('user')
    
    # 锁定用户
    def locked_interface(username):
        user_info = db_handler.select(username)
        user_info['locked'] = True
        user_info['time'] = time.time()+20
        db_handler.save(username, user_info)
        # 记录日志
        logger_user.info("%s被锁定了" % username)
    

    4.6.3.4 解锁用户接口

    import time
    from db import db_handler
    from lib import common
    logger_user = common.make_log('user')
    
    # 解锁用户接口
    def unlocked_interface(username):
        user_info = db_handler.select(username)
        last_time = user_info['time'] - time.time()
        if user_info['time'] <= time.time():
            user_info['locked'] = False
            db_handler.save(username, user_info)
        	# 记录日志
        	logger_user.info("%s用户已解锁" % username)
            return "%s用户已经解锁,请重新登陆" % username
        else:
            return "%s用户已被锁,剩余锁定时间%s" % (username, last_time)
    
  • 相关阅读:
    VB.NET与C# 语法区别展示
    利用 ASP.NET 的内置功能抵御 Web 攻击 (1)
    .NET 中获取调用方法名
    C# 6.0 的那些事
    .NET基础之自定义泛型
    汽车学习---汽车知识大全【all】
    Django学习---抽屉热搜榜分析【all】
    Python 系统学习梳理_【All】
    Python学习---装饰器/迭代器/生成器的学习【all】
    Java 系统学习梳理_【All】
  • 原文地址:https://www.cnblogs.com/caojiaxin/p/14153014.html
Copyright © 2011-2022 走看看