python atm作业_python作业---模拟实现一个ATM + 购物商城程序

作业需求:

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

额度 15000或自定义

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

可以提现,手续费5%

支持多账户登录

支持账户间转账

记录每月日常消费流水

提供还款接口

ATM记录操作日志

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

用户认证用装饰器

作业思路

实现购物商城和信用卡的ATM功能

本程序有6个模块,实现了购物和ATM的取款、还款、转账、账单查看和用户管理的功能。

程序结构:

test

├── README

├── ATM #ATM主程目录

│ ├── __init__.py

│ ├── bin #ATM 执行文件 目录

│ │ ├── __init__.py

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

│ ├── conf #配置文件

│ │ ├── __init__.py

│ │ └── settings.py

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

│ │ ├── __init__.py

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

│ │ ├── auth.py #用户认证模块

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

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

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

│ │ └── transaction.py #记账\还钱\取钱等所有的与账户金额相关的操作都 在这

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

│ │ ├── __init__.py

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

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

│ └── log #日志目录

│ ├── __init__.py

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

│ └── transactions.log #所有的交易日志

└── shopping #电子商城程序

├── shopping_mol #购物商城的程序

└── __init__.py

开始先运行atm.py时执行程序,直接到main下,输入正确用户zcl和密码abc,才能进行下一步的操作,然后列出atm的功能列表(还款、取款、转账、查看等)

shopping是一个独立的程序,调用了还款的金额,购物结束后把剩余的金额在写入到文件中,存入到信用卡中。

流程图

shopping_mol

1 importos,json2

3 dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))4 print(dir)5 file="%s/ATM/db/accounts/zcl.json"%dir6 print(file)7 with open(file, "r", encoding="utf-8") as f:8 account_data =json.load(f)9 print(account_data)10

11

12

13 product_list =[14 ("Apple Iphone",6000),15 ("Apple Watch",4600),16 ("Books",600),17 ("Bike",750),18 ("cups",120),19 ("Apple",50),20 ("banana",60),21 ]22 shopping_list =[]23 salary = account_data["balance"]24

25 whileTrue:26 for index,item inenumerate(product_list):27 print(index,item)28 user_choice = input ("Enter the serial number:")29 ifuser_choice.isdigit():30 user_choice =int (user_choice)31 if user_choice =0:32 p_item =product_list[user_choice]33 if p_item[1] <=salary:34 shopping_list.append(p_item)35 salary -= p_item[1]36 with open(file,"w+",encoding="utf-8") as f:37 account_data["balance"]=salary38 print(account_data)39 json.dump(account_data,f)40 print ("Added %s into your shopping cart,your current balance is %s"%(p_item,salary))41 else:42 print ("Your balance is not enough!!")43 else:44 print ("The goods you entered do not exist")45

46 elif user_choice == "q":47 print ("====shopping list====")48 for p inshopping_list:49 print(p)50 print ("Your current balance is %s"%salary)51 exit()52 else:53 print ("invalid option")

View Code

atm

1 #ATM程序的执行文件

2 importos3 importsys4

5 dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #找到路径

6 sys.path.insert(0,dir) #添加路径

7

8

9 print(dir)10 print(sys.path)11

12 #将main.py里面的所有代码封装成main变量

13 from core importmain14

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

View Code

settings

1 #配置文件

2 importlogging3 importos4

5 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#找到路径

6

7 LOGIN_LEVEL = logging.INFO#定义日志的记录级别

8

9 DATABASE ={10 "db_tool":"file_storage", #文件存储,这里可拓展成数据库形式的

11 "name":"accounts", #db下的文件名

12 "path":"%s/db"%BASE_DIR13 }14 #print(DATABASE)

15 #日志类型

16 LOGIN_TYPE={17 "access":"access.log",18 "transaction":"transaction.log"

19 }20

21 #用户交易类型,每个类型对应一个字典,包括帐户金额变动方式,利息

22 TRANSACTION_TYPE={23 "repay":{"action":"plus","interest":0},24 "withdraw":{"action":"minus","interest":0.05},25 "transfer":{"action":"minus","interest":0}26 }

View Code

account

1 """

2 用于处理用户信息的load or dump3 每进行一个操作就将信息更新到数据库4 """

5 from core importdb_handle6 from conf importsettings7 importjson8

9 defload_account(account_id):10 """

11 将用户信息从文件中load出来12 :return: 用户信息的字典13 """

14 #返回路径 ATM/db/accounts

15 db_path =db_handle.handle(settings.DATABASE)16 account_file = "%s/%s.json" %(db_path, account_id)17 with open(account_file, "r", encoding="utf-8") as f:18 account_data =json.load(f)19 returnaccount_data20

21

22 defdump_account(account_data):23 """

24 将已更改的用户信息更新到用户文件25 :param account_data: 每操作后用户的信息26 :return:27 """

28 db_path =db_handle.handle(settings.DATABASE)29 account_file = "%s/%s.json" % (db_path, account_data["id"])30 with open(account_file, "w+", encoding="utf-8") as f:31 json.dump(account_data, f)32

33 print("dump success")

View Code

auth

1 #认证模块

2 importos3 importjson4 importtime5

6 from core importdb_handle7 from conf importsettings8

9 defaccess_auth(account,password,log_obj):10 """

11 下面的access_login调用access_auth方法,用于登陆12 :param acount: 用户名13 :param password: 密码14 :return:如果未超期,返回字典,超期则打印相应提示15 """

16 db_path=db_handle.handle(settings.DATABASE) #调用db_handle下的handle方法,返回路径/db/accounts

17 print(db_path)18 account_file="%s/%s.json"%(db_path,account) #用户文件

19 print(account_file)20 if os.path.isfile(account_file): #如果用户文件存在(即用户存在)

21 with open(account_file,"r",encoding="utf-8") as f: #打开文件

22 account_data = json.load(f) #file_data为字典形式

23 print(account_data)24 if account_data["password"]==password:25 expire_time=time.mktime(time.strptime(account_data["expire_date"],"%Y-%m-%d"))26 #print(expire_time)

27 #print(time.strptime(account_data["expire_date"],"%Y-%m-%d"))

28 if time.time()>expire_time: #如果信用卡已超期

29 log_obj.error("Account [%s] had expired,Please contract the bank" %account)30 print("Account %s had expired,Please contract the bank"%account)31 else: #信用卡未超期,返回用户数据的字典

32 #print("return")

33 log_obj.info("Account [%s] logging success" %account)34 returnaccount_data35 else:36 log_obj.error("Account or Passworddoes not correct!")37 print("Account or Passworddoes not correct!")38 else:#用户不存在

39 log_obj.error("Account [%s] does not exist!" %account)40 print("Account [%s] does not exist!"%account)41

42

43 defaccess_login(user_data,log_obj):44 """

45 用记登陆,当登陆失败超过三次则退出46 :param user_data: main.py里面的字典47 :return:若用户帐号密码正确且信用卡未超期,返回用户数据的字典48 """

49 retry=050 while not user_data["is_authenticated"] and retry<3:51 account=input("Account:").strip()52 password= input("Password:").strip() #用户帐号密码正确且信用卡未超期,返回用户数据的字典

53 user_auth_data=access_auth(account,password,log_obj)54 ifuser_auth_data:55 user_data["is_authenticated"]=True #用户认证为True

56 user_data["account_id"]=account #用户帐号ID为帐号名

57 print("welcome %s"%account)58 returnuser_auth_data59 retry+=1

60 else:61 print("Account [%s] try logging too many times..." %account)62 log_obj.error("Account [%s] try logging too many times..." %account)63 exit()

View Code

db_handle

1 #处理与数据库的交互,若是file_db_storage,返回路径

2

3 deffile_db_handle(database):4 """

5 数据存在文件6 :param database:7 :return: 返回路径 ATM1/db/accounts8 """

9 db_path="%s/%s"%(database["path"],database["name"])10 #print(db_path)

11 returndb_path12

13 #def mysql_db_handle(database):

14 #"""

15 #处理mysql数据库,这里用文件来存数据,

16 #保留这个方法主要为了程序拓展性

17 #:return:

18 #"""

19 #pass

20

21 defhandle(database):22 """

23 对某种数据库形式处于是24 本程序用的是文件处理file_storage25 :param database: settings里面的DATABASE26 :return: 返回路径27 """

28 if database["db_tool"]=="file_storage":29 returnfile_db_handle(database)30 #if database["db_tool"]=="mysql":

31 #return mysql_db_handle(database)

View Code

log

1 importlogging2 from conf importsettings3 from core importdb_handle4

5 deflog(logging_type):6 """

7 main模块调用access_logger = log.log("access")8 :param logging_type: "access"9 return: 返回logger日志对象10 """

11 logger=logging.getLogger(logging_type) #传日志用例,生成日志对象

12 logger.setLevel(settings.LOGIN_LEVEL) #设置日志级别

13

14 ch = logging.StreamHandler() #日志打印到屏幕,获取对象

15 ch.setLevel(settings.LOGIN_LEVEL)16

17 #获取文件日志对象及日志文件

18 log_file="%s/log/%s"%(settings.BASE_DIR,settings.LOGIN_TYPE[logging_type])19 fh =logging.FileHandler(log_file)20 fh.setLevel(settings.LOGIN_LEVEL)21

22 #日志格式

23 formatter=logging.Formatter("%(asctime)s-%(name)s-%(levelname)s-%(message)s")24

25 #输出格式

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

29 #把日志打印到指定的handler

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

33 return logger #log方法返回logger对象

View Code

transaction

1 """

2 交易模块,处理用户金额移动3 """

4 from conf importsettings5 from core importaccount6 from core importlog7

8 def make_transaction(account_data,transcation_type,amount,log_obj,**kwargs):9 """

10 处理用户的交易11 :param account_data:字典,用户的帐户信息12 :param transaction_type:用户交易类型,repay or withdraw...13 :param amount:交易金额14 :return:用户交易后帐户的信息15 """

16 amount=float(amount) #将字符串类型转换为float类型

17 if transcation_type insettings.TRANSACTION_TYPE:18 interest=amount*settings.TRANSACTION_TYPE[transcation_type]["interest"] #利息计算

19 old_balace= account_data["balance"] #用户原金额

20 print(interest,old_balace)21 #如果帐户金额变化方式是"plus",加钱

22 if settings.TRANSACTION_TYPE[transcation_type]["action"]=="plus":23 new_balance=old_balace+amount+interest24 log_obj.info("Your account repay%s,your account new balance is %s"%(amount,new_balance))25 #如果帐户金额变化方式是"minus",减钱

26 elif settings.TRANSACTION_TYPE[transcation_type]["action"]=="minus":27 new_balance=old_balace-amount-interest28 log_obj.info("Your account withdraw%s,your account new balance is %s" %(amount, new_balance))29 if new_balance<0:30 print("Your Credit [%s] is not enough for transaction [-%s],"

31 "and Now your current balance is [%s]" % (account_data["credit"], (amount+interest), old_balace))32 return

33 account_data["balance"]=new_balance34 account.dump_account(account_data) #调用core下account模块将已更改的用户信息更新到用户文件

35 returnaccount_data36 else:37 print("Transaction is not exist!")

View Code

main

1 """

2 主逻辑交互模块3 """

4 from core importauth5 from core importlog6 from core importtransaction7 from core importaccount8 from conf importsettings9 from core importdb_handle10

11 importos12

13

14 #用户数据信息

15 user_data ={16 'account_id':None, #帐号ID

17 'is_authenticated':False, #是否认证

18 'account_data':None #帐号数据

19

20 }21

22 #调用log文件下的log方法,返回日志对象

23 access_logger = log.log("access")24 transaction_logger = log.log("transaction")25

26

27

28 defaccount_info(access_data):29 """

30 access_data:包括ID,is_authenticaed,用户帐号信息31 查看用户帐户信息32 :return:33 """

34 print(access_data)35

36

37

38

39 defrepay(access_data):40 """

41 access_data:包括ID,is_authenticaed,用户帐号信息42 还款43 :return:44 """

45 print(access_data)46 print("repay")47 #调用account模块的load_account方法,从数据库从load出用户信息

48 account_data = account.load_account(access_data["account_id"])49 print(account_data)50 current_balance = """

51 -------------BALANCE INFO--------------52 Credit:%s53 Balance:%s54 """ % (account_data["credit"], account_data["balance"])55 back_flag =False56 while notback_flag:57 print(current_balance)58 repay_amount = input("\033[31;1mInput repay amount(b=back):\033[0m").strip()59 #如果用户输入整型数字

60 if len(repay_amount) > 0 andrepay_amount.isdigit():61 #调用transaction模块的方法,参数分别是用户帐户信息,交易类型,交易金额

62 new_account_data = transaction.make_transaction(account_data, "repay", repay_amount,transaction_logger)63 ifnew_account_data:64 print("\033[42;1mNew Balance:%s\033[0m" % new_account_data["balance"])65

66 else:67 print("\033[31;1m%s is not valid amount,Only accept interger!\033[0m" %repay_amount)68

69 if repay_amount =="b" or repay_amount == "back":70 back_flag =True71

72 defwithdraw(access_data):73 """

74 取款75 :return:76 """

77 print(access_data)78 print("withdraw")79 #调用account模块的load_account方法,从数据库从load出用户信息

80 account_data = account.load_account(access_data["account_id"])81 print(account_data)82 current_balance = """

83 -------------BALANCE INFO--------------84 Credit:%s85 Balance:%s86 """ % (account_data["credit"], account_data["balance"])87 back_flag =False88 while notback_flag:89 print(current_balance)90 withdraw_amount = input("\033[31;1mInput withdraw amount(b=back):\033[0m").strip()91 #如果用户输入整型数字

92 if len(withdraw_amount) > 0 andwithdraw_amount.isdigit():93 #调用transaction模块的方法,参数分别是用户帐户信息,交易类型,交易金额

94 new_account_data = transaction.make_transaction(account_data, "withdraw", withdraw_amount,transaction_logger)95 ifnew_account_data:96 print("\033[42;1mNew Balance:%s\033[0m" % new_account_data["balance"])97

98 else:99 print("\033[31;1m%s is not valid amount,Only accept interger!\033[0m" %withdraw_amount)100

101 if withdraw_amount == "b" or withdraw_amount == "back":102 back_flag =True103

104

105 deftransfer(access_data):106 """

107 转帐108 :return:109 """

110 print(access_data)111 print("transfer")112 #调用account模块的load_account方法,从数据库从load出用户信息

113 account_data = account.load_account(access_data["account_id"])114 print(account_data)115 current_balance = """

116 -------------BALANCE INFO--------------117 Credit:%s118 Balance:%s119 """ % (account_data["credit"], account_data["balance"])120 back_flag =False121 while notback_flag:122 print(current_balance)123 transfer_amount = input("\033[31;1mInput transfer amount(b=back):\033[0m").strip()124 #如果用户输入整型数字

125 if len(transfer_amount) > 0 andtransfer_amount.isdigit():126 #调用transaction模块的方法,参数分别是用户帐户信息,交易类型,交易金额

127 new_account_data = transaction.make_transaction(account_data, "transfer", transfer_amount,transaction_logger)128 ifnew_account_data:129 print("\033[42;1mNew Balance:%s\033[0m" % new_account_data["balance"])130 new_account_data2 = transaction.make_transaction(account_data, "repay", new_account_data["balance"],transaction_logger)131 ifnew_account_data2:132 print("\033[42;1mNew Balance2:%s\033[0m" % new_account_data2["balance"])133

134 else:135 print("\033[31;1m%s is not valid amount,Only accept interger!\033[0m" %transfer_amount)136

137 if transfer_amount == "b" or transfer_amount == "back":138 back_flag =True139

140

141 defpaycheck(access_data):142 """

143 账单查看144 :return:145 """

146

147 time=input("please input time(Y-M-D):")148 log_file = "%s/log/%s" % (settings.BASE_DIR, settings.LOGIN_TYPE["transaction"])149 print(log_file)150 with open (log_file,"r",encoding="utf-8") as f :151 for i inf.readlines():152 if time == i[0:10]:153 print(i)154 elif time == i[0:7]:155 print(i)156 elif time == i[0:4]:157 print(i)158

159

160

161

162 deflogout(access_data):163 """

164 退出登陆165 :return:166 """

167 q = input("If you want to quit,please input q:")168 if q =="q":169 exit()170

171

172 def interactive(access_data,**kwargs):173 """

174 用户交互175 :return:176 """

177 msg =(178 """

179 -------------ZhangChengLiang Bank---------------180 \033[31;1m181 1. 账户信息182 2. 存款183 3. 取款184 4. 转账185 5. 账单186 6. 退出187 \033[0m"""

188 )189 menu_dic ={190 "1":account_info,191 "2":repay,192 "3":withdraw,193 "4":transfer,194 "5":paycheck,195 "6":logout196 }197 flag =False198 while notflag:199 print(msg)200 choice = input("<<<: if choice inmenu_dic:202>

203 menu_dic[choice](access_data)204

205 else:206 print("\033[31;1mYou choice doesn't exist!\033[0m")207

208

209

210 defrun():211 """

212 当程序启动时调用,用于实现主要交互逻辑213 :return:214 """

215 #调用认证模块,返回用户文件json.load后的字典,传入access_logger日志对象

216 access_data =auth.access_login(user_data, access_logger)217 print("AA")218 if user_data["is_authenticated"]: #如果用户认证成功

219 print("has authenticated")220 #将用户文件的字典赋给user_data["account_data"]

221 user_data["account_data"] =access_data222 interactive(user_data) #用户交互开始

View Code

.json

{"status": 0, "expire_date": "2021-01-01", "credit": 15000, "pay_day": 22, "balance": 13650, "enroll_date": "2016-01-02", "id": 22, "password": "abc"}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值