作业需求

指定最大透支额度

可取款

定期还款(每月指定日期还款,如15号)

可存款

定期出账单

支持多用户登陆,用户间转帐

支持多用户

管理员可添加账户、指定用户额度、冻结用户等

目录结构如下:

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

importsys,os,logging

BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.append(BASE_DIR)

BILL_DAY=25DATABASE={'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

deffile_db_handle(conn_params):'''存放数据的文件路径

:param conn_params:

:return:'''db_path='%s/%s' %(conn_params['path'],conn_params['name'])returndb_pathdefdb_handler(conn_parms):'''数据库类型

:param conn_parms:

:return:'''

if conn_parms['engine']=='file_storage':returnfile_db_handle(conn_parms)elif conn_parms['engine']=='mysql':pass

View Code

auth.py

#!/usr/bin/env python#-*- coding:utf-8 -*-#Author: liang

importos,sys

BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.append(BASE_DIR)importosfrom core importdb_handlerfrom core importaccountsfrom conf importsettingsimportjsonimportdatetimedefacc_auth(account,password):'''用户验证函数

:param account:

:param password:

:return:'''db_path=db_handler.db_handler(settings.DATABASE)

account_file="%s/%s.json" %(db_path,account)ifos.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:returnaccount_dataelse:print("账户已经过期了。或者不是管理员!!")else:print("密码错误")else:print("文件不存在")defacc_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

account=input("请输入用户名:").strip()

password=input("请输入密码").strip()if account==last_account:

same_account+=1auth=acc_auth(account,password)

last_account=accountifauth:

user_data['is_authenticated']=True

user_data['account_id']=accountreturnauth

retry_connt+=1

else:if same_account==exit_count -1:

log_obj.error("account [%s] too many login attempts" %account)

exit()defacc_check(account):'''查询账户是否存在

:param account:

:return:'''db_path=db_handler.db_handler(settings.DATABASE)

account_file="%s/%s.json" %(db_path,account)ifos.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:returnaccount_dataelse:returnFalsedefsign_up():'''用户注册和admin 管理员用户

:return:'''pay_dat=22exit_flag=Truewhile exit_flag isTrue:

account=input("请输入你的用户名:").strip()

password=input("请输入你的密码:").strip()

exit_flag=acc_check(account)ifexit_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)returnTruedefmodify():'''修改用户信息

:return:'''items=["password","credit","status","expire_day","pay_day"]

acc_data=False

contine_flag=Falsewhile acc_data isFalse:

account=input("请输入你要修改的用户名:").strip()#丢到验证函数中

account_data=acc_check(account)if account_data isFalse:print("你输入的用户不存在")else:while contine_flag is notTrue:#判断输入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)exceptException as e:print("输入错误!!!")continueerror_flag=False #初始化错误标记

for index inmodify_items:if index initems:#修改用户数据 就是字典修改方式

account_data[index]=modify_items[index]else:print("输入有错误!!!")continue

iferror_flag:continue

#再写到文件中

accounts.dump_account(account_data)print("修改成功!!!")

contine_flag=True

acc_data=Truereturn True

View Code

accounts.py

#!/usr/bin/env python#-*- coding:utf-8 -*-#Author: liang

importjsonimporttimefrom core importdb_handlerfrom conf importsettingsdefload_current_balance(account_id):'''json load 用户文件

:param account_id:

:return:'''db_path=db_handler.db_handler(settings.DATABASE)#db_path 调用的是配置文件的DATABASE路径

#db_path 完整的路径是 ATM\db\accounts

account_file="%s/%s.json" %(db_path,account_id)

with open(account_file,'r') as f:

acc_data=json.load(f)returnacc_datadefdump_account(account_data):'''写到文件当中

:param account_data:

:return:'''db_path=db_handler.db_handler(settings.DATABASE)#这个数据的目录 ATM\db\accounts

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 importsettingsimportdatetimedefget_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.monthif month ==12:

month=1year+=1

else:

month+=1bill_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 importsettingsfrom core importaccountsfrom core importlogger#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 insettings.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 [\033[31;1m%s\033[0m] is not enough for this transaction [-%s],

your current balance is [\033[32;1m%s\033[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))#返回最新的用户数据

returnaccount_data#不存在的交易类型

else:print("\033[31;1mTransaction type [%s] is not exist!\033[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

importloggingimportdatetimefrom conf importsettingsfrom core importbill_datedeflogger(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)returnlogger#'application' code

'''logger.debug('debug message')

logger.info('info message')

logger.warn('warn message')

logger.error('error message')

logger.critical('critical message')'''

defshow_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 infile:#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

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

#

#

#

#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

importos,sys

BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.append(BASE_DIR)from core importauthfrom core importloggerfrom core importaccountsfrom core importtransactionfrom core importdb_handlerfrom conf importsettingsimportdatetimeimporttimeimportos#建立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

}defdisp_account_info(account_data):'''格式化输出账户信息(管理员可直接使用)

#去除 password 字段显示

:param account_data: 账户信息

:return:'''ignore_display=["password"]for k inaccount_data:if k inignore_display:continue

else:print("{:<20}:\033[32;1m{:<20}\033[0m".format(k, account_data[k]))defadmin_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)returnTrueelse:print("你能查询其它管理员【%s】的信息"%(admin_input_id))elif new_user_info !=8:

disp_account_info(new_user_info)else:

exit("非法操作")defaccount_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)returnTrueelse:

exit("谢谢!!!!!")defget_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#返回最新用户数据

returnuser_dataelse:returnNonedefpay(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)ifnew_balance:returnTrue#小于0

else:print("你输入的金额需要大于0%s"%amount)returnNonedefrepay(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=Falsewhile notback_flag:print("按b退出")#还款金额

reap_amount=input("请输入你还款的金额:>>").strip()if len(reap_amount) >0 andreap_amount.isdigit():#new_balance = 用户最新数据

new_balance=transaction.make_transaction(trans_logger,account_data,'repay',reap_amount)

time.sleep(0.1)ifnew_balance:print("你的余额为%s"%(new_balance['balance']))elif reap_amount =='b':

back_flag=Trueelse:print("输入错误。请从新输入!!!!%s"%(reap_amount))defwithdraw2(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=Falsewhile notback_flag:print("输入b 跳出")

withdrwa_amount=input("请输入提款金额:>>>").strip()if len(withdrwa_amount)>0 andwithdrwa_amount.isdigit():

new_balance2=transaction.make_transaction(transaction,account_data,'withdraw',withdrwa_amount)

time.sleep(0.1)ifnew_balance2:print("你剩余的余额%s" %new_balance2['balance'])elif withdrwa_amount=='b':

back_flag=Trueelse:print("你输入错误!!!%s"%withdrwa_amount)defwithdraw(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=Falsewhile notback_flag:print("Tip: [b] to back")#输入还款金额

withdraw_amount = input("\033[33;1mInput withdraw amount:\033[0m").strip()#长度大于0 并且是数字

if len(withdraw_amount) > 0 andwithdraw_amount.isdigit():#返回用户最新的数据

new_balance = transaction.make_transaction(trans_logger, account_data, 'withdraw', withdraw_amount)

time.sleep(0.1) #处理显示问题

#如果有数据, 就显示现有的账目

ifnew_balance:print('''\033[42;1mNew Balance:%s\033[0m''' % (new_balance['balance']))elif withdraw_amount == 'b':

back_flag=Trueelif withdraw_amount == 'q' and withdraw_amount == 'exit':

exit("谢谢下次再来")break

else:print('[\033[31;1m%s\033[0m] is not a valid amount, only accept integer!' %withdraw_amount)deftransfer(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=Falsewhile notback_flag:#输入转给谁 .不能转给自己

recevier=input("输入你需要转钱的用户:>>>>").strip()if str(recevier)==str(account_data["id"]):print("不能转给自己")continue

elif recevier=='b':

back_flag=Trueelse:#检查是否有这个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 andtransfer_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)ifnew_blance:

time.sleep(0.2)print("转钱成功!!!")else:print("请输入大于0的金额!!!!")if transfer_amount=='b':

back_flag=Trueelse:print("不能转为其他人")defpay_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 notos.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 inf: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)defsave(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=Falsewhile notback_flag:#输入存款金额

save_amount=input("输入你需要存款的金额:>>>").strip()if save_amount == 'b':

back_flag=Trueelif len(save_amount) > 0 andsave_amount.isdigit():

new_balance= transaction.make_transaction(trans_logger, account_data, 'save', save_amount)

time.sleep(0.1) #解决日志显示问题

ifnew_balance:print('''\033[42;1mNew Balance:%s\033[0m''' % (new_balance['balance']))

back_flag=Trueelse:print('[\033[31;1m%s\033[0m] is not a valid amount, only accept integer!' %save_amount)deflogout(acc_data):'''清除认证信息、退出

:param acc_data:

:return:'''exit("谢谢!!!!".center(50,'#'))definteractive(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=Falsewhile notexit_flag:print(menu)

user_option=input(":>>>").strip()if user_option inmenu_dic:#print(acc_data)

menu_dic[user_option](acc_data)else:print("输入错误!!!")defget_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("\033[31;1mToday is not the bill generation day!\033[0m")if balance>=credit:

repay_amount=0

bill_info="Account [\033[32;1m%s\033[0m] needn't to repay." %account_idelse:

repay_amount=credit-balance

bill_info="Account [\033[32;1m%s\033[0m] need to repay [\033[33;1m%s\033[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\n" %(year_month, account_id, repay_amount))defget_all_bill():

db_path=db_handler.db_handler(settings.DATABASE)for root, dirs , files inos.walk(db_path):for file infiles:#分割出来结尾的文件

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,'-'))returnTruedefchenk_admin(func):'''检查是否是管理员

:param func:

:return:'''

def inner(*args,**kwargs):if user_data['account_data'].get('status',None)==8:

ret=func(*args,**kwargs)returnretelse:print("不是管理员")returninnerdefmanage_func(acc_data):'''管理员功能

:param acc_data:

:return:'''menu= u'''------- Admin erea ---------\033[32;1m

1. 添加账户

2. 查询用户信息

3. 用户信息修改(冻结帐户、用户信用卡额度等)

4. 生成全部用户帐单

5. 退出

\033[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=Truewhilego_flag:print(menu)

user_option=input(":>>").strip()if user_option inmenu_dic.keys():

go_flag=eval(menu_dic[user_option])else:print("\033[31;1mOption does not exist!\033[0m")defrun():'''这个是普通用户运行的界面

:return:'''

print("Welocome to ATM".center(50,'#'))

user_data=get_user_data()

interactive(user_data)defadmin_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

importosimportsys

base_dir= os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.append(base_dir)from core importmainif __name__ == '__main__':

main.admin_run()#管理员账户 admin 密码 abc

View Code

atm_user.py

#!/usr/bin/env python#-*- coding:utf-8 -*-#Author: liang

importosimportsys

base_dir= os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.append(base_dir)from core importmainif __name__ == '__main__':

main.run()#普通用户 liang 密码 123456

View Code

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

测试如下:

C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python36.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

转钱成功!!!

输入你需要转钱的用户:>>>>

python atm作业详解_python day4 作业 ATM相关推荐

  1. python atm作业详解_Python小案例--ATM系统

    今天偶尔在知乎上看到某大佬用Python写的ATM系统案例,然后观摩了下他的实现思路和源码,感觉受益颇多.于是就根据自己的思路和目前掌握的Python编程基础将ATM实现了一下,以下是案例解析的过程: ...

  2. python协程详解_python协程详解

    原博文 2019-10-25 10:07 − # python协程详解 ![python协程详解](https://pic2.zhimg.com/50/v2-9f3e2152b616e89fbad86 ...

  3. python atm作业详解_Python学习day5作业-ATM和购物商城

    Python学习day5作业 Python学习day5作业 ATM和购物商城 作业需求 ATM:指定最大透支额度 可取款 定期还款(每月指定日期还款,如15号) 可存款 定期出账单 支持多用户登陆,用 ...

  4. python int函数详解_Python内置函数OCT详解

    英文文档:oct ( x ) Convert an integer number to an octal string. The result is a valid Python expression ...

  5. python average函数详解_python 函数详解

    函数函数是代码的一种组织形式 函数应该能完成一项特定的工作,而且一般一个函数只完成一项工作 有些语言,分函数和过程两个概念,通俗解释是,有返回结果的是函数,无返回结果的叫过程,python不加以区分 ...

  6. python时间函数详解_Python:Numpy库基础分析——详解datetime类型的处理

    原标题:Python:Numpy库基础分析--详解datetime类型的处理 Python:Numpy库基础分析--详解datetime类型的处理 关于时间的处理,Python中自带的处理时间的模块就 ...

  7. python中configparser详解_Python中的ConfigParser模块使用详解

    1.基本的读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该sect ...

  8. python 元类 详解_Python 元类详解 __new__、__init__、__call__、__metacalss__

    了解元类之前,先了解几个魔术方法: __new__.__init__.__call__ __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪 ...

  9. python requests库详解_python爬虫之路(一)-----requests库详解

    requests库 requests库是python实现的最简单易用的http库. requests库的功能详解. 我们可以自然而然地想到这些方法其实就是http协议对资源的操作. 调用request ...

最新文章

  1. 基于圆形标定点的相机几何参数的标定
  2. 独家!扒出腾讯新高管余总的真面目!
  3. hdu3786 Floyd或搜索 水题
  4. 遇到问题描述:Android Please ensure that adb is correctly located at问题解决
  5. php fastcgi_param,nginx-404与root指令 fastcgi_param 指令
  6. 【中级软考】前驱图是什么?(貌似又名“前趋图”)
  7. web 服务器 内存 影响_C/C++服务器开发常用的7大开源库,让你在同行中脱颖而出...
  8. 探测器反向偏压_近红外和可见光双模有机光电探测器
  9. python 制作动画片_cocos2d from python Animation 动画片的实现
  10. VS2017下载地址和安装教程(图解)
  11. 浅谈-国标GB28181协议上下级对接国标编码要求(四)
  12. JavaScript网页打印国际象棋棋盘
  13. C中 stdarg.h
  14. 双精度,单精度和半精度
  15. [BZOJ2827]千山鸟飞绝
  16. 计算机专业高数学科难度,大学里极其有难度的4个专业,挂科率很高,不是学霸学不明白...
  17. 基于Java的建筑工程综合管理信息系统
  18. Activiti源码解读之TaskService
  19. Java 工程师,掌握这些,你离大神只差一步
  20. 机器学习实战课后习题(一)

热门文章

  1. Mysql用navicat操作导出查询结果
  2. CRMEB系统开发文档
  3. php中如何让这段东西不显示出来,数据显示处理,该怎么处理
  4. 2008matlab error 95,VS2008和MATLAB2010b混合编程有关问题 error LINK2028 恳请指教!(2)
  5. document write的用法
  6. python微信聊天机器人_python实战项目,使用itchat模块制作微信聊天机器人
  7. centos 7 局域网丢包排查_ethtool原理介绍和解决网卡丢包排查思路
  8. php+linux+线程安全,PHP 线程安全与非线程安全版本的区别深入解析
  9. opencv mat 修改_C++ opencv矩阵和pytorch tensor的互相转换
  10. 安装windows时loading files结束就重启_Boot Camp安装windows 10