zoukankan      html  css  js  c++  java
  • 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
    转钱成功!!!
    输入你需要转钱的用户:>>>>











  • 相关阅读:
    1104 Sum of Number Segments (20 分)(数学问题)
    1092 To Buy or Not to Buy (20 分)(hash散列)
    1082 Read Number in Chinese (25 分)(字符串处理)【背】
    1105 Spiral Matrix (25 分)(模拟)
    初识网络安全及搭建网站(内网)
    HTML5开发者需要了解的技巧和工具汇总(转)
    native+web开发模式之web前端经验分享
    移动平台3G手机网站前端开发布局技巧汇总(转)
    Asp.net 中图片存储数据库以及页面读取显示通用方法详解附源码下载
    使用H3Viewer来查看VS2010的帮助文档
  • 原文地址:https://www.cnblogs.com/liang2580/p/8392687.html
Copyright © 2011-2022 走看看