zoukankan      html  css  js  c++  java
  • ATM

    ATM 要求

    示例代码: https://github.com/triaquae/py_training/tree/master/sample_code/day5-atm

    ================================================================================================================================= 

    作业代码: https://github.com/cheese320/atm

    bin

    • main.py 主程序
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import os
    import sys
    path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(path)  # 这样这个路径会在最后面,每次都要遍历到最后才能找到(如果中途没有同名文件的话)
    sys.path.insert(0, path)  # 将该路径插到前面去
    from core import tools
    
    
    def run():
        exit_flag = False
        # 普通用户
        if tools.username != "admin":
            # 能打印帐户信息的都是正常状态的帐户, 所以这里不显示帐户状态
            initial = '''
            ---------- {_name}帐户信息 --------- 
            credit: {_credit}
            balance: {_balance}
            enroll-date: {_enroll}
            expire_date: {_expire}
            pay_day: {_payday}
            ------------ The End ----------- 
            '''.format(_name=tools.username,
                       _credit=tools.info[tools.username]["credit"],
                       _balance=tools.info[tools.username]["balance"],
                       _enroll=tools.info[tools.username]["enroll_date"],
                       _expire=tools.info[tools.username]["expire_date"],
                       _payday=tools.info[tools.username]["pay_day"])
            print(initial)
            while not exit_flag:
                msg = '''
                1. 商城
                2. 还款
                3. 取款
                4. 转帐
                5. 帐单
                6. 退出
                '''
                print("功能列表".center(20, "*"))
                print(msg)
                print("The end".center(23, "*"))
                user_choice = input("请选择功能数字代码: ")
                if user_choice == "quit":
                    exit_flag = True
                elif not user_choice.isdigit():
                    print("输入有误, 请重输")
                    break
                else:
                    seq = int(user_choice)
                    if seq <= 0 or seq > 6:
                        print("输入有误, 请重输")
                    elif seq == 1:
                        tools.shopping_mall()
                    elif seq == 2:
                        tools.repay()
                    elif seq == 3:
                        tools.withdraw()
                    elif seq == 4:
                        tools.transfer()
                    elif seq == 5:
                        tools.bill()
                    elif seq == 6:
                        exit()
    
        else:
            while not exit_flag:
                msg2 = '''
                1. 添加帐户
                2. 解锁帐户
                3. 修改用户额度
                4. 冻结帐户
                5. 解冻帐户
                6. 退出
                '''
                print("功能列表".center(20, "*"))
                print(msg2)
                print("The end".center(23, "*"))
                print("
    ")
                user_choice2 = input("请选择功能数字代码: ")
                if user_choice2 == "quit":
                    exit_flag = True
                elif not user_choice2.isdigit():
                    print("输入有误, 请重输")
                    break
                else:
                    seq2 = int(user_choice2)
                    if seq2 <= 0 or seq2 > 6:
                        print("输入有误, 请重输")
                    elif seq2 == 1:
                        tools.new_account()
                    elif seq2 == 2:
                        tools.unlock()
                    elif seq2 == 3:
                        tools.adjustment()
                    elif seq2 == 4:
                        tools.freeze()
                    elif seq2 == 5:
                        tools.unfreeze()
                    elif seq2 == 6:
                        exit()
    
    
    run()
    View Code
    • path_define.py 执行主程序
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import os
    import sys
    
    
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.insert(0, base_dir)
    
    
    from bin import main
    if __name__ == '__main__':
        main.run()
    View Code

    conf

    • settings.py 数据库,log,路径等
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import logging
    import os
    
    
    BASE_DIR =os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    DATABASE = {
        'engine': 'file_storage',  # support mysql, postgresql in the future
        'name': 'account',
        'path': "%sdb" % BASE_DIR
    }
    
    
    LOG_LEVEL = logging.INFO
    LOG_TYPES = {
        'transaction': 'transactions.log',
        'access': 'access.log'
    }
    
    
    TRANSACTION_TYPE = {
        'repay': {'action': 'plus', 'interest': 0},
        'withdraw': {'action': 'minus', 'interest': 0.05},
        'transfer': {'action': 'minus', 'interest': 0.05},
        'consume': {'action': 'minus', 'interest': 0},
    }
    View Code

    core

    • db_handle.py 处理json文件(读, 写)
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    
    def file_db_handle(database):
        """
        数据存于文件
        :param database:
        :return: 文件存储路径
        """
        db_path = "%s" % (database['path'])
        return db_path
    
    
    
    def sql_db_handle(database):
        """
        数据存于数据库
        :param database:
        :return:
        """
        pass
    
    
    def handle(database):
        """
        根据数据存储方式判断如何获取数据
        :param database:
        :return:
        """
        if database['engine'] == 'file_storage':
            return file_db_handle(database)
        elif database['engine'] == 'sql':
            return sql_db_handle(database)
        else:
            pass
    View Code

    db

    • account.json 帐户信息
    • repository.json 商品信息
    • shopping_list.json 已购买清单
    {"Alex": {"password": "aaa", "credit": 78000, "balance": 15000.0, "enroll_date": "2017-01-01", "expire_date": "2021-01-01", "pay_day": 22, "status": 0}, "Lucy": {"password": "bbb", "credit": 15000, "balance": 15000, "enroll_date": "2017-02-02", "expire_date": "2022-02-02", "pay_day": 22, "status": 0}, "Jack": {"password": "ccc", "credit": 15000, "balance": 15000, "enroll_date": "2017-03-03", "expire_date": "2023-03-03", "pay_day": 22, "status": 2}, "admin": {"password": "root", "status": 0}, "David,999": {"password": "999", "credit": 150000, "balance": 15000, "enroll_date": "2017-01-01", "expire_date": "2021-01-01", "pay_day": 22, "status": 0}}
    account.json
    {"iphone": {"inventory": 20, "price": 9000}, "book": {"inventory": 3, "price": 50}, "bike": {"inventory": 90, "price": 600}, "cd": {"inventory": 100, "price": 83}, "fish": {"inventory": 90, "price": 40}}
    repository.json
    {"Alex": {"cd": {"buy_qty": 5, "spent": 249}, "book": {"buy_qty": 8, "spent": 100}, "iphone": {"buy_qty": 1, "spent": 9000}}, "Lucy": {"book": {"buy_qty": 3, "spent": 150}, "iphone": {"buy_qty": 1, "spent": 9000}}, "Jack": {}}
    shopping_list.json

    doc

    • flowchart
    • idea.txt 设计思路

    1. 主程序
    /*
    错误提示字体颜色: 34
    成功提示字体颜色: 31
    
    帐户状态:
    0 - normal
    1 - locked
    2 - frozen
    
    退出 :
    1. 在任一子程序, 输入quit返回上一级.
    2. 在功能列表层级, 输入quit结束程序.
    */
        1.1, 判断用户是否登录, 并返回用户信息.
             def login()
             A. 普通用户 (进入循环菜单)
                1.1.1, 打印功能列表
                     1). 商城
                         def shopping_mall()
                     2). 还款
                         def repay()
                     3). 取款
                         def "withdraw()
                     4). 转帐
                         def transfer()
                     5). 帐单
                         def bill()
                     6). 退出
             B. 管理帐户 (进入循环菜单)
                1.1.2, 打印功能列表
                     1). 添加帐户
                         def new_account()
                     2). 解锁帐户
                         def unlock()
                     3). 修改用户额度
                         def adjustment()
                     4). 冻结帐户
                         def freeze()
                     5). 解冻帐户
                         def unfreeze()
                     6). 退出
    2. 登录
       def login()
       2.1, 用户输入用户名密码
            1). 对用户输入进行处理strip()
            2). 判断
                A). 用户输入是否是quit?
                    -- 是: 退出程序
                    -- 不是: 进入下一步 ==>2.1.2.c
                B). 用户输入用户名是否存在?
                    a). 不存在: 需重输.
                    b). 存在: 判断密码是否正确
                       -- 不正确: 需重输, 重输超过三次, 锁定帐户 (提示联系管理员解锁并退出程序)
                       -- 正确: 判断用户是普通用户还是管理帐户, 返回相应帐户信息
                               -- 若帐户已冻结, 提示联系管理员解冻并退出程序
    
    3. 商城
       def shopping_mall()
       3.1, 打印商品列表
       3.2, 用户输入商品编号和购买数量
            1). 判断输入的商品是否存在, 及购买数量是否合适
              -- 商品存在且购买数量<=库存 : 下一步 ==> 3.3
              -- else: 请用户输入商品编号及购买数量
            2). 用户输入quit退出
       3.3, 判断帐户余额是否足够支付
            -- 不足够支付: 重输商品编号和购买数量 (重复3.2判断)
            -- 足够支付: 下一步 ==> 3.4
       3.4, 打印用户购买商品清单
       3.5, 购买成功
            1). 扣减帐户余额, 并打印更新的帐户信息; 同时, 更新帐户信息写回account.py
                @ATM LOG
            2). 扣减库存, 并写回repository.py
    
    4. 还款
       def repay()
       4.1, 打印当前欠款金额
       4.2, 用户输入还款金额
            1). 判断输入是否是quit
                -- 是: 退出
                -- 不是: 下一步 ==> 4.2.2
            2). 判断输入的金额是否是数字
                -- 是: 下一步 ==> 4.3
                -- 不是: 重输
       4.3, 还款成功
            1). 更新帐户余额, 并打印更新的帐户信息; 更新的帐户信息写回account.py
                @ATM LOG
    
    5. 取款
       def withdraw()
       5.1, 用户输入取款金额
       5.2, 对用户输入进行处理strip()
       5.3, 判断输入是否是quit
                -- 是: 退出
                -- 不是: 下一步 ==> 5.4
       5.4, 判断输入是否是数字
            -- 是: 下一步 ==> 5.4
            -- 不是: 重输
       5.5, 判断输入的数字是否<当前帐户余额
            -- 是: 下一步 ==> 5.5
            -- 不是: 重输
       5.6, 借钱成功
            1). 扣减帐户余额, 并打印更新的帐户信息; 更新的帐户信息写回account.py
                @ATM LOG
    
    6. 转帐
       def transfer()
       6.1, 用户输入收款用户名和转帐金额
       6.2, 判断输入是否是quit
                -- 是: 退出
                -- 不是: 下一步 ==> 6.3
       6.3, 判断用户名是否存在
            -- 存在: 判断转帐金额是否是数字
                    -- 是数字且金额小于帐户余额: 下一步 ==> 6.3
                    -- else: 重输
            -- 不存在: 重输
       6.4, 转帐成功
            1). 扣减帐户余额, 并打印更新的帐户信息; 更新的帐户信息写回account.py
                @ATM LOG
    
    7. 帐单
       def bill()
       7.1, 用户输入年,月
       7.2, 判断输入是否是quit
            -- 是: 退出程序
            -- 不是: 下一步 ==> 7.3
       7.3, 判断用户输入是否有效
            -- 有效: 下一步 ==> 7.4
            -- 无效: 重输
       7.4, 打印帐单明细
    
    8. 添加帐户
       def new_account()
       8.1, 用户输入用户名和密码及帐户信息
       8.2, 判断输入是否是quit
            -- 是: 退出程序
            -- 不是: 下一步 ==> 8.3
       8.3, 判断用户名是否存在
            -- 是: 重输
            -- 不是: 下一步 ==> 8.4
       8.4, 添加成功
            1). 将用户信息添加到account.py
    
    9. 解锁帐户
       def unlock()
       9.1, 用户输入需要解锁的用户名
       9.2, 判断输入是否是quit
            -- 是: 退出程序
            -- 不是: 下一步 ==> 9.3
       9.3, 判断帐户是否已被锁定
            -- 是: 下一步
            -- 不是: 重输
       9.4, 解锁成功
            1). 将用户信息更新到account.py
    
    10. 修改用户额度
        def adjustment()
        10.1, 用户输入用户名
        10.2, 判断输入是否是quit
            -- 是: 退出程序
            -- 不是: 下一步 ==> 10.3
        10.3, 修改成功
            1). 将用户信息更新到account.py
    
    11. 冻结帐户
        def freeze()
        11.1, 用户输入用户名
        11.2, 判断输入是否是quit
            -- 是: 退出程序
            -- 不是: 下一步 ==> 11.3
        11.3, 冻结成功
            1). 将用户信息更新到account.py
    
    12. 解冻帐户
        def unfreeze()
        12.1, 用户输入用户名
        12.2, 判断输入是否是quit
            -- 是: 退出程序
            -- 不是: 下一步 ==> 12.3
        12.3, 解冻成功
            1). 将用户信息更新到account.py
    
    
    common:
        a. 判断输入是否是quit
        b. 判断用户名是否存在
        c. 更新account.py
    idea.txt

    log

    • log.py 记录access和transactions的日志
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import os
    import sys
    import json
    import logging
    
    path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    sys.path.append(path)  # 这样这个路径会在最后面,每次都要遍历到最后才能找到(如果中途没有同名文件的话)
    sys.path.insert(0, path)  # 将该路径插到前面去
    
    
    from conf import settings
    
    
    def log(logging_type):
        """
        去掉打印在屏幕上的功能
        :param logging_type:
        :return:
        """
        # 传日志用例, 生成日志对象
        logger = logging.getLogger(logging_type)
        # 设置日志级别
        logger.setLevel(settings.LOG_LEVEL)
    
        # # 日志打印到屏幕上
        # ch = logging.StreamHandler()
        # ch.setLevel(settings.LOG_LEVEL)
    
        # 获取文件日志对象及日志文件
        log_file = "%slog\%s" % (settings.BASE_DIR, settings.LOG_TYPES[logging_type])
        # 默认log文件编译用GBK, 这里指定编码utf-8
        fh = logging.FileHandler(log_file, "a", encoding="UTF-8")
        fh.setLevel(settings.LOG_LEVEL)
    
        # 日志格式
        formatter = logging.Formatter("%(asctime)s-%(name)s-%(levelname)s-%(message)s")
    
        # 输出格式
        # ch.setFormatter(formatter)
        fh.setFormatter(formatter)
    
        # 把日志打印到指定的handler
        # logger.addHandler(ch)
        logger.addHandler(fh)
    
        return logger
    log.py

    readme.txt

    Module2-atm/
    ├── README
    ├── atm #ATM主程目录
    │ ├── __init__.py
    │ ├── bin #ATM 执行文件 目录
    │ │ ├── __init__.py
    │ │ ├── main.py # 主程序
    │ │ └── path_define.py # 执行程序
    │ ├── conf #配置文件
    │ │ ├── __init__.py
    │ │ └── settings.py
    │ ├── core #主要程序逻辑都在这个目录 里
    │ │ ├── __init__.py
    │ │ ├── db_handle.py #数据库连接引擎
    │ │ └── tools.py #所有子程序都在这儿,a包括商城程序.
    │ ├── db #用户数据存储的地方
    │ │ ├── __init__.py
    │ │ ├── account.py #便于迅速恢复同名json文件数据初始化状态.
    │ │ ├── account.json #用户帐户信息.
    │ │ ├── repository.py #便于迅速恢复同名json文件数据初始化状态.
    │ │ ├── repository.json #商品库存信息
    │ │ └── shopping_list.json #存各个用户的商城购买清单
    │ │
    │ │── doc #文档
    │ │ ├── __init__.py
    │ │ ├── idea.txt #代码思路
    │ │ └── flowchart.jpg #流程图
    │ └── log #日志目录
    │ ├── __init__.py
    │ ├── access.log #用户访问和操作的相关日志
    └── └── transactions.log #所有的交易日志
  • 相关阅读:
    List<T>和ObservableCollection<T>的相互转换
    MySQL Cannot add or update a child row: a foreign key constraint fails
    Genymotion常见问题解决方案
    关于Socket的建立及连接
    在WPF中引用WinForm的控件
    WCF调试日志
    WebSocket简介
    关于依赖注入和依赖属性
    ASP.NET MVC 学习笔记1 Talk about controller & route
    【转】关于List排序的时效性
  • 原文地址:https://www.cnblogs.com/cheese320/p/8981382.html
Copyright © 2011-2022 走看看