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
转钱成功!!!
输入你需要转钱的用户:>>>>











原文地址:https://www.cnblogs.com/liang2580/p/8392687.html