信用卡atm python_Python学习--------------Atm+购物车系统

一、程序需求

模拟实现一个ATM + 购物商城程序:

1.额度 15000或自定义

2.实现购物商城,买东西加入 购物车,调用信用卡接口结账

3.可以提现,手续费5%

4.每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息(没写)

5.支持多账户登录

6.支持账户间转账

7.记录每月日常消费流水

8.提供还款接口

9.ATM记录操作日志

10.提供管理接口,包括添加账户、用户额度,冻结账户等。。。

11.用户认证用装饰器

脑图:

二、目录

1 ├── ATM #ATM主程目录2 │ ├── __init__.py3 │ ├── bin #ATM 执行文件 目录4 │ │ ├── __init__.py5 │ │ ├── atm.py #ATM 执行程序6 │ │ ├── manage.py #信用卡管理7 │ ├── conf #配置文件8 │ │ ├── __init__.py9 │ │ └── Settings.py #配置参数10 │ ├── core #主要程序逻辑都 在这个目录 里11 │ │ ├── __init__.py12 │ │ ├── accounts.py #用于从文件里加载和存储账户数据13 │ │ ├── auth.py #用户认证模块及主要功能函数14 │ │ ├── db_handler.py #数据库连接引擎15 │ │ ├── logger.py #日志记录模块16 │ │ ├── main.py #主逻辑交互程序17 │ │ ├── transaction.py #记账\还钱\取钱\与账户金额相关的操作,冻结或者锁定用户18 │ ├── db #用户数据存储的地方19 │ │ ├── __init__.py20 │ │ ├── account_sample.py #生成一个初始的账户数据 ,把这个数据 存成一个 以这个账户id为文件名的文件,放在accounts目录 就行了,程序自己去会这里找21 │ │ └── accounts #存各个用户的账户数据 ,一个用户一个文件22 │ │ └── 123.json #新创建的用户账户示例文件23 │ │ └── 1234.json #一个用户账户示例文件24 │ │ └── 123456.json #一个用户账户示例文件25 │ │ └── 6230001.json #管理用户账户示例文件26 │ └── log #日志目录27 │ ├── access.log #用户访问和操作的相关日志28 │ └── login_in.log #登陆日志29 └── shopping_mall #电子商城程序,需单独实现,主要实现购物的功能。30 │ └── __init__.py31 │ └── product.txt #存放商品的txt文件32 │ └── shopping_list.txt #存放购物清单的txt.文件33 │ └── shopping_mall.py #购物商城程序34 ├── README

目录

三、简要说明

1.程序从/bin/atm.py开始执行if __name__ == '__main__':

main.run()

2.程序转到/core/main.py下的run()函数,登陆时调用/core/auth的acc_login()进行登陆验证:用到了/core/auth下的acc_auth2()方法进行验证(此时传入的参数时用户输入的账户和密码)

acc_auth2中有调用了/core/db_handler下的db_handler()方法(参数是输入的账户名)在db_handler中只是进行判断是什么引擎,return file_db_handle(数据库引擎)解析文件,返回文件执行加载输入的用户的账户的所有数据

接下来判断是否为管理者账户,或者是否被冻结,若都不是,则判断输入的密码是否与数据库中的密码一样,在判断到期时间是否过期

所有都通过的话就返回这个账户的数据,之前已经创建了一个空字典,里面有是否验证:用户数据:用户账户:,判断是否被验证过,然后把用户数据临时的传递到里面,执行主循环函数

可以选择进入到购物商城,或者信用卡操作或者退出

1)购物商城

调用/shopping_mall/shopping_mall.py文件执行,主循环函数,选择你是商家还是用户,

①如果选择商家,商家有增加商品修改商品的功能

②如果选择用户,用户则有购物,刷信用卡消费的功能,当退出时打印消费清单

2)信用卡操作

调用/core/main.py下interactive(用户的所有数据)调用主循环函数,可以打印账户信息、还款、取款、转账、账单、退出等操作

①账户信息

②还款

③取款

④转账

⑤账单

⑥退出

3)若在账户登陆的时候进行输入的时管理员账户调用/bin/manage.py则可以对用户进行管理,解冻    用户、冻结用户、申领新卡

①添加账户

②冻结账户

③解冻账户

④退出

四、主程序

1.bin目录下代码

1 '''/bin/atm.py'''

2

3

4 #!/usr/bin/env python

5 #-*- Coding:utf-8 -*-

6 #Author:Eric.Shen

7 importos,sys8 base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))9 #print(base_dir)

10 sys.path.append(base_dir)11 from core importmain12

13

14 if __name__ == '__main__':15 main.run()16

17

18

19

20

21

22

23 '''/bin/manage.py'''

24

25

26

27 #!/usr/bin/env python

28 #-*- Coding:utf-8 -*-

29 #Author:Eric.Shen

30 #管理端(提供管理接口,包括添加账户、用户额度,冻结账户)

31 #解冻账户

32 #from core.auth import login_required

33 from core importaccounts34 from core importtransaction35 #解冻账户

36 defunblock_account(acc_data):37 user_input = input("请输入你要解冻的用户:")38 flag =039 #锁定用户

40 val =transaction.lock_or_not(user_input,flag)41 if val ==0:42 print("解冻成功!")43 return

44 #冻结账户

45 defblock_account(acc_data):46 '''

47 冻结账户初步构想是,在linux里把他的权限改掉;48 或者将其文件改名49 :param acc_data:50 :return:51 '''

52 user_input = input("请输入你要冻结的用户:")53 flag = 1

54 #锁定用户

55 val =transaction.lock_or_not(user_input,flag)56 if val ==0:57 print("冻结成功!")58 return

59

60 #添加账户、用户额度

61 defadd_account(acc_data):62 account ={63 "id": None,64 "balance": None,65 "expire_date": None,66 "enroll_date": None,67 "credit": None,68 "pay_day": None,69 "password": None,70 "status": None71 }72 menu ={73 0: "账户(数字):",74 1: "余额:",75 2: "到期时间:",76 3: "办卡时间:",77 4: "信用额度:",78 5: "还款日期:",79 6: "密码:",80 7: "默认:"}81 menu_user ={82 0: "id",83 1: "balance",84 2: "expire_date",85 3: "enroll_date",86 4: "credit",87 5: "pay_day",88 6: "password",89 7: "status"

90 }91 for i in range(8):92 data = input("%s" %menu[i]).strip()93 account['%s' % menu_user[i]] =data94 accounts.dump_account(account)#写入文件

95 print("创建成功!")96 return

97

98

99

100 deflogout(acc_data):101 exit("程序退出!")102 #管理界面主程序

103 defmanage_main(acc_data):104

105 menu = u'''

106 ---------管理界面---------107 1.添加账户108 2.冻结账户109 3.解冻账户110 4.退出'''

111 menu_dic ={112 '1': add_account,113 '2': block_account,114 '3': unblock_account,115 '4': logout116 }117 exit_flag =False118 while notexit_flag:119 print(menu)120 user_option = input("请输入你的选择:")121 if user_option inmenu_dic:122 menu_dic[user_option](acc_data)123 else:124 print("\033[31;1m选择不存在!\033[0m")125

126

127

128

129 .

View Code

2.conf目录下代码

1 '''/conf/Settings.py'''

2

3

4 #!/usr/bin/env python

5 #-*- Coding:utf-8 -*-

6 #Author:Eric.Shen

7 #参数配置文件

8 importos,sys,logging9

10 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#/Atm

11

12 DATABASE ={13 'engine': 'file_storage',14 'name': 'accounts',15 'path': "%s/db" % BASE_DIR#../Atm

16 }17

18 LOG_LEVEL =logging.INFO19 LOG_TYPES ={20 'transaction': 'transaction.log',21 'access': 'access.log',22 }23

24 #发生交易的配置类型

25 TRANSACTION_TYPE ={26 'repay':{'action':'plus','interest':0},#还款

27 'withdraw':{'action':'minus','interest':0.05},#取现是降低可用余额

28 'transfer':{'action':'minus','interest':0.05},#转账是降低可用余额

29 'consume':{'action':'minus','interest':0},30 }

View Code

3.core目录下代码

1 '''/core/accounts.py'''

2

3

4 #!/usr/bin/env python

5 #-*- Coding:utf-8 -*-

6 #Author:Eric.Shen

7 #用于从文件里加载和存储账户数据

8 importjson,time9 from core importdb_handler10 from conf importSettings11

12 #返回账户余额和其他基础信息(返回最新的数据)

13 defload_current_balance(account_id):14 '''

15 返回账户余额和其他基础信息16 :param account_id: 用户账户的名字17 :return: 返回最新读到的数据文件中的最新数据18 '''

19 #db_path = db_handler.db_handler(settings.DATABASE)

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

21 #22 db_api =db_handler.db_handler()23 data = db_api("select * from accounts where account=%s" % account_id)#在进行操作的时候在读取一遍数据中的数据(保证数据的最新)

24 return data#返回读取到的数据

25

26 #with open(account_file) as f:

27 #acc_data = json.load(f)

28 #return acc_data

29

30 #写入文件数据

31 defdump_account(account_data):32 '''

33

34 :param account_data:35 :return:36 '''

37 db_api =db_handler.db_handler()38 data = db_api("update accounts where account=%s" % account_data['id'],account_data =account_data)39

40 #db_path = db_handler.db_handler(settings.DATABASE)

41 #account_file = "%s/%s.json" %(db_path,account_data['id'])

42 #with open(account_file, 'w') as f:

43 #acc_data = json.dump(account_data,f)

44 return True

accounts.py

1 '''/core/auth.py'''

2

3

4 #!/usr/bin/env python

5 #-*- Coding:utf-8 -*-

6 #Author:Eric.Shen

7 #用户认证模块

8 importjson,time,os9 from core importdb_handler10 from bin importmanage11 from conf importSettings12 from core importlogger13 #装饰器(用于验证账户是否登陆过)

14 deflogin_required(func):15 '''

16 验证用户是否登陆17 :return:18 '''

19 def wrapper(*args,**kwargs):20 if args[0].get('is_authenticated'):21 return func(*args,**kwargs)22 else:23 exit("用户不能认证")24 returnwrapper25

26 defacc_auth(account,password):27 '''

28 账户验证函数29 :return:30 '''

31 db_path =db_handler.db_handler()32 account_file = "%s/%s.json" %(db_path,account)33 print(account_file)34 ifos.path.isfile(account_file):35 with open(account_file,'r') as f:36 account_data =json.load(f)37 if account_data['password'] ==password:38 exp_time_stamp = time.mktime(time.strptime(account_data['expire_date'], "%Y-%m-%d"))39 if time.time() >exp_time_stamp:40 print("\033[31;1m[%s]账户已经注销,请重新申领账户!\033[0m" %account)41 else: #passed the authentication

42 returnaccount_data43 else:44 print("\033[31;1m账号或密码错误,请重新输入!\033[0m")45 else:46 print("\033[31;1m[%s]账户不存在!\033[0m" %account)47

48 defacc_auth2(account,password):49 '''

50 优化版认证接口51 :param52 account:信用卡账户53 password:信用卡密码54 :return: 返回读取到的数据文件的所有账户数据55 '''

56 db_api =db_handler.db_handler()57 data = db_api("select * from accounts where account=%s" %account)#此处返回值为db_handler.py中的

58 #得到的所有数据(读取到的这个账户的所有数据)赋值给data

59 if data["status"] == 2:#判断是否为管理者

60 manage.manage_main(data)61 if data['status'] == 1:62 print("你的账户已经被冻结,请联系管理员!\n")63 option = input("请按b退出!")64 if option == "b":65 exit("程序已经退出!")66 if data['password'] == password:#判断data中的password数据是否恒等于输入的password(此处如果继续执行,则账户密码完全正确)

67 #time.mktime 返回用秒数来表示时间的浮点数。

68 #实例结果:time.mktime(t) : 1234915418.000000

69 #time.strptime 根据指定的格式把一个时间字符串解析为时间元组

70 #实例结果:time.strptime(string[, format])

71 exp_time_stamp = time.mktime(time.strptime(data['expire_date'],"%Y-%m-%d"))#将数据文件中的expire_data时间

72 #转为以秒计数的时间赋值给exp_time_stamp

73 if time.time() > exp_time_stamp:#判断当前以秒计算的数据是否大于数据文件中的数据

74 print("\033[31;1m[%s]账户以及过期,请重新激活!\033[0m" %account)75 else:76 return data#没有超时,则返回读取到的数据文件的所有内容

77 else:78 print("\033[31;1m帐户名或者密码错误!\033[0m")79

80

81 defacc_login(user_data,log_obj):82 '''

83 账户登陆函数84 :param85 user_data:用户信息数据,只存在内存中86 :return: 账户密码都对的情况下,返回所有账户数据87 '''

88 retry_count = 0#初始化重试次数

89 while user_data['is_authenticated'] is not True and retry_count < 3:#如果没有验证过,或循环此时没超过三次就执行下面的

90 account = input("\033[32;1m账户:\033[0m").strip()#输入账户

91 password = input("\033[32;1m密码:\033[0m").strip()#输入密码

92 auth = acc_auth2(account,password)#解耦,将输入的账户和密码传入到acc_auth2函数中,进行验证

93 #(最后返回的是读取到的输入正确账户的所有数据)赋值给auth

94 ifauth:95 user_data['is_authenticated'] = True#登陆成功,将只存在与内存中的数据中的是否验证改为True

96 user_data['account_id'] = account#将只存在与内存中的数据中的账户id改为账户名字(开始输入的帐户名)

97 return auth#这一步操作就是验证此账户是否登陆,然后返回账户的所有数据(数据文件中的所有数据)

98 retry_count += 1

99 else:100 log_obj.error("[%s]账户太多次尝试" %account)101 exit()

auth.py

1 '''/core/db_handler.py'''

2

3

4

5 #!/usr/bin/env python

6 #-*- Coding:utf-8 -*-

7 #Author:Eric.Shen

8 #数据库连接引擎

9 #处理所有数据库交互

10 importjson,time,os11 from conf importSettings12

13 #解析文件数据路径

14 deffile_db_handle(conn_params):15 '''

16 解析数据库文件路径17 :return:18 '''

19 #print('file db:',conn_params)

20 returnfile_execute21

22 #数据库句柄

23 defdb_handler():24 '''

25 连接数据库26 :return:27 '''

28 conn_params = Settings.DATABASE#把Settings下的DATABASE的数据赋值给conn_params

29 if conn_params['engine'] == 'file_storage':#判断Settings下的DABASE是什么引擎,这里只用文件文件引擎

30 return file_db_handle(conn_params)#则把Settings下的DABASE的数据传给file_db_handle并返回

31 elif conn_params['engine'] == 'mysql':32 pass#支持扩展,此次只作为一个说明

33

34 #文件执行

35 def file_execute(sql,**kwargs):36 '''

37 传入sql语句,及其他变量,38 :param sql: sql语句操作得到结果39 :param kwargs: 其他得变量40 :return:41 '''

42 conn_params = Settings.DATABASE#把Settings下的DATABASE的数据赋值给conn_params,再一次赋值意味着得到最新得数据

43 db_path = '%s/%s' % (conn_params['path'],conn_params['name'])#数据库的文件路径 ../db/accounts

44 #print(sql,db_path)#sql = select * from accounts where account=%s %account(此时这个account等于程序开始时要求哟用户输入得数据)

45 sql_list = sql.split('where')#将上面得sql语句以where分开,(sql_list列表内容:'select * from accounts' ,"account='account' ")

46 #print(sql_list)

47 #startswith() 方法用于检查字符串是否是以指定子字符串开头,

48 #如果是则返回 True,否则返回False。如果参数 beg 和 end 指定值,

49 #则在指定范围内检查。

50 if sql_list[0].startswith('select') and len(sql_list) > 1:#判断sql_list列表中得第一个字符是select并且列表的长度是大于1的

51 column,val = sql_list[1].strip().split('=')#将sql_list列表第二个数据先去掉默认空格,并且以‘=’为界分开放入--》

52 #-->column = account , val = '此处为开始程序输入的账户'

53 #Python strip() 方法用于移除字符串头尾指定的字符(默认为空格)。

54 if column == 'account':#判断是否为account,然后做指定的操作(这里使用的是account)

55 account_file = '%s/%s.json' % (db_path,val)#这一步得到数据文件路径的文件绝对路径

56 #print(account_file)

57 if os.path.isfile(account_file):#使用绝对路径判断是否为文件,返回True

58 with open(account_file,'r') as f:#以只对的方式打开文件并把文件句柄赋值给f(用with方法打开不用自己写关闭文件的方法)

59 account_data = json.load(f)#json加载文件赋值给account_data

60 return account_data#返回account_data数据(将.json文件中的数据都都出来返回)

61 else:62 exit("\033[31;1m[%s]账户不存在!\033[0m" % val)#若判断不是,则返回没有此用户

63 #写入数据

64 elif sql_list[0].startswith('update') and len(sql_list) > 1:65 column, val = sql_list[1].strip().split('=')#将帐户名写入到val中

66 if column == 'account':67 account_file = "%s/%s.json" %(db_path,val)68 #if os.path.isfile(account_file):

69 account_data = kwargs.get("account_data")#得到账户数据

70 with open(account_file,'w') as f:71 acc_data =json.dump(account_data,f)72 #print(acc_data)

73 return True

db_handler.py

1 '''/core/logger.py'''

2

3 #!/usr/bin/env python

4 #-*- Coding:utf-8 -*-

5 #Author:Eric.Shen

6 #日志记录模块,处理所有日志工作

7

8 importlogging9 from conf importSettings10

11 deflogger(log_type):12 #创建日志

13 logger =logging.getLogger(log_type)14 logger.setLevel(Settings.LOG_LEVEL)15

16 #创建控制台处理程序并将级别设置为调试

17 ch =logging.StreamHandler()18 ch.setLevel(Settings.LOG_LEVEL)19 #创建文件处理程序并设置级别为警告

20 log_file = "%s/logs/%s" %(Settings.BASE_DIR,Settings.LOG_TYPES[log_type])21 fh =logging.FileHandler(log_file)22 fh.setLevel(Settings.LOG_LEVEL)23 #创建格式化程序

24 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levename)s- %(message)s')25

26 #添加格式化的CH和FH

27 ch.setFormatter(formatter)28 fh.setFormatter(formatter)29

30 #添加CH和FH到loggerh

31 logger.addHandler(ch)32 logger.addHandler(fh)33

34 returnlogger35

36 #应用程序代码

37 '''logger.debug('debug message')38 '''

logger.py

1 #!/usr/bin/env python

2 #-*- Coding:utf-8 -*-

3 #Author:Eric.Shen

4 #记账\还钱\取钱\与账户金额相关的操作,冻结或者锁定用户

5 from conf importSettings6 from core importaccounts7 from core importlogger8

9 def make_transaction(log_obj,account_data,tran_type,amount,**kwargs):10 '''

11 处理所有用户的所有交易12 :param log_obj:13 :param account_data: 用户最新的数据14 :param tran_type: 交易类型15 :param amount: 交易数量16 :param other: 主要用于日志使用17 :return: 返回最新的账户数据18 '''

19 amount = float(amount)#转换为浮点型

20 if tran_type in Settings.TRANSACTION_TYPE:#判断传入的类型是否在配置参数里面

21 interest = amount * Settings.TRANSACTION_TYPE[tran_type]["interest"]#根据交易类型计算利息赋值给interest

22 old_balance = account_data['balance']#读取数据中账户余额

23 #还款操作

24 if Settings.TRANSACTION_TYPE[tran_type]['action'] == 'plus':#因为是信用卡,所以还款时提升可使用余额的操作,故计为加plus

25 new_balance = old_balance + amount + interest#执行的是信用卡的还款操作,计算方法是,旧余额+还款的钱和利息=最后的账户可用余额

26 #取现\转账操作

27 elif Settings.TRANSACTION_TYPE[tran_type]['action'] == 'minus':#因为是信用卡,所以取现都是降低可用余额的操作

28 new_balance = old_balance - amount -interest29 #只属于转账的

30 if kwargs.get('re_account'):31 #print(kwargs[0],kwargs[1])

32 re_account_data = accounts.load_current_balance(kwargs.get('re_account'))#得到要转入账户的所有数据

33 re_account_balance = re_account_data['balance'] + amount#得到转入账户余额的最新值

34 re_account_data['balance'] = re_account_balance#将最新的余额全部写入账户的余额中

35 print(re_account_data)36 accounts.dump_account(re_account_data)#将最新的账户所有数据写入到文件中

37 if new_balance <0:38 print("\033[31;1m[%s]账户的信用余额不足以支付此次交易[-%s],你当前的余额是[%s]\033[0m"

39 % (account_data['creat'], (amount +interest), old_balance))40 return

41 #转账

42 '''

43 elif Settings.TRANSACTION_TYPE[tran_type] == 'transfer' :44 new_balance = old_balance - amount - interest#自己账户的最新余额45 #读取转入的账户,写入转入金额46 print(kwargs[0],kwargs[1])47 re_account_data = accounts.load_current_balance(kwargs.get('re_account'))#得到要转入账户的所有数据48 re_account_balance = re_account_data['balance'] + amount#得到转入账户余额的最新值49 re_account_data['balance'] = re_account_balance#将最新的余额全部写入账户的余额中50 print(re_account_data)51 accounts.dump_account(re_account_data)#将最新的账户所有数据写入到文件中52 '''

53

54 account_data['balance'] = new_balance#将最新的余额写入到账户数据中

55 print(account_data)56 accounts.dump_account(account_data)#将最新的账户余额写回文件

57 #写入日志

58 #log_obj.info('账户:%s,操作:%s,数量:%s,利息:%s' %(account_data['id'],tran_type,amount,interest))

59 returnaccount_data60 else:61 print("\033[31;1m%s交易类型不存在\033[0m" %tran_type)62 #冻结或者锁定用户

63 deflock_or_not(account,flag):64 data =accounts.load_current_balance(account)65

66 if data["status"] == 1:67 print("该账户已经锁定!")68 if data['status']:69 data["status"] =flag70 accounts.dump_account(data)71 return 0

transaction.py

1 #!/usr/bin/env python

2 #-*- Coding:utf-8 -*-

3 #Author:Eric.Shen

4 #主程序句柄模块,处理所有用户交互内容

5 from core importauth6 from core importaccounts7 from core importlogger8 from core importtransaction9 from core.auth importlogin_required10 from shopping_mall importshopping_mall11 from bin importmanage12 importtime13

14

15 #交易日志

16 trans_logger = logger.logger('transaction')17 #访问日志

18 access_logger = logger.logger('access')19

20 #临时账户数据,仅存在于内存中

21 user_data ={22 'account_id':None,23 'is_authenticated':False,24 'account_data':None25 }26

27 #账户信息

28 defaccount_info(acc_data):29 print(user_data)30 #还款

31 @login_required#装饰器,判断用户是否登陆

32 defrepay(acc_data):33 '''

34 打印当前余额,让用户偿还账单35 :param acc_data:36 :return:37 '''

38 account_data = accounts.load_current_balance(acc_data['account_id'])#将用户账户名字传入到load_current_balance中

39 #返回最新的用户数据赋值给 account_data

40 current_balance = '''

41 ---------银行信息----------42 信用额度: %s43 可用余额: %s44 ''' %(account_data['credit'],account_data['balance'])45 print(current_balance)46 back_flag =False47 while notback_flag:48 repay_amount = input("\033[33;1m输入你要还款的金额:\033[0m").strip()#还款金额

49 if len(repay_amount) > 0 andrepay_amount.isdigit():50 #print('ddd 00')

51 #将数据传入make_transaction中(交易日志,用户数据,交易类型,还款金额)进行操作,最后返回的是最新操作之后的账户数据

52 new_balance = transaction.make_transaction(trans_logger,account_data,'repay',repay_amount)53 ifnew_balance:54 print('''\033[42;1m最新的余额:%s\033[0m''' %(new_balance['balance']))55 else:56 print('\033[31;1m[%s]是无效的账户!\033[0m' %repay_amount)57 if repay_amount == 'b':58 back_flag =True59 #取款

60 @login_required61 defwithdraw(acc_data):62 '''

63 打印当前余额,让用户执行取款操作64 :param acc_data:65 :return:66 '''

67 account_data = accounts.load_current_balance(acc_data['account_id'])68 #将用户账户名字传入到load_current_balance中

69 #返回最新的用户数据赋值给 account_data

70 current_balance = '''--------- 银行信息 --------71 信用额度: %s72 账户余额: %s''' % (account_data['credit'], account_data['balance'])73 print(current_balance)74 back_flag =False75 while notback_flag:76 withdraw_amount = input("\033[33;1m输入取款金额:\033[0m").strip()77 if withdraw_amount == 'b':78 return

79 if len(withdraw_amount) > 0 andwithdraw_amount.isdigit():80 new_balance = transaction.make_transaction(trans_logger,account_data,'withdraw', withdraw_amount)81 ifnew_balance:82 print('''\033[42;1m最新余额:%s\033[0m''' %(new_balance['balance']))83 else:84 print('\033[31;1m[%s]是无效的账户!\033[0m' %withdraw_amount)85

86

87 #转账

88 @login_required89 deftransfer(acc_data):90 '''

91 打印当前余额,转账操作函数92 :param acc_data:用户数据93 :return:94 '''

95 account_data = accounts.load_current_balance(acc_data['account_id'])96 #将用户账户名字传入到load_current_balance中

97 #返回最新的用户数据赋值给 account_data

98 current_balance = '''--------- 银行信息 --------99 信用额度: %s100 账户余额: %s''' % (account_data['credit'], account_data['balance'])101 print(current_balance)102 back_flag =False103 while notback_flag:104 reciprocal_account = input("\033[31;1m请输入对方帐户名:\033[0m").strip()#输入对方账户信息

105 transfer_amount = input("\033[31;1m转账金额:\033[0m").strip()#转账金额

106 if reciprocal_account or transfer_amount == 'b':107 return

108 if len(transfer_amount) > 0 andtransfer_amount.isdigit():109 new_balance = transaction.make_transaction(trans_logger,account_data,'transfer',110 transfer_amount,re_account =reciprocal_account)111 ifnew_balance:112 print("\033[41;1m转账成功!\033[0m")113 print("\033[42;1m您当前的余额为:%s\033[0m" %(new_balance["balance"]))114 else:115 print('\033[31;1m[%s] \033[0m')116

117

118 #账单

119 @login_required120 defpay_check(acc_data):121 pass

122 #退出

123 deflogout(acc_data):124 exit("程序已经退出!")125 #购物商城

126 defshopping_mall_this(acc_data):127 shopping_mall.main_menu(acc_data)128 #管理窗口

129 defgoto_manage():130 manage.manage_main(user_data)131 #菜单

132 definteractive(acc_data):133 '''

134 与用户交互135 :param acc_data: 验证过的用户的所用数据136 :return:137 '''

138 menu = u'''

139 -----------银行----------140 \033[32;1m141 1.账户信息142 2.还款143 3.取款144 4.转账145 5.账单146 6.退出147 \033[0m148 '''

149 menu_dic ={150 '1': account_info,151 '2': repay,152 '3': withdraw,153 '4': transfer,154 '5': pay_check,155 '6': logout,156 }157 exit_flag =False158 while notexit_flag:159 print(menu)#打印出菜单,供用户选择

160 user_option = input("请输入你的选择:").strip()#输入用户的选择,过滤掉空格

161 if user_option == 'b':162 return

163 if user_option in menu_dic:#用户的选择如果在这个菜单里

164 #print('accdata',acc_data)

165 menu_dic[user_option](acc_data)#用户选择执行的功能,把acc_data验证过的用户的所有数据(数据文件中的数据)

166 else:167 print("\033[31;1m选择不存在!\033[0m")168 #带有购物商场的主菜单

169 defmain_menu(acc_data):170 main_menu = u'''

171 ----------主菜单---------172 \033[32;1m173 1.购物商城174 2.银行卡操作175 3.退出176 \033[0m177 '''

178 main_menu_dic ={179 '1':shopping_mall_this,180 '2':interactive,181 '3':logout,182 }183 exit_flag =False184 while notexit_flag:185 print(main_menu)186 user_option = input("请输入你的选择:").strip()187 if user_option == 'b':188 return

189 if user_option inmain_menu_dic:190 main_menu_dic[user_option](acc_data)191 else:192 print("\033[31;1m选择不存在!\033[0m")193 defrun():194 '''

195 当程序启动时,这个程序开始运行,处理关于用户的所有交互的内容196 '''

197 acc_data = auth.acc_login(user_data,access_logger)#程序从这里开始,执行auth下的acc_login函数

198 #(返回的是验证过的正确的账户数据)赋值给acc_data(此时这里的数据为输入账户名字的数据文件的数据)

199 if user_data['is_authenticated']:200 user_data['account_data'] = acc_data#把账户所有信息传给账户开始时的临时的账户数据空字典,

201 #把所有的数据文件传给账户的账户数据里面,

202 #interactive(user_data)#把user_data里的所有数据传入菜单函数,进行下一步操作

203 main_menu(user_data)

main.py

4.db下目录下代码

/db/accounts/123.json

1 {"pay_day": "22", "enroll_date": "2018-02-19", "credit": "15000", "balance": "123", "id": "123", "expire_date": "2032-01-01", "password": "123", "status": 0}

123.json

5.logs目录下代码

/logs/access.log&transaction.log

6.shopping_mall下代码

/shopping_mall/product.txt&shopping_list.txt

1 #!/usr/bin/env python

2 #-*- Coding:utf-8 -*-

3 #Author:Eric.Shen

4 #!/usr/bin/env python

5 #-*- Coding:utf-8 -*-

6 #Author:Eric.Shen

7 #2018.02.06

8 #path python3.5

9 #优化版的购物车

10 #用户入口:

11 #1.商品的信息存到文件里

12 #2.已购商品,余额记录

13 #商家入口:

14 #1.可以添加商品 2.修改商品价格

15 #存储商品列表

16 importfileinput17 from core importaccounts18

19 product_list =[]20 f = open("D:\\Python_train\\day4\\Atm\\shopping_mall\\product.txt", "r") #打开文件

21 for line inf.readlines():22 line = line.strip() #去掉最后一个换行符

23 index, item = line.split(":") #以冒号分割得到前后两个数据

24 product_list.append((index, item)) #添加的数据

25 f.close()26

27

28 defprint_product_list():29 for index, item inenumerate(product_list):30 print(index, item)31

32

33 #用户入口

34 #用户购物

35 defuser_shopping(account_data):36 #salary = input("请输入你的薪水:")

37 salary = account_data['account_data']['balance']38 print_product_list()39 if salary >0:40 shopping_list = [] #存放用户购物车清单

41 whileTrue:42 option = input("喜欢那个就买哪个(对应的标号):")43 ifoption.isdigit():44 option =int(option)45 if option >= 0 and option <=len(product_list):46 p_item = product_list[option] #用户选择的商品

47 #print(product_list)

48 #print(p_item[1])

49 c_num = int(p_item[1])50 if salary >=c_num:51 shopping_list.append(p_item)52 salary -=c_num53 print("添加购物车成功,你的余额还有%s" %(salary))54 else:55 print("你的余额不足,只剩%s元" %(salary))56 else:57 print("输入错误,请重新输入!")58 elif option == "q":59 print("----------------购物清单---------------")60 for s_list inshopping_list:61 print(s_list)62 print("你的余额为%s" %(salary))63 account_data['account_data']['balance'] =salary64 #print(account_data)

65 accounts.dump_account(account_data['account_data'])#写入文件

66 print("..........exit.........")67 exit()68 else:69 print("无效的输入")70 else:71 exit("余额不足!")72

73

74 #商家入口

75 #商家添加商品

76 defadd_product():77 name_of_product = input("请输入你要添加的商品名字:")78 price_of_product = input("请输入你要添加商品的价格:")79 f = open("product.txt", "a")80 f.write(str("\n" + name_of_product) + ": %s" %(price_of_product))81 f.close()82 print("添加成功!\nexit----------")83

84

85 #修改商品价格

86 defchange_price():87 print_product_list() #打印商品列表

88 choice = input("请输入你的选择:")89 #name_of_change = input("请输入你要改变的商品名字")

90 price_of_change = input("请输入你要改变商品的价格:")91 ifchoice.isdigit():92 choice =int(choice)93 if choice >= 0 and choice <=len(product_list):94 p_item = product_list[choice] #选择的商品

95 #c_num = int(p_item[1])#转换成int类型

96 for line in fileinput.input("product.txt", inplace="%s" % (choice)): #对输入的选择行进行修改

97 line = line.replace("%s" % (p_item[1]), "%s" %(price_of_change)).strip()98 print(line)99 exit("修改成功!")100 else:101 print("输入无效")102 else:103 if choice == "q":104 exit("退出")105

106

107 defmain_menu(account_data):108 print("--------------------------"

109 "--------------------------"

110 "\n"

111 "欢迎进入购物菜单"

112 "\n"

113 "\n"

114 "商家请按b,用户请按c\n"

115 "--------------------------"

116 "--------------------------")117 c_num = input("请输入你的选择:") #使用者选择

118 if c_num == "b":119 print("--------------------------"

120 "--------------------------"

121 "\n"

122 "欢迎进入商家界面"

123 "\n"

124 "\n"

125 "添加商品请按a,修改价格请按c\n"

126 "--------------------------"

127 "--------------------------")128 c_num2 = input("请输入你的选择:")129 if c_num2 == "a":130 #实现添加商品功能

131 add_product()132 if c_num2 == "c":133 #实现商品价格修改功能

134 change_price()135 else:136 print("输入有误!")137 if c_num == "c":138 print("--------------------------"

139 "--------------------------"

140 "\n"

141 "欢迎进入用户界面"

142 "\n"

143 "\n"

144

145 "--------------------------"

146 "--------------------------")147 #购物功能

148 print(account_data)149 user_shopping(account_data)150 else:151 print("输入有误程序退出!")

shopping_mall

五、README

1 作者:Eric.shen2 此次系统的设计仅用来学习python,开始于2018.2.13-19完(此系统,日志部分没有完善留着日后补充现在还没学到)3 作业需求:4

5 模拟实现一个ATM +购物商城程序:6 1.额度 15000或自定义7 2.实现购物商城,买东西加入 购物车,调用信用卡接口结账8 3.可以提现,手续费5%

9 4.每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息(没写)10 5.支持多账户登录11 6.支持账户间转账12 7.记录每月日常消费流水13 8.提供还款接口14 9.ATM记录操作日志15 10.提供管理接口,包括添加账户、用户额度,冻结账户等。。。16 11.用户认证用装饰器17

18 一、软件定位,软件的基本功能。19 实现一个简单的atm与购物车程序,20 二、运行代码的方法: 安装环境、启动命令等。21 用Python3.5写的,语法就是至此之前所学的,直接打开运行即可22 三、目录结构。23

24 ├── ATM #ATM主程目录

25 │ ├── __init__.py26 │ ├── bin #ATM 执行文件 目录

27 │ │ ├── __init__.py28 │ │ ├── atm.py #ATM 执行程序

29 │ │ ├── manage.py #信用卡管理

30 │ ├── conf #配置文件

31 │ │ ├── __init__.py32 │ │ └── Settings.py #配置参数

33 │ ├── core #主要程序逻辑都 在这个目录 里

34 │ │ ├── __init__.py35 │ │ ├── accounts.py #用于从文件里加载和存储账户数据

36 │ │ ├── auth.py #用户认证模块及主要功能函数

37 │ │ ├── db_handler.py #数据库连接引擎

38 │ │ ├── logger.py #日志记录模块

39 │ │ ├── main.py #主逻辑交互程序

40 │ │ ├── transaction.py #记账\还钱\取钱\与账户金额相关的操作,冻结或者锁定用户

41 │ ├── db #用户数据存储的地方

42 │ │ ├── __init__.py43 │ │ ├── account_sample.py #生成一个初始的账户数据 ,把这个数据 存成一个 以这个账户id为文件名的文件,放在accounts目录 就行了,程序自己去会这里找

44 │ │ └── accounts #存各个用户的账户数据 ,一个用户一个文件

45 │ │ └── 123.json #新创建的用户账户示例文件

46 │ │ └── 1234.json #一个用户账户示例文件

47 │ │ └── 123456.json #一个用户账户示例文件

48 │ │ └── 6230001.json #管理用户账户示例文件

49 │ └── log #日志目录

50 │ ├── access.log #用户访问和操作的相关日志

51 │ └── login_in.log #登陆日志

52 └── shopping_mall #电子商城程序,需单独实现,主要实现购物的功能。

53 │ └── __init__.py54 │ └── product.txt #存放商品的txt文件

55 │ └── shopping_list.txt #存放购物清单的txt.文件

56 │ └── shopping_mall.py #购物商城程序

57 ├── README58 四、简要说明,更详细点可以说明软件的基本原理。59 1.程序从/bin/atm.py开始执行if __name__ == '__main__':60 main.run()61 2.程序转到/core/main.py下的run()函数,登陆时调用/core/auth的acc_login()进行登陆验证:用到了/core/auth下的acc_auth2()方法进行验证(此时传入的参数时用户输入的账户和密码)62 acc_auth2中有调用了/core/db_handler下的db_handler()方法(参数是输入的账户名)在db_handler中只是进行判断是什么引擎,returnfile_db_handle(数据库引擎)解析文件,返回文件执行加载输入的用户的账户的所有数据63 接下来判断是否为管理者账户,或者是否被冻结,若都不是,则判断输入的密码是否与数据库中的密码一样,在判断到期时间是否过期64 所有都通过的话就返回这个账户的数据,之前已经创建了一个空字典,里面有是否验证:用户数据:用户账户:,判断是否被验证过,然后把用户数据临时的传递到里面,执行主循环函数65 可以选择进入到购物商城,或者信用卡操作或者退出66 1)购物商城67 调用/shopping_mall/shopping_mall.py文件执行,主循环函数,选择你是商家还是用户,68 ①如果选择商家,商家有增加商品修改商品的功能69 ②如果选择用户,用户则有购物,刷信用卡消费的功能,当退出时打印消费清单70 2)信用卡操作71 调用/core/main.py下interactive(用户的所有数据)调用主循环函数,可以打印账户信息、还款、取款、转账、账单、退出等操作72 ①账户信息73 ②还款74 ③取款75 ④转账76 ⑤账单77 ⑥退出78 3)若在账户登陆的时候进行输入的时管理员账户调用/bin/manage.py则可以对用户进行管理,解冻用户、冻结用户、申领新卡79 ①添加账户80 ②冻结账户81 ③解冻账户82 ④退出83 五、常见问题说明。84 日志没有实现,账单没有实现

View Code

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

product.txt

iphone: 5288Mac pro:12000Bike:800Watch:36000Coffe:39Python book:120Book:100

shopping_list.txt

('Coffe', 39)

('Pychon book', 120)

长风破浪会有时,直挂云帆济沧海。

欢迎多多提提意见

你可能感兴趣的:(信用卡atm,python)