• python day4 作业 ATM


    作业需求
    1. 指定最大透支额度
    2. 可取款
    3. 定期还款(每月指定日期还款,如15号)
    4. 可存款
    5. 定期出账单
    6. 支持多用户登陆,用户间转帐
    7. 支持多用户
    8. 管理员可添加账户、指定用户额度、冻结用户等
    目录结构如下:

    ATM2/
    ├── bin
    │   ├── admin_user.py  ##管理员进入界面
    │   ├── atm_user.py  # 普通用户进入界面
    │   └── __init__.py
    ├── conf
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-36.pyc
    │   │   └── settings.cpython-36.pyc
    │   └── settings.py  # 主配置文件 (首先看这个)
    ├── core
    │   ├── accounts.py   # 用户数据json 文件
    │   ├── auth.py         # 用户认证
    │   ├── bill_date.py    # 时间格式
    │   ├── db_handler.py  # 数据库
    │   ├── __init__.py
    │   ├── logger.py     #log 文件
    │   ├── main.py     # 主函数
    │   ├── __pycache__
    │   │   ├── accounts.cpython-36.pyc
    │   │   ├── auth.cpython-36.pyc
    │   │   ├── bill_date.cpython-36.pyc
    │   │   ├── db_handler.cpython-36.pyc
    │   │   ├── __init__.cpython-36.pyc
    │   │   ├── logger.cpython-36.pyc
    │   │   ├── main.cpython-36.pyc
    │   │   └── transaction.cpython-36.pyc
    │   └── transaction.py
    ├── db
    │   ├── accounts
    │   │   ├── admin.json
    │   │   ├── liang2.json
    │   │   └── liang.json
    │   └── __init__.py
    ├── __init__.py
    └── log
    ├── access.log
    ├── accounts
    ├── __init__.py
    └── transactions.log

    说下心得哈。首先我。我也是第一次写这种代码 最开始的时候一个文件相互调来调去的确实繁琐,

    后面看ygqygq2 老哥写的,豁然开朗。第一步就是看代码。先把代码一行行去读起来。因为我也没

    学多久。久久看了两天才把老哥的代码看懂。实在没办法。 还有就是看代码的顺序。第一看的是配置

    文件,后面你文件头里面的import 是那个文件,这样以此类推的看下去。

    我的代码还是有点问题,没有老哥的代码写的完美。那么上代码把

    settings.py 

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    import sys,os,logging
    
    
    BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    
    BILL_DAY=25
    
    DATABASE={
        'engine':'file_storage',
        'name':'accounts',
        'path':'%s/db' %BASE_DIR
    }
    
    LOG_LEVEL=logging.INFO
    
    LOG_TYPES={
        'transaction':'transactions.log',
        'access':'access.log',
    }
    
    LOG_DATABASE={
        'engine': 'file_storage',
        'name': 'accounts',
        'path': '%s/log' %BASE_DIR
    }
    
    TRANSACTION_TYPE={
        'repay':{'action':'plus','interest':0}, # 还款
        'receive':{'action':'plus','interest':0}, #接受
        'withdraw':{'action':'munus','interest':0.05}, #提款
        'transfer':{'action':'minus','interest':0.05}, # 转出
        'pay':{'action':'minus','interest':0}, #支付
        'sava':{'action':'plus','interest':0}, #存钱
    }
    
    ACCOUNT_FORMAT={
        '''
        用户数据格式
        {"enroll_date": "2016-01-02", "password": "abc", "id": 1000, "credit": 15000,
         "status": 0, "balance": 1000.0, "expire_date": "2021-01-01", "pay_day": 22}
        '''
    }
    View Code

    db_handler.py 

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    
    def file_db_handle(conn_params):
        '''
        存放数据的文件路径
        :param conn_params:
        :return:
        '''
        db_path='%s/%s' %(conn_params['path'],conn_params['name'])
    
        return db_path
    
    def db_handler(conn_parms):
        '''
        数据库类型
        :param conn_parms:
        :return:
        '''
        if conn_parms['engine']=='file_storage':
            return file_db_handle(conn_parms)
        elif conn_parms['engine']=='mysql':
            pass
    View Code

    auth.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    import os,sys
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    import os
    from core import db_handler
    from core import accounts
    from conf import settings
    import json
    import datetime
    
    
    
    def acc_auth(account,password):
        '''
        用户验证函数
        :param account:
        :param password:
        :return:
        '''
        db_path=db_handler.db_handler(settings.DATABASE)
        account_file="%s/%s.json" %(db_path,account)
    
        if os.path.isfile(account_file):
            with open(account_file) as f:
                account_data=json.load(f)
                if account_data["password"] == password:
                    exp_time_stamp=datetime.datetime.strptime(account_data['expire_date'], "%Y-%m-%d")
                    status=account_data['status']
    
                    if datetime.datetime.now() > exp_time_stamp:
                        print("%s账户已近过期了.请联系管理员"%account)
                    elif status == 0 or status == 8:
                        return account_data
                    else:
                        print("账户已经过期了。或者不是管理员!!")
                else:
                    print("密码错误")
        else:
            print("文件不存在")
    
    
    
    def acc_login(user_data,log_obj):
        '''
        用户登录 的函数
        :param user_data:
        :param log_obj:
        :return:
        '''
        exit_count=3 #登录次数
        retry_connt=0 # 初始化重试数据
        same_account=0 #输入时。相同数据计数
        last_account="" # 初始化上一次输入的用户
        while user_data['is_authenticated'] is not True and retry_connt<exit_count:
            account=input("请输入用户名:").strip()
            password=input("请输入密码").strip()
            if account==last_account:
                same_account+=1
            auth=acc_auth(account,password)
            last_account=account
            if auth:
                user_data['is_authenticated']=True
                user_data['account_id']=account
    
                return auth
            retry_connt+=1
        else:
            if same_account==exit_count -1:
                log_obj.error("account [%s] too many login attempts" % account)
            exit()
    
    
    def acc_check(account):
        '''
        查询账户是否存在
        :param account:
        :return:
        '''
    
        db_path=db_handler.db_handler(settings.DATABASE)
        account_file="%s/%s.json" %(db_path,account)
        if os.path.isfile(account_file):
            with open(account_file,'r') as f:
                account_data=json.load(f)
                status=account_data["status"]
    
                exp_time_stamp=datetime.datetime.strptime(account_data['expire_date'],"%Y-%m-%d")
                if datetime.datetime.now()>exp_time_stamp:
                    print("此%s账户已经过期。请联系管理员"%account)
    
                else:
                    return account_data
        else:
            return False
    
    def sign_up():
        '''
        用户注册和admin 管理员用户
        :return:
        '''
        pay_dat=22
        exit_flag=True
        while exit_flag is True:
            account=input("请输入你的用户名:").strip()
            password=input("请输入你的密码:").strip()
    
            exit_flag=acc_check(account)
            if exit_flag:
                print("次用户已经存在。请选择其他用户名")
            else:
                # 现在的时间格式
                today=datetime.datetime.now().strftime("%Y-%m-%d")
                # 默认五年后过期
                after_5_years=int(datetime.datetime.now().strftime('%Y')) +5
                #五年后的今天
                after_5_years_today=datetime.datetime.now().replace(year=after_5_years)
                #五年后的昨天
                expire_day=(after_5_years_today + datetime.timedelta(-1)).strftime('%Y-%m-%d')
                """用户数据库格式
                 {"enroll_date": "2016-01-02", "password": "abc", "id": 1000, "credit": 15000,"balance":0,
                  "status": 0, "balance": 1000.0, "expire_date": "2021-01-01", "pay_day": 22}
                """
                account_data={"enroll_date":today,"password":password,"id":account,"credit":15000,"balance":0,
                              "status":0,"expire_date":expire_day,"pay_day":pay_dat}
                print(account_data)
                accounts.dump_account(account_data)
                print("添加成功 用户ID:[%s]!!!" %account)
    
                return True
    
    def modify():
        '''
        修改用户信息
        :return:
        '''
        items=["password","credit","status","expire_day","pay_day"]
        acc_data=False
        contine_flag=False
        while acc_data is False:
            account=input("请输入你要修改的用户名:").strip()
            # 丢到验证函数中
            account_data=acc_check(account)
            if account_data is False:
                print("你输入的用户不存在")
            else:
                while contine_flag is not True:
                    #判断输入json 格式
                    print('''请你输入json 格式
    {
        "password": "abc",
        "credit": 15000,
        "status": 0,
        "expire_date": "2021-01-01",
        "pay_day": 22
    }''')
                    modify_items=input("请你输入json格式").strip()
                    try:
                        modify_items=json.loads(modify_items)
                    except Exception as e:
                        print("输入错误!!!")
                        continue
    
                    error_flag=False # 初始化错误标记
                    for index in modify_items:
                        if index in items:
                        # 修改用户数据 就是字典修改方式
                            account_data[index]=modify_items[index]
                        else:
                            print("输入有错误!!!")
                            continue
                    if error_flag:
                        continue
                    #再写到文件中
                    accounts.dump_account(account_data)
                    print("修改成功!!!")
                    contine_flag=True
                    acc_data = True
        return True
    View Code

    accounts.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    
    import json
    import time
    from core import db_handler
    from conf import settings
    
    
    def load_current_balance(account_id):
        '''
        json load 用户文件
        :param account_id:
        :return:
        '''
        db_path=db_handler.db_handler(settings.DATABASE)
        # db_path 调用的是配置文件的DATABASE路径
        # db_path 完整的路径是 ATMdbaccounts
        account_file="%s/%s.json" %(db_path,account_id)
    
        with open(account_file,'r') as f:
            acc_data=json.load(f)
    
            return acc_data
    
    def dump_account(account_data):
        '''
        写到文件当中
        :param account_data:
        :return:
        '''
        db_path=db_handler.db_handler(settings.DATABASE)
        # 这个数据的目录 ATMdbaccounts
        account_file="%s/%s.json" %(db_path,account_data['id'])
    
        with open(account_file,'w') as f:
            acc_data=json.dump(account_data,f)
    
        return True
    View Code

    bill_date.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    
    from conf import settings
    import datetime
    
    
    def get_bill_time(year_month):
        '''
        获取给出的年-月的信用卡账单 月份起止时间
        :param year_month:  年-月
        :return:  返回时间
        '''
        the_bill_day="%s-%s" %(year_month,settings.BILL_DAY)
        bill_begin_time=datetime.datetime.strptime(the_bill_day,"%Y-%m-%d")
        year=bill_begin_time.year
        month=bill_begin_time.month
        if month ==12:
            month=1
            year +=1
        else:
            month+=1
        bill_end_time=datetime.datetime(year,month,settings.BILL_DAY)
        return bill_begin_time,bill_end_time
    View Code

     transaction.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    #
    
    from conf import settings
    from core import accounts
    from core import logger
    
    
    # transaction logger
    
    
    def make_transaction(log_obj, account_data, tran_type, amount, **others):
        '''
        deal all the user transactions
        :param account_data: user account data
        :param tran_type: transaction type
        :param amount: transaction amount
        :param others: mainly for logging usage
        :return:
        '''
        # 交易金额 为浮点型
        amount = float(amount)
        # 判断交易类型是否在存在里面
        if tran_type in settings.TRANSACTION_TYPE:
    
            # 利息的计算
            interest = amount * settings.TRANSACTION_TYPE[tran_type]['interest']
            # 我现有的金额
            old_balance = account_data['balance']
            #判断是否是加金额
            if settings.TRANSACTION_TYPE[tran_type]['action'] == 'plus':
                # 金额的加 是 本金+交易金额+ 利息
                new_balance = old_balance + amount + interest
            # 如果为减
            elif settings.TRANSACTION_TYPE[tran_type]['action'] == 'minus':
                # 那就是 本金 减 交易金额 减 利息
                new_balance = old_balance - amount - interest
                # check credit
                #减去了 所有的 如果大于0
                if new_balance < 0:
                    # 输出用户的额度 、 减少了多少金额  、剩下了多少额度
                    print('''Your credit [33[31;1m%s33[0m] is not enough for this transaction [-%s],
                    your current balance is [33[32;1m%s33[0m]'''
                          % (account_data['credit'], (amount + interest), old_balance))
                    return
            #把用户剩余的额度 写入到文件中
            account_data['balance'] = new_balance
            # json 序列化到文件中
            accounts.dump_account(account_data)  # save the new balance back to file
            #输出用户的用户名、交易类型、交易金额、利息
            log_obj.info("account:%s   action:%s    amount:%s   interest:%s" %
                         (account_data['id'], tran_type, amount, interest))
            # 返回最新的用户数据
            return account_data
        #不存在的交易类型
        else:
            print("33[31;1mTransaction type [%s] is not exist!33[0m" % tran_type)
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    # from conf import settings
    # from core import accounts
    # from core import logger
    #
    #
    #
    #
    #
    # def make_transaction(log_obj,account_data,tran_type,amount,**kwargs):
    #     '''
    #     交易函数
    #     :param log_obj:  log
    #     :param account_data:  用户数据
    #     :param tran_type: 交易类型
    #     :param amount:  金额action
    #     :param kwargs: 主要用于日志
    #     :return:
    #     '''
    #     #交易金额 为浮点型
    #     amount=float(amount)
    #
    #     if tran_type in settings.TRANSACTION_TYPE:
    #
    #         #利息的计算
    #         interest=amount *settings.TRANSACTION_TYPE[tran_type]['interest']
    #         print(interest)
    #         # 现有的余额
    #         old_balance= account_data['balance']
    #
    #         #判断是否加金额
    #         if settings.TRANSACTION_TYPE[tran_type]['action'] == 'plus':
    #             # 金额 就是本金+交易金额+利息
    #             new_balance=old_balance+amount+interest
    #             print(new_balance)
    #         #如果是减去
    #         elif settings.TRANSACTION_TYPE[tran_type]['action']=='minus':
    #             new_balance=old_balance-amount-interest
    #             if new_balance<0:
    #                 print("你的额度为%s .你本次交易的金额(+利息的)%s 你的余额为%s"%(account_data['credit'],(amount+interest),account_data['old_balance']))
    #                 return None
    #         #把用户更新的额度写入到文件中
    #         account_data['balance']= new_balance
    #
    #         # json 序列化到文件中
    #         xx=accounts.dump_account(account_data)
    #         # 输出用户的用户名、交易类型、交易金额、利息
    #         log_obj.info("account:%s   action:%s    amount:%s   interest:%s" %
    #                      (account_data["id"],tran_type,amount,interest))
    #
    #         return xx
    #
    #     else:
    #         print("错误类型")
    # # money=input("输入需要存款的数量:>>>")
    # # account_data={'enroll_date': '2018-01-31', 'password': '123456', 'id': 'liang', 'credit': 15000, 'balance': 0, 'status': 0, 'expire_date': '2023-01-30', 'pay_day': 22}
    # #
    # # x=make_transaction(trans_logger,account_data,'sava',money)
    # # print(x)
    View Code

    logger.py 

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang
    
    import logging
    import datetime
    from conf import settings
    from core import bill_date
    
    def logger(log_type):
    
        # 创建loggin
        logger = logging.getLogger(log_type)
        logger.setLevel(settings.LOG_LEVEL)
    
        # create console handler and set level to debug
        ch = logging.StreamHandler()
        ch.setLevel(settings.LOG_LEVEL)
    
        # create file handler and set level to warning
        # 创建 log 文件的一个级别
        log_file = "%s/log/%s" % (settings.BASE_DIR, settings.LOG_TYPES[log_type])
        fh = logging.FileHandler(log_file)
        fh.setLevel(settings.LOG_LEVEL)
        # create formatter
        # log的输入格式
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
        # add formatter to ch and fh
    
        ch.setFormatter(formatter)
        fh.setFormatter(formatter)
    
        # add ch and fh to logger
        logger.addHandler(ch)
        logger.addHandler(fh)
    
        return logger
        # 'application' code
        '''logger.debug('debug message')
        logger.info('info message')
        logger.warn('warn message')
        logger.error('error message')
        logger.critical('critical message')'''
    
    
    def show_log(account, log_type, year_month):
        """
        显示日志内容
        :param user_name: 用户名
        :param log_type: 日志类型
        :return:
        """
        #给出的账单时间   结束的账单时间
        begin_time, end_time = bill_date.get_bill_time(year_month)
    
        # log文件的所在路径
        log_file = "%s/log/%s" % (settings.BASE_DIR, settings.LOG_TYPES[log_type])
        # 打开log文件
        file = open(log_file)
        print("-".center(50, "-"))
        for line in file:
            #log 时间
            log_time = datetime.datetime.strptime(line.split(",")[0], "%Y-%m-%d %H:%M:%S")
            # 记录的用户
            user_name = line.split()[7].split(":")[1]
            # 帐单生成日是25号,则每月帐单是从上月25日到本月24日之间
            if account == user_name and begin_time <= log_time < end_time:
                print(line.strip())
        print("-".center(50, "-"))
        file.close()
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    # import os,sys
    # BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    # sys.path.append(BASE_DIR)
    # import logging
    # import datetime
    # from conf import settings
    # from core import bill_date
    #
    #
    # def logger(log_type):
    #
    #     #创建loggin
    #     logger=logging.getLogger(log_type)
    #     logger.setLevel(settings.LOG_LEVEL)
    #
    #     ch=logging.StreamHandler()
    #     ch.setLevel(settings.LOG_LEVEL)
    #
    #     # 创建log 文件 级别
    #     log_file="%s/log/%s" %(settings.BASE_DIR,settings.LOG_TYPES[log_type])
    #     fh =logging.StreamHandler(log_file)
    #     fh.setLevel(settings.LOG_LEVEL)
    #
    #     #log 的输入格式
    #     formatter=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    #
    #     ch.setFormatter(formatter)
    #     fh.setFormatter(formatter)
    #
    #     return logger
    #
    # def show_log(account,log_type,year_month):
    #     '''
    #     显示 日志内容
    #     :param account: 用户 名
    #     :param log_type:  日志类型
    #     :param year_month:
    #     :return:
    #     '''
    #     # 给出账单 时间 结束时间
    #     begin_time,end_time=bill_date.get_bill_time(year_month)
    #     # log 文件路径
    #     log_file="%s/log/%s" %(settings.BASE_DIR,settings.LOG_TYPES[log_type])
    #
    #     # 打开log文件
    #     file=open(log_file,'r')
    #     print("-".center(50,"-"))
    #     for line in file:
    #         # log 时间
    #         log_time=datetime.datetime.strptime(line.split(",")[0],"%Y-%m-%d %H:%M:%S")
    #         # 记录用户
    #         user_name=line.split()[7].split(":")[1]
    #         #账单生成日是25 号 则每月账单是从上月25到本月24之间
    #         if account==user_name and begin_time<=log_time<end_time:
    #             print(line.strip())
    #     print("-".center(50,"-"))
    #     file.close()
    #
    #
    #
    #
    # x=logger('transaction')
    # x.info("account:%s   action:%s    amount:%s   interest:%s" %('liang','tran_type','amount','interest'))
    View Code

     main.py  

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    import os,sys
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    
    from core import auth
    from core import logger
    from core import accounts
    from core import transaction
    from core import db_handler
    from conf import settings
    import datetime
    import time
    import os
    
    # 建立transaction.log 文件
    trans_logger=logger.logger('transaction')
    #建立 access.log 文件
    access_logger=logger.logger('access')
    
    # 临时账户数据、仅保存在内存中
    user_data={
        'account_id':None,
        'is_authenticated':False,
        'account_data':None
    }
    
    def disp_account_info(account_data):
        '''
        格式化输出账户信息(管理员可直接使用)
        #去除 password 字段显示
        :param account_data: 账户信息
        :return:
        '''
    
        ignore_display=["password"]
        for k in account_data:
            if k in ignore_display:
                continue
            else:
                print("{:<20}:33[32;1m{:<20}33[0m".format(k, account_data[k]))
    
    
    def admin_account_info(acc_data):
        '''
        管理员查看其它用户
        :param acc_data:
        :return:
        '''
        user_id=acc_data["account_id"]
        account_data=acc_data["account_data"]
        status=account_data["status"]
        if status ==8:
            admin_input_id=input("请输入你需要查询的ID").strip()
            new_user_info=auth.acc_check(admin_input_id)
            new_user_status=new_user_info["status"]
            if new_user_status ==8:
                if user_id==admin_input_id:
                    disp_account_info(new_user_info)
                    return True
                else:
                    print("你能查询其它管理员【%s】的信息"%(admin_input_id))
            elif new_user_info !=8:
                disp_account_info(new_user_info)
        else:
            exit("非法操作")
    
    def account_info(acc_data):
        '''
        普通用户打印登录用户信息
        :param acc_data:  登录信息
        :return:
        '''
        # 用户ID
        account_id=acc_data["account_id"]
        #
        account_data=acc_data["account_data"]
        #
        status=account_data["status"]
        #
        if status !=8:
    
            disp_account_info(account_data)
            return True
        else:
            exit("谢谢!!!!!")
    
    def get_user_data():
        '''
        登录并获取新的user-data
        :return:
        '''
        account_data=auth.acc_login(user_data,access_logger)
    
        if user_data["is_authenticated"]:
            #此刻就是有数据了
            user_data["account_data"]=account_data
            # 返回最新用户数据
            return user_data
        else:
            return None
    
    def pay(amount):
        '''
        消费付款
        :param amount: 付款金额
        :return:
        '''
        #用户数据
        acc_data=get_user_data()
        account_data=accounts.load_current_balance(acc_data['account_id'])
        if amount>0:
            # new_balance 是用户的最新数据。有两个结果 。一个是None 一个是用户数据
            new_balance=transaction.make_transaction(trans_logger,account_data,'pay',amount)
            if new_balance:
                return True
        # 小于0
        else:
            print("你输入的金额需要大于0%s"%amount)
            return None
    def repay(acc_data):
        '''
        还款
        :param acc_data:
        :return:
        '''
        print(acc_data)
        account_data = accounts.load_current_balance(acc_data['account_id'])
        current_blance=''' -------- balance info ---------
            Credit : %s
            Balance: %s
        '''%(account_data['credit'],account_data['balance'])
        print(current_blance)
        back_flag=False
        while not back_flag:
            print("按b退出")
            # 还款金额
            reap_amount=input("请输入你还款的金额:>>").strip()
            if len(reap_amount) >0 and reap_amount.isdigit():
                # new_balance = 用户最新数据
                new_balance=transaction.make_transaction(trans_logger,account_data,'repay',reap_amount)
                time.sleep(0.1)
                if new_balance:
                    print("你的余额为%s"%(new_balance['balance']))
            elif reap_amount =='b':
                back_flag=True
            else:
                print("输入错误。请从新输入!!!!%s"%(reap_amount))
    
    def withdraw2(acc_data):
        '''
        提款
        :param acc_data:
        :return:
        '''
        # 用户最新数据
        account_data=accounts.load_current_balance(acc_data['account_id'])
        current_blance=''' -------- balance info ---------
            Credit : %s
            Balance: %s
        '''%(account_data['credit'],account_data['balance'])
        print(current_blance)
        back_flag=False
        while not back_flag:
            print("输入b 跳出")
            withdrwa_amount=input("请输入提款金额:>>>").strip()
            if len(withdrwa_amount)>0  and withdrwa_amount.isdigit():
    
                new_balance2=transaction.make_transaction(transaction,account_data,'withdraw',withdrwa_amount)
    
                time.sleep(0.1)
                if new_balance2:
                    print("你剩余的余额%s" %new_balance2['balance'])
            elif withdrwa_amount=='b':
                back_flag=True
            else:
                print("你输入错误!!!%s"%withdrwa_amount)
    
    def withdraw(acc_data):
        '''
        提款
        print current balance and let user do the withdraw action
        :param acc_data:
        :return:
        '''
        # 用户最新数据
        account_data = accounts.load_current_balance(acc_data['account_id'])
        # 格式化输出用户的 额度+ 用户的账目
        current_balance = ''' --------- BALANCE INFO --------
            Credit :    %s
            Balance:    %s''' % (account_data['credit'], account_data['balance'])
        print(current_balance)
        back_flag = False
        while not back_flag:
            print("Tip: [b] to back")
            # 输入还款金额
            withdraw_amount = input("33[33;1mInput withdraw amount:33[0m").strip()
            # 长度大于0 并且是数字
            if len(withdraw_amount) > 0 and withdraw_amount.isdigit():
                #返回用户最新的数据
                new_balance = transaction.make_transaction(trans_logger, account_data, 'withdraw', withdraw_amount)
                time.sleep(0.1)  # 处理显示问题
                # 如果有数据, 就显示现有的账目
                if new_balance:
                    print('''33[42;1mNew Balance:%s33[0m''' % (new_balance['balance']))
            elif withdraw_amount == 'b':
                back_flag = True
            elif withdraw_amount == 'q' and withdraw_amount == 'exit':
                exit("谢谢下次再来")
                break
    
            else:
                print('[33[31;1m%s33[0m] is not a valid amount, only accept integer!' % withdraw_amount)
    
    
    
    
    def transfer(acc_data):
        '''
        打印出当前余额  并转钱
        :param acc_data:
        :return:
        '''
        # 用户最近数据
        account_data=accounts.load_current_balance(acc_data['account_id'])
    
    
        #显示用户的额度
        current_blance=''' -------- balance info ---------
            Credit : %s
            Balance: %s
        '''%(account_data['credit'],account_data['balance'])
        print(current_blance)
        back_flag=False
        while not back_flag:
            #输入转给谁 .不能转给自己
            recevier=input("输入你需要转钱的用户:>>>>").strip()
            if str(recevier)==str(account_data["id"]):
                print("不能转给自己")
                continue
            elif recevier=='b':
                back_flag=True
            else:
                #检查是否有这个ID
                receiver_account_data=auth.acc_check(recevier)
    
                #判断这个Id 是否过期和是不是普通用户
                status=receiver_account_data["status"]
                print(status)
                if status ==0:
                    # 如果等于0就让他输入金额
                    transfer_amount=input("输入你需要转的金额:>>")
                    if len(transfer_amount) >0 and transfer_amount.isdigit():
                        new_blance=transaction.make_transaction(trans_logger,account_data,'transfer',transfer_amount)
                        transaction.make_transaction(trans_logger,receiver_account_data,'receive',transfer_amount)
                        if new_blance:
                            time.sleep(0.2)
                            print("转钱成功!!!")
                    else:
                        print("请输入大于0的金额!!!!")
                    if transfer_amount=='b':
                        back_flag=True
                else:
                    print("不能转为其他人")
    
    
    
    def pay_check(acc_data):
        '''
        查询账单详情
        :param acc_data:
        :return:
        '''
        bill_data=input("请输入你需要查询的年月份 例如[2018-01]:>>>>").strip()
        log_path=db_handler.db_handler(settings.DATABASE)
        bill_log="%s/%s.bills" %(log_path,acc_data["account_id"])
        if not os.path.exists(bill_log):
            print("没有记录用户[%s]"%acc_data["account_id"])
            return
        print("请输入你需要查询的ID %s"%acc_data["account_id"])
        print("-".center(50,'#'))
        with open(bill_data,'r') as f:
            for bill in f:
                print(bill)
                b_data=bill.split(" ")[0]
                if bill_data==b_data:
                    print("%s"%bill.strip())
        log_type="transactions"
        print("%s" %acc_data["account_id"])
        logger.show_log(acc_data["account_id"],log_type,bill_data)
    
    
    def save(acc_data):
        '''
        存钱
        :param acc_data:
        :return:
        '''
    
        account_data=accounts.load_current_balance(acc_data["account_id"])
        print(account_data)
        current_balance = ''' --------- BALANCE INFO --------
                Credit :    %s
                Balance:    %s
    
        (Tip: input [b] to back)''' % (account_data['credit'], account_data['balance'])
        print(current_balance)
        back_flag=False
        while not back_flag:
            # 输入存款金额
            save_amount=input("输入你需要存款的金额:>>>").strip()
            if save_amount == 'b':
                back_flag = True
            elif len(save_amount) > 0 and save_amount.isdigit():
    
                new_balance = transaction.make_transaction(trans_logger, account_data, 'save', save_amount)
                time.sleep(0.1)  # 解决日志显示问题
                if new_balance:
                    print('''33[42;1mNew Balance:%s33[0m''' % (new_balance['balance']))
                    back_flag = True
            else:
                print('[33[31;1m%s33[0m] is not a valid amount, only accept integer!' % save_amount)
    
    
    def logout(acc_data):
        '''
        清除认证信息、退出
        :param acc_data:
        :return:
        '''
        exit("谢谢!!!!".center(50,'#'))
    
    def interactive(acc_data):
        '''
        普通用户界面
        :param acc_data:
        :return:
        '''
    
        status=acc_data["account_data"]["status"]
    
        if status==8:
            print("管理员不能查看!!%s"%acc_data["account_id"])
        menu=u'''
        ----------- user bank ------------
        1. 账户信息
        2. 还款
        3. 取款
        4. 转账
        5. 存款
        6. 账单
        7. 退出
        '''
    
        menu_dic={
            '1':account_info,
            '2':repay,
            '3':withdraw,
            '4':transfer,
            '5':save,
            '6':pay_check,
            '7':logout,
    
        }
        exit_flag=False
        while not exit_flag:
            print(menu)
            user_option=input(":>>>").strip()
            if user_option in menu_dic:
                #print(acc_data)
                menu_dic[user_option](acc_data)
    
            else:
                print("输入错误!!! ")
    
    
    def get_bill(account_id):
        '''
        生成账单 、定义每月25 日
        :param account_id:
        :return:
        '''
        #当前时间
        i = datetime.datetime.now()
        year_month="%s-%s" %(i.year,i.month)
        account_data=accounts.load_current_balance(account_id)
        balance=account_data["balance"]# 可用额度
        credit=account_data["credit"]
        if i.day !=settings.BILL_DAY:
            print("33[31;1mToday is not the bill generation day!33[0m")
        if balance>=credit:
            repay_amount=0
            bill_info="Account [33[32;1m%s33[0m] needn't to repay." %account_id
    
        else:
            repay_amount=credit-balance
            bill_info="Account [33[32;1m%s33[0m] need to repay [33[33;1m%s33[0m]" 
                        % (account_id, repay_amount)
        print(bill_info)
        log_path=db_handler.db_handler(settings.LOG_DATABASE)
        bill_log="%s/%s.bills" %(log_path,account_data["account_id"])
        with open(bill_log,'a+') as f:
            f.write("bill_date: %s account_id: %s need_repay: %d
    " % (year_month, account_id, repay_amount))
    
    def get_all_bill():
        db_path=db_handler.db_handler(settings.DATABASE)
        for root, dirs , files in os.walk(db_path):
            for file in files:
                #分割出来结尾的文件
                if os.path.splitext(file)[1] =='json':
                    account_id=os.path.splitext(file)[0] # 账户id
                    #检查这个账户
                    account_data=auth.acc_check(account_id)
                    status=account_data['status']
    
                    print("Account bill:".center(50,'='))
                    #除了管理员其他人都应该出账单
                    if status !=8:
                        disp_account_info(account_data)#显示账户详情
                        get_bill(account_id)
                    print("End".center(50,'-'))
        return True
    
    
    
    def chenk_admin(func):
        '''
        检查是否是管理员
        :param func:
        :return:
        '''
    
        def inner(*args,**kwargs):
            if user_data['account_data'].get('status',None)==8:
                ret=func(*args,**kwargs)
                return ret
            else:
                print("不是管理员")
        return inner
    
    
    
    def manage_func(acc_data):
        '''
        管理员功能
        :param acc_data:
        :return:
        '''
        menu = u'''
        ------- Admin erea ---------33[32;1m
        1.  添加账户
        2.  查询用户信息
        3.  用户信息修改(冻结帐户、用户信用卡额度等)
        4.  生成全部用户帐单
        5.  退出
        33[0m'''
    
        menu_dic={
            '1':'auth.sign_up()',
            '2':'account_info(acc_data)',
            '3':'auth.modify()',
            '4':'get_all_bill()',
            '5':'logout(acc_data)',
        }
        go_flag=True
        while go_flag:
            print(menu)
            user_option=input(":>>").strip()
            if user_option in menu_dic.keys():
                go_flag=eval(menu_dic[user_option])
            else:
                print("33[31;1mOption does not exist!33[0m")
    
    def run():
        '''
        这个是普通用户运行的界面
        :return:
        '''
        print("Welocome to ATM ".center(50,'#'))
        user_data=get_user_data()
    
        interactive(user_data)
    
    
    
    def admin_run():
        print(" ATM admin manager".center(50,'#'))
        user_data=get_user_data()
        manage_func(user_data)
    View Code

    admin_user.py 

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    import os
    import sys
    
    
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(base_dir)
    
    from core import main
    
    if __name__ == '__main__':
        main.admin_run()
    
    # 管理员账户 admin  密码 abc
    View Code

    atm_user.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: liang 
    import os
    import sys
    
    
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(base_dir)
    
    from core import main
    
    if __name__ == '__main__':
        main.run()
    
    # 普通用户 liang 密码 123456
    View Code

    文件的存储位置如以下图片:

    测试如下:

    C:UsersAdministratorAppDataLocalProgramsPythonPython36python36.exe G:/python/ATM2/bin/atm_user.py
    #################Welocome to ATM #################
    请输入用户名:liang
    请输入密码123456

    ----------- user bank ------------
    1. 账户信息
    2. 还款
    3. 取款
    4. 转账
    5. 存款
    6. 账单
    7. 退出

    :>>>1
    enroll_date :2018-01-31
    id :liang
    credit :15000
    balance :1888888888737010.2
    status :0
    expire_date :2023-01-30
    pay_day :22

    ----------- user bank ------------
    1. 账户信息
    2. 还款
    3. 取款
    4. 转账
    5. 存款
    6. 账单
    7. 退出

    :>>>2
    {'account_id': 'liang', 'is_authenticated': True, 'account_data': {'enroll_date': '2018-01-31', 'password': '123456', 'id': 'liang', 'credit': 15000, 'balance': 1888888888737010.2, 'status': 0, 'expire_date': '2023-01-30', 'pay_day': 22}}
    -------- balance info ---------
    Credit : 15000
    Balance: 1888888888737010.2

    按b退出
    请输入你还款的金额:>>10
    2018-01-31 15:41:35,310 - transaction - INFO - account:liang action:repay amount:10.0 interest:0.0
    你的余额为1888888888737020.2
    按b退出
    请输入你还款的金额:>>b

    ----------- user bank ------------
    1. 账户信息
    2. 还款
    3. 取款
    4. 转账
    5. 存款
    6. 账单
    7. 退出

    :>>>4
    -------- balance info ---------
    Credit : 15000
    Balance: 1888888888737020.2

    输入你需要转钱的用户:>>>>admin
    8
    不能转为其他人
    输入你需要转钱的用户:>>>>liang
    不能转给自己
    输入你需要转钱的用户:>>>>liang2
    0
    输入你需要转的金额:>>1000
    2018-01-31 15:42:21,639 - transaction - INFO - account:liang action:transfer amount:1000.0 interest:50.0
    2018-01-31 15:42:21,639 - transaction - INFO - account:liang2 action:receive amount:1000.0 interest:0.0
    转钱成功!!!
    输入你需要转钱的用户:>>>>











  • 相关阅读:
    【学习笔记】整除分块
    【Luogu P2201】【JZOJ 3922】数列编辑器
    【SSL1786】麻将游戏
    【SSL2325】最小转弯问题
    【JZOJ 3910】Idiot 的间谍网络
    【Luogu P1879】[USACO06NOV]玉米田Corn Fields
    【JZOJ 3909】Idiot 的乘幂
    【JZOJ 3918】蛋糕
    【Luogu P3174 】[HAOI2009]毛毛虫
    【SSL1194】最优乘车
  • 原文地址:https://www.cnblogs.com/liang2580/p/8392687.html
Copyright © 2020-2023  润新知