• ATM项目三层结构


    ATM项目三层结构

    0 分析需求

     作业需求:
    
    模拟实现一个ATM + 购物商城程序
    
    额度 15000或自定义
    实现购物商城,买东西加入 购物车,调用信用卡接口结账
    可以提现,手续费5%
    支持多账户登录
    支持账户间转账
    记录每月日常消费流水
    提供还款接口
    ATM记录操作日志
    提供管理接口,包括添加账户、用户额度,冻结账户等。。。
    用户认证用装饰器
    

    上述需求可以分为下面10个功能

    # 登录
    # 用户视图:1.接收输入用户名密码,转交逻辑接口
    #		  5.输出可视化结果
    # 逻辑接口:2.将用户名交给数据处理层,查找数据
    # 		  4.得到用户视图及数据处理的用户名密码,进行比较,将结果返回用户视图层
    # 数据处理:3.将用户名对应的数据提取出来,交给逻辑接口
    
    
    # 注册
    # 用户视图:1.接收输入用户名密码,转交逻辑接口
    #		  6.输出可视化结果
    # 逻辑接口:2.将用户名交给数据处理层,查找数据  
    #		  4.得到用户名是否存在,若不存在将用户名密码交给数据处理存储,返回用户视图,若存在返回用户视图
    # 数据处理:3.查找用户名对应的数据是否存在,结果交给逻辑接口 
    #		  5.如果用户名不存在,收到用户名密码,存储数据
    
    
    
    # 转账
    # 用户视图:1.得到在线用户名,转账的用户名及金额,判断金额有效性
    #		  8.输出可视化结果
    # 逻辑接口:2.将转账用户名交给数据处理层,查找是否存在
    #		  4.将在线用户名交给数据处理层,查看余额是否足够
    #		  6.若转账用户名存在且当前用户金额足够,计算结果,操作数据处理保存数据,返回用户视图
    # 数据处理:3.查找用户名对应的数据是否存在,若不存在直接将结果交给逻辑接口 
    #		  5.查看在线用户余额是否足够,若不足够直接将结果交给逻辑接口 
    # 		  7.若满足条件,存储数据
    
    
    # 提现
    # 用户视图:1.得到在线用户名,金额,判断金额有效性
    #		  6.输出可视化结果
    # 逻辑接口:2.将在线用户名交给数据处理层,查看余额是否足够
    #		  4.若当前用户金额足够,计算结果,操作数据处理保存数据,返回用户视图
    # 数据处理:3.查看在线用户余额是否足够,若不足够直接将结果交给逻辑接口 
    # 		  5.若满足条件,存储数据
    
    # 还款
    # 用户视图:1.得到在线用户名,金额,判断金额有效性
    #		  4.输出可视化结果
    # 逻辑接口:2.计算结果,操作数据处理保存数据,返回用户视图
    # 数据处理:3.存储数据
    
    # 查看流水
    # 用户视图:1.得到在线用户名
    #		  4.输出可视化结果
    # 逻辑接口:2.操作数据处理查找数据,得到结果,返回用户视图
    # 数据处理:3.查找在线用户流水数据,返回逻辑接口
    
    # 查看余额
    # 用户视图:1.得到在线用户名
    #		  4.输出可视化结果
    # 逻辑接口:2.操作数据处理查找数据,得到结果,返回用户视图
    # 数据处理:3.查找在线用户余额数据,返回逻辑接口
    
    # 购物
    # 用户视图:1.申请查看货物信息,		5.输出可视化的货物信息,
    #		  6.接收在线用户,选择货物编号及数量,简单判断有效性,若有效传入逻辑接口
    #		  7.输出可视化结果
    # 逻辑接口:2.申请查看货物信息,		4.得到货物信息,返回视图层,
    #		  7.调取在线用户信息,更改,传入数据处理	9.得到结果返回用户视图
    # 数据处理:3.查找货物信息,返回逻辑接口	8.保存用户数据
    
    # 查看购物车
    # 用户视图:1.得到在线用户名		5.输出可视化结果 
    #		  6.询问是否结账,简单判断有效性,若有效传入逻辑接口
    #		  8.输出可视化结果
    # 逻辑接口:2.操作数据处理查找数据,	4得到结果,返回用户视图
    #		  5.计算总价,调取在线用户信息,查看金额是否足够,如果足够则扣费,传入数据处理,不足则返回视图层结果
    #		  7.得到结果返回用户视图
    # 数据处理:3.查找在线用户流水数据,返回逻辑接口	6.保存用户数据,返回结果
    
    # 管理员功能
    # 用户视图:1.得到在线用户名
    #		  2.输出可视化结果
    # 逻辑接口:1.操作数据处理查看是否为管理员,得到结果,返回用户视图
    #		  2.若为管理员进入管理员功能
    # 数据处理:查看在线用户是否为管理员,结果返回逻辑接口
    
    

    1 用户视图层

    主要为输入输出的显示及简单的逻辑判断

    from interface import user_interface
    from interface import shop_interface
    from interface import bank_interface
    from interface import admin_interface
    from lib import common
    
    online_user = None
    
    
    # 登录
    def login():
        while 1:
            print("登录功能执行中")
            user_name = input("请输入用户名:[温馨提示:输入q退出]")
            if user_name.lower() == "q":
                break
            password = input("请输入密码:")
            flag, msg = user_interface.login_interface(user_name, password)
            if flag is False:
                print(msg)
                continue
            if flag is True:
                print(msg)
                global online_user
                online_user = user_name
                break
            pass
    
    
    # 注册
    def register():
        while 1:
            print("===============注册功能执行中")
            user_name = input("请输入用户名:[温馨提示:输入q退出]")
            if user_name.lower() == "q":
                break
            flag, msg = user_interface.check_name(user_name)
            if flag is False:
                print(msg)
                continue
            password1 = input("请输入密码:")
            password2 = input("请确认密码:")
            if password1 == password2:
                msg = user_interface.new_user(user_name, password1)
                print(msg)
                break
            else:
                print("两次密码不一致")
    
    
    # 查看余额
    @common.identify
    def check_balance():
        print("============查询余额功能执行中")
        balance, limit = bank_interface.check_balance_interface(online_user)
        print("您的余额为{}元,您的额度为{}元".format(balance, limit))
        pass
    
    
    # 提现
    @common.identify
    def withdraw():
        while 1:
            print("================提现功能执行中")
            money = input("请输入要提现的金额:[温馨提示:输入q退出]")
            if money.lower() == "q":
                break
            if not money.isdigit():
                print("请输入数字")
                continue
            flag, msg = bank_interface.withdraw_interface(online_user, money)
            if flag is False:
                print(msg)
                continue
            else:
                print(msg)
                break
    
    
    # 转账
    @common.identify
    def transfer():
        while 1:
            print("=============转账功能执行中")
            money = input("请输入要转账的金额:[温馨提示:输入q退出]")
            if money.lower() == "q":
                break
            if not money.isdigit():
                print("请输入数字")
                continue
            to_user = input("请输入转账的账号:")
            flag, msg = bank_interface.transfer_interface(online_user, to_user, money)
            if flag is False:
                print(msg)
                continue
            else:
                print(msg)
                break
    
    
    # 还款
    @common.identify
    def pay_back():
        while 1:
            print("=============还款功能执行中")
            money = input("请输入要还款的金额:[温馨提示:输入q退出]")
            if money.lower() == "q":
                break
            if not money.isdigit():
                print("请输入数字")
                continue
            flag, msg = bank_interface.pay_back_interface(online_user, money)
            if flag is False:
                print(msg)
                continue
            else:
                print(msg)
                break
    
    
    # 查看流水
    @common.identify
    def check_record():
        print("================查看流水功能执行中")
        records = bank_interface.check_record_interface(online_user)
        if len(records) == 0:
            print("当前用户无记录")
        for i in records:
            print(i)
    
    
    # 购物
    @common.identify
    def shopping():
        while 1:
            print("================购物功能执行中")
            cargo_list = shop_interface.cargo_list_interface()
            # ["mac", 20000]
            for num, cargo in enumerate(cargo_list):
                print("商品编号:[{}]    商品名:[{}]    单价:[{}]".format(num, cargo[0], cargo[1]))
            choose = input("请输入选购的商品的编号:[温馨提示:输入q退出]")
            if choose.lower() == "q":
                break
            if not choose.isdigit():
                print("请输入正确的编号")
                continue
            choose = int(choose)
            if choose not in range(len(cargo_list)):
                print("请输入正确的编号")
                continue
            quantity = input("请输入选购的商品的数量:")
            if not quantity.isdigit():
                print("请输入正确的数量")
                continue
            cargo_info = [cargo_list[choose][0], cargo_list[choose][1], quantity]
            msg = shop_interface.add_cargo_cart(online_user, cargo_info)
            print(msg)
    
    
    # 查看购物车
    @common.identify
    def check_shopping_cart():
        print("======================查看购物车功能执行中")
        shopping_cart = shop_interface.check_cart_interface(online_user)
        # {"臭豆腐": [10, 14], "鸡": [100, 2]}
        sum_price = 0
        for name, info in shopping_cart.items():
            price = info[0] * info[1]
            sum_price += price
            print("商品名:[{}]  数量:[{}]  单价:[{}]   总价:[{}]".format(name, info[0], info[1], price))
        print("=========共计:[{}]元=======".format(sum_price))
        close_choose = input("是否结账:[输入y结账]")
        if close_choose.lower() == "y":
            flag, msg = shop_interface.close_account(online_user, sum_price)
            print(msg)
    
    
    # 管理员功能
    @common.identify
    def admin():
        print("=================管理员功能执行中")
        admin_interface.check_admin(online_user)
    
    
    func_dic = {
        "1": ["注册", register],
        "2": ["登录", login],
        "3": ["转账", transfer],
        "4": ["提现", withdraw],
        "5": ["还款", pay_back],
        "6": ["查询余额", check_balance],
        "7": ["查看流水", check_record],
        "8": ["购物", shopping],
        "9": ["查看购物车", check_shopping_cart],
        "10": ["管理员", admin]
    }
    
    
    def run():
        while 1:
            print("========wu超市========")
            for num, func in func_dic.items():
                print(num, func[0])
            print("======== end ========")
            choose = input("请输入功能编号:[温馨提示:输入q退出]")
            if choose.lower() == "q":
                break
            if choose in func_dic:
                func_dic[choose][1]()
            else:
                print("请输入正确的功能编号!")
    

    2 逻辑接口层

    主要为有效的输入数据与存储数据的对比,判断结果

    2.1 管理员接口

    import logging.config
    from db import db_handler
    from conf import settings
    
    logging.config.dictConfig(settings.LOGGING_DIC)
    logger = logging.getLogger('admin')
    
    
    # 添加账户、用户额度,冻结账户
    def check_admin(online_user):
        user_dic = db_handler.select(online_user)
        if user_dic["admin"] is False:
            print("非管理员,无法使用该功能")
            return
        else:
            run_admin(online_user)
    
    
    def add_user(online_user):
        from core import src
        src.register()
    
    
    def change_limit(online_user):
        while 1:
            change_user = input("请输入更改额度的用户名:[温馨提示:输入q退出]")
            if change_user.lower() == "q":
                break
            user_dic = db_handler.select(change_user)
            if not user_dic:
                print("输入的用户名不存在")
                continue
            limit = input("请输入额度:")
            if not limit.isdigit():
                print("只能输入数字")
                continue
            user_dic["limit"] = int(limit)
            db_handler.save_data(user_dic)
            print("更改成功")
            logger.info('{}更改{}额度'.format(online_user, change_user))
    
    
    def freeze_user(online_user):
        while 1:
            freeze_user = input("请输入冻结的用户名:[温馨提示:输入q退出]")
            if freeze_user.lower() == "q":
                break
            user_dic = db_handler.select(freeze_user)
            if not user_dic:
                print("输入的用户名不存在")
                continue
            user_dic["locked"] = True
            db_handler.save_data(user_dic)
            print("冻结用户{}成功".format(freeze_user))
            logger.info('{}冻结{}'.format(online_user, freeze_user))
    
    
    admin_func = {"0": ["添加账户", add_user],
                  "1": ["更改额度", change_limit],
                  "2": ["冻结用户", freeze_user]
                  }
    
    
    def run_admin(online_user):
        while 1:
            for num, func in admin_func.items():
                print("[{}]-----[{}]".format(num, func[0]))
            cmd = input("请输入功能编号:[温馨提示:输入q退出]")
            if cmd.lower() == "q":
                break
            if cmd not in admin_func:
                print("无此功能")
                continue
            admin_func[cmd][1](online_user)
    

    2.2 用户接口

    import logging.config
    from db import db_handler
    from conf import settings
    
    logging.config.dictConfig(settings.LOGGING_DIC)
    logger = logging.getLogger('user')
    # 检查用户名是否存在
    def check_name(user):
        if db_handler.select(user):
            return False,"用户名已存在,请重新输入"
        else:
            return True,""
    
    # 创建新用户
    def new_user(user_name,password,limit = 15000):
        password = db_handler.encrypt(password)
        user_dic = {"user":user_name,"password":password,"balance":0,"limit":limit,"locked":False,"current_account":[],"shopping_cart":{},"admin":False}
        db_handler.save_data(user_dic)
        logger.info('{}注册'.format(user_name))
        return "注册成功"
    
    # 登录接口
    def login_interface(user,password):
        user_dic = db_handler.select(user)
        if not user_dic:
            return False,"用户名不存在,请重新输入"
        if user_dic["locked"]:
            return False,"该用户已被锁定"
        password = db_handler.encrypt(password)
        if user_dic["password"] == password:
            logger.info('{}登录'.format(user))
            return True,"登陆成功"
        else:
            return False,"密码错误,请重新输入"
    

    2.3 银行接口

    import logging.config
    from db import db_handler
    from conf import settings
    
    logging.config.dictConfig(settings.LOGGING_DIC)
    logger = logging.getLogger('bank')
    
    def check_balance_interface(online_user):
        user_dic = db_handler.select(online_user)
        balance = user_dic["balance"]
        limit = user_dic["limit"]
        logger.info('{}查询余额'.format(online_user))
        return balance, limit
    
    
    def withdraw_interface(online_user, money):
        user_dic = db_handler.select(online_user)
        balance = user_dic["balance"]
        money = float(money)
        balance = float(balance)
        cost = money * 1.05
        if cost > balance:
            return False, "余额不足,无法提现"
        new_balance = balance - cost
        user_dic["balance"] = new_balance
        fee = cost - money
        user_dic["current_account"].append("提现[{}]元,手续费[{}]".format(money, fee))
        db_handler.save_data(user_dic)
        logger.info('{}提现{}手续费{}'.format(online_user,money, fee))
        return True, "[{}]提现[{}]成功,手续费为[{}]".format(online_user, money, fee)
    
    
    def transfer_interface(online_user, to_user, money):
        to_user_dic = db_handler.select(to_user)
        if not to_user_dic:
            return False, "转账用户不存在,请重新输入"
        online_user_dic = db_handler.select(online_user)
        online_user_balance = online_user_dic["balance"]
        money = float(money)
        balance = float(online_user_balance)
        if money > balance:
            return False, "余额不足,无法转账"
        online_user_dic["balance"] -= money
        to_user_dic["balance"] += money
        online_user_dic["current_account"].append("转账[{}]元给[{}]".format(money, to_user))
        to_user_dic["current_account"].append("收到[{}]转账[{}]元".format(online_user, money))
        db_handler.save_data(online_user_dic)
        db_handler.save_data(to_user_dic)
        logger.info('{}转账给{}-{}'.format(online_user,to_user,money))
        return True, "[{}]转账[{}]元成功".format(online_user, money)
    
    
    def pay_back_interface(online_user, money):
        user_dic = db_handler.select(online_user)
        balance = user_dic["balance"]
        money = float(money)
        balance = float(balance)
        balance += money
        user_dic["balance"] = balance
        user_dic["current_account"].append("还款[{}]".format(money))
        db_handler.save_data(user_dic)
        logger.info('{}还款{}'.format(online_user,money))
        return True, "[{}]还款[{}]".format(online_user, money)
    
    
    def check_record_interface(online_user):
        user_dic = db_handler.select(online_user)
        records = user_dic["current_account"]
        return records
    
    
    def charge(online_user, sum_price):
        user_dic = db_handler.select(online_user)
        balance = user_dic["balance"]
        limit = user_dic["limit"]
        if balance + limit < sum_price:
            return False
        user_dic["balance"] -= sum_price
        user_dic["current_account"].append("购买消费[{}]".format(sum_price))
        db_handler.save_data(user_dic)
        logger.info("[{}]消费[{}]".format(online_user, sum_price))
        return True
    

    2.4 商店接口

    from db import db_handler
    from interface import bank_interface
    
    
    def cargo_list_interface():
        cargo_list = db_handler.get_cargo_list()
        return cargo_list
    
    
    def add_cargo_cart(online_user, cargo_info):
        '''
    
        :param online_user: 用户
        :param cargo_info: [商品名,价格,数量]
        :return:
        '''
        cargo_info[1] = int(cargo_info[1])
        cargo_info[2] = int(cargo_info[2])
        user_dic = db_handler.select(online_user)
        if cargo_info[0] not in user_dic["shopping_cart"]:
            user_dic["shopping_cart"][cargo_info[0]] = [cargo_info[1], cargo_info[2]]
        else:
            user_dic["shopping_cart"][cargo_info[0]][1] += cargo_info[2]
        db_handler.save_data(user_dic)
        return "商品[{}]  [{}]个已成功加入购物车".format(cargo_info[0], cargo_info[2])
    
    
    def check_cart_interface(online_user):
        user_dic = db_handler.select(online_user)
        shopping_cart = user_dic["shopping_cart"]
        return shopping_cart
    
    
    def close_account(online_user, sum_price):
        res = bank_interface.charge(online_user, sum_price)
        if res is False:
            return False, "余额以及额度不足,无法结账"
        else:
            user_dic = db_handler.select(online_user)
            user_dic["shopping_cart"] = {}
            db_handler.save_data(user_dic)
            return True, "结账成功,扣除{}元".format(sum_price)
    

    3 数据处理层

    主要为存储数据的提取,存储等

    import os
    import json
    import hashlib
    from conf import settings
    
    
    def select(user):
        user_file = os.path.join(settings.DB_USER_DATA_PATH, "{}.json".format(user))
        if os.path.exists(user_file):
            with open(user_file, "rb") as f:
                user_dic = json.load(f)
            return user_dic
    
    
    def save_data(user_dic):
        user = user_dic["user"]
        user_file = os.path.join(settings.DB_USER_DATA_PATH, r"{}.json".format(user))
        with open(user_file, "w",encoding="utf-8") as f:
            json.dump(user_dic, f, ensure_ascii=False)
            return True
    
    
    def encrypt(password):
        md5 = hashlib.md5()
        md5.update(password.encode("utf-8"))
        salt = "tank真帅"
        md5.update(salt.encode("utf-8"))
        res = md5.hexdigest()
        return res
    
    
    def get_cargo_list():
        with open(settings.DB_CARGO_LIST_PATH,"rb") as f:
            res = json.load(f)
            return res
    # def add_cargo():
    #     cargo = [["苹果",2],["mac",20000],["鸡",100],["臭豆腐",10]]
    #     with open(settings.DB_CARGO_LIST_PATH,"w",encoding="utf-8") as f:
    #         json.dump(cargo,f)
    # add_cargo()
    

    4 其他文件

    4.1 配置文件

    import os
    
    
    BASE_PATH = os.path.dirname(os.path.dirname(__file__))
    DB_PATH = os.path.join(BASE_PATH,"db")
    DB_USER_DATA_PATH = os.path.join(DB_PATH,"user_data")
    DB_CARGO_DATA_PATH = os.path.join(DB_PATH,"cargo_data")
    DB_CARGO_LIST_PATH = os.path.join(DB_CARGO_DATA_PATH,"cargo_list.json")
    LOG_PATH = os.path.join(BASE_PATH,"log")
    LOG_LOG_PATH = os.path.join(LOG_PATH,"log.log")
    
    
    standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' 
                      '[%(levelname)s][%(message)s]'
    
    simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
    
    test_format = '%(asctime)s] %(message)s'
    
    LOGGING_DIC = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': standard_format
            },
            'simple': {
                'format': simple_format
            },
            'test': {
                'format': test_format
            },
        },
        'filters': {},
        'handlers': {
            #打印到终端的日志
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',  # 打印到屏幕
                'formatter': 'simple'
            },
            #打印到文件的日志,收集info及以上的日志
            'default': {
                'level': 'DEBUG',
                'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,日志轮转
                'formatter': 'standard',
                # 可以定制日志文件路径
                # BASE_DIR = os.path.dirname(os.path.abspath(__file__))  # log文件的目录
                # LOG_PATH = os.path.join(BASE_DIR,'a1.log')
                'filename': LOG_LOG_PATH,  # 日志文件
                'maxBytes': 1024*1024*50,  # 日志大小 5M
                'backupCount': 5,
                'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
            },
            'other': {
                'level': 'DEBUG',
                'class': 'logging.FileHandler',  # 保存到文件
                'formatter': 'test',
                'filename': LOG_LOG_PATH,
                'encoding': 'utf-8',
            },
        },
        'loggers': {
            #logging.getLogger(__name__)拿到的logger配置
            '': {
                'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
                'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
            },
            '专门的采集': {
                'handlers': ['other',],
                'level': 'DEBUG',
                'propagate': False,
            },
        },
    }
    

    4.2 通用文件

    # 用户认证用装饰器
    
    def identify(func):
        def wrapper(*args,**kwargs):
            from core.src import online_user
            if online_user:
                res = func(*args,**kwargs)
                return res
            else:
                print("请先登录")
                from core import src
                src.login()
        return wrapper
    

    4.3 启动文件

    from core import src
    
    
    if __name__ == '__main__':
        src.run()
    
  • 相关阅读:
    Mysql数学函数不求人数据库专栏,MySQL
    下班以后就不要开电脑了,
    在ubuntu下用eclipsecdt调试memcached C language ITeye论坛
    mperham/sidekiq
    Reference C++ Reference
    请问一下哪有机械键盘的实体店可以体验一下? 外设 Chiphell 分享与交流用户体验的最佳平台 Powered by Discuz!
    Linux的cron和crontab iTech 博客园
    MIUI官方论坛 发烧友必刷的Android ROM
    机器学习视频
    crossover 海客谈, 季小军, 义乌人
  • 原文地址:https://www.cnblogs.com/achai222/p/12623035.html
Copyright © 2020-2023  润新知