标签:
ATM:
1. 指定最大透支额度
2. 可取款
3. 定期还款(每月指定日期还款,如15号)
4. 可存款
5. 定期出账单
6. 支持多用户登陆,用户间转帐
7. 支持多用户
8. 管理员可添加账户、指定用户额度、冻结用户等
---------------------------------
运行环境:OS X and Win
工具:运行pyCharm
Python 版本:3.5+
---------------------------------
博客地址:https://www.cnblogs.com/blademaster/
---------------------------------
主程序入口:main.py
管理员账号/密码:abc/123
目录结构:
1.主程序入口
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import sys, os 4 sys.path.append(os.path.join(os.path.dirname(__file__), "admin.py")) 5 sys.path.append(os.path.join(os.path.dirname(__file__), "user.py")) 6 import admin, user 7 8 9 def show_main_menu(): 10 while True: 11 print("[1]管理员登录\n" 12 "[2]用户登录\n" 13 "[q]退出系统") 14 15 cmd = input("请输入选项:") 16 if cmd == "q": 17 break 18 19 if not cmd.isdigit(): 20 print("无效输入") 21 continue 22 23 if cmd == ‘1‘: 24 admin.show_admin_menu() 25 elif cmd == "2": 26 user.show_user_menu() 27 else: 28 print("无效输入") 29 continue 30 31 32 if __name__ == "__main__": 33 show_main_menu()
2.Admin 入口
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import os, pickle, time 4 5 USER_INFO_SAMPLE = {"username": "abc", 6 "card_no": "1234567", 7 "password": "8888", 8 "credit": 15000.00, 9 "balance": 15000.00, 10 "saving": 0.00, 11 "pay_date": "15", 12 "stat_date": "1", 13 "user_status": 1} 14 15 ADMIN_INFO_SAMPLE = {"username": "admin"} 16 17 USER_INFO = {} 18 19 ADMIN_INFO = {} 20 21 22 def deco(func): 23 """ 24 装饰器 25 :param func: 要装饰的函数 26 :return: _deco: 内层函数 27 """ 28 def _deco(*args, **kwargs): 29 if ADMIN_INFO: 30 func(*args, **kwargs) 31 else: 32 admin_login_menu() 33 return _deco 34 35 36 def admin_login_menu(): 37 """ 38 显示管理员登录菜单 39 :return: 40 """ 41 while True: 42 print("-"*40) 43 username = input("请输入管理员用户名:") 44 pwd = input("请输入管理员密码:") 45 r = admin_login(username, pwd) 46 if r: 47 break 48 49 50 def admin_login(username, pwd): 51 """ 52 管理员登录 53 :param username: 用户名 54 :param pwd: 密码 55 :return: 56 """ 57 if os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "admin", username)): 58 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "admin", username), "r", 59 encoding="utf-8") as f: 60 pwd_file = f.readline() 61 if pwd_file.strip("\n").strip() == pwd: 62 ADMIN_INFO["username"] = username 63 ADMIN_INFO["password"] = pwd 64 print("管理员登录成功") 65 print("-"*40) 66 show_admin_menu() 67 return True 68 else: 69 print("密码错误") 70 else: 71 print("管理员不存在") 72 73 74 def show_all_user(): 75 """ 76 打印所有用户 77 :return: 78 """ 79 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 80 print("目录结构错误") 81 return None 82 83 for root, dirs, files in os.walk(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 84 for d in dirs: 85 u_name = os.path.join(root, d, d) 86 with open(u_name, "rb") as f: 87 data = pickle.load(f) 88 print(data.get("username").center(40, "-")) 89 print("用户名 %s"%data["username"]) 90 print("卡号 %s"%data["card_no"]) 91 print("密码 %s"%data["password"]) 92 print("信用卡额度 $%.2f"%data["credit"]) 93 print("信用卡可用额度 $%.2f" % data["balance"]) 94 print("存款 $%.2f"%data["saving"]) 95 print("账单日 每个月%s日"%data["stat_date"]) 96 print("还款日 每个月%s日"%data["pay_date"]) 97 if data["user_status"] == 0: 98 print("用户状态正常") 99 elif data["user_status"] == 1: 100 print("用户被锁定") 101 if data["user_status"] == 2: 102 print("用户已销户") 103 print("-"*40) 104 105 106 def create_user(): 107 """ 108 创建用户 109 :return: 110 """ 111 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 112 print("目录结构错误") 113 return None 114 115 username = input("请输入新用户名:") 116 card_no = input("请输入卡号:") 117 pwd = input("请输入新密码:") 118 credit = input("请输入额度:") 119 120 USER_INFO["username"] = username 121 USER_INFO["card_no"] = card_no 122 USER_INFO["password"] = pwd 123 USER_INFO["credit"] = float(credit) 124 USER_INFO["balance"] = float(credit) 125 USER_INFO["saving"] = 0.00 126 USER_INFO["pay_date"] = "15" 127 USER_INFO["stat_date"] = "1" 128 USER_INFO["user_status"] = 0 # 正常用户 129 130 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no)): 131 os.makedirs(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no)) 132 133 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no), "wb") as f: 134 pickle.dump(USER_INFO, f, 0) 135 136 137 def load_user(card_no): 138 """ 139 读取用户信息 140 :param card_no: 用户卡号 141 :return: 142 """ 143 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no)): 144 print("无效卡号, 读取失败") 145 return None 146 147 global USER_INFO 148 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no), "rb") as f: 149 USER_INFO = pickle.load(f) 150 return True 151 152 153 def dump_user(card_no): 154 """ 155 写入用户信息 156 :param card_no: 用户卡号 157 :return: 158 """ 159 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no)): 160 print("无效卡号, 写入失败") 161 return None 162 163 global USER_INFO 164 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no), "wb") as f: 165 pickle.dump(USER_INFO, f, 0) 166 return True 167 168 169 def set_credit(): 170 """ 171 调整用户额度 172 :return: 173 """ 174 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 175 print("目录结构错误") 176 return None 177 178 card_no = input("请输入用户卡号:") 179 credit = input("请输入新的额度:") 180 181 if credit.isdigit() and float(credit) > 0: 182 if load_user(card_no): 183 old_credit = float(USER_INFO.get("credit", None)) 184 old_balance = float(USER_INFO.get("balance", None)) 185 USER_INFO["credit"] = float(credit) 186 if old_credit > float(credit): 187 if old_balance > float(credit): 188 USER_INFO["balance"] = float(credit) 189 else: 190 USER_INFO["balance"] = old_balance + (float(credit) - old_credit) 191 dump_user(card_no) 192 print("调整额度完成") 193 else: 194 print("调整额度失败") 195 else: 196 print("额度输入有误") 197 198 199 def freeze_user(): 200 """ 201 冻结用户 202 :return: 203 """ 204 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 205 print("目录结构错误") 206 return None 207 208 card_no = input("请输入用户卡号:") 209 print("1. 恢复用户, 2. 冻结用户") 210 cmd = input("请输入选项:") 211 if cmd.isdigit() and cmd == "2": 212 if load_user(card_no): 213 USER_INFO["user_status"] = 1 214 dump_user(card_no) 215 print("冻结用户完成") 216 else: 217 print("冻结用户失败") 218 elif cmd.isdigit() and cmd == "1": 219 if load_user(card_no): 220 USER_INFO["user_status"] = 0 221 dump_user(card_no) 222 print("恢复用户完成") 223 else: 224 print("恢复用户失败") 225 else: 226 print("输入错误") 227 228 229 def bill(): 230 """ 231 为每个用户生成账单 232 :return: 233 """ 234 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 235 print("目录结构错误") 236 return None 237 238 for root, dirs, files in os.walk(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 239 for d in dirs: 240 u_name = os.path.join(root, d, d) 241 with open(u_name, "rb") as f: 242 data = pickle.load(f) 243 stat_name = "%s-%s" % (time.strftime("%Y"), time.strftime("%m")) 244 if int(time.strftime("%d")) > int(data["stat_date"]) and 245 (not os.path.exists(os.path.join(root, d, stat_name))): 246 with open(os.path.join(root, d, stat_name), "w", encoding="utf-8") as f1: 247 f1.write("%s年%s月需还金额为: %.2f" % (time.strftime("%Y"), time.strftime("%m"), 248 float(data["credit"]) - float(data["balance"]))) 249 250 251 def auto_pay(): 252 """ 253 自动还款 254 :return: 255 """ 256 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 257 print("目录结构错误") 258 return None 259 260 for root, dirs, files in os.walk(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 261 for d in dirs: 262 u_name = os.path.join(root, d, d) 263 with open(u_name, "rb") as f: 264 data = pickle.load(f) 265 stat_name = "%s-%s" % (time.strftime("%Y"), time.strftime("%m")) 266 if int(time.strftime("%d")) > int(data["pay_date"]) and (os.path.exists(os.path.join(root, d, stat_name))): 267 with open(os.path.join(root, d, stat_name), "r", encoding="utf-8") as f1: 268 pay = float(f1.readline().strip("\n").split()[1]) 269 saving = float(data["saving"]) 270 if saving > pay: 271 data["saving"] -= float(pay) 272 data["balance"] += float(pay) 273 os.rename(os.path.join(root, d, stat_name), os.path.join(root, d, "%s.ok" % stat_name)) 274 global USER_INFO 275 USER_INFO = data 276 dump_user(USER_INFO.get("card_no")) 277 else: 278 print("卡号%s还款失败, 余额不足" % data["card_no"]) 279 280 281 @deco 282 def show_admin_menu(): 283 """ 284 显示管理员菜单 285 :return: 286 """ 287 288 while True: 289 bill() 290 auto_pay() 291 print("[1]查看所有用户\n" 292 "[2]添加用户\n" 293 "[3]指定用户额度\n" 294 "[4]冻结用户\n" 295 "[q]退出系统") 296 297 cmd = input("请输入选项:") 298 if cmd == "q": 299 global ADMIN_INFO 300 ADMIN_INFO = {} 301 break 302 303 if not cmd.isdigit(): 304 print("无效输入") 305 continue 306 307 if cmd == ‘1‘: 308 show_all_user() 309 elif cmd == "2": 310 create_user() 311 elif cmd == "3": 312 set_credit() 313 elif cmd == "4": 314 freeze_user() 315 else: 316 print("无效输入") 317 continue
3.User 入口
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import os, pickle, time, logging 4 5 USER_INFO_SAMPLE = {"username": "abc", 6 "card_no": "1234567", 7 "password": "8888", 8 "credit": 15000.00, 9 "balance": 15000.00, 10 "saving": 0.00, 11 "pay_date": "15", 12 "stat_date": "1", 13 "user_status": 1} 14 15 ADMIN_INFO_SAMPLE = {"username": "admin.py"} 16 17 USER_INFO = {} 18 19 20 def deco(func): 21 """ 22 装饰器 23 :param func: 要装饰的函数 24 :return: _deco: 内层函数 25 """ 26 def _deco(*args, **kwargs): 27 if USER_INFO: 28 func(*args, **kwargs) 29 else: 30 user_login_menu() 31 return _deco 32 33 34 def user_login_menu(): 35 """ 36 显示登录菜单 37 :return: 38 """ 39 while True: 40 print("-"*40) 41 card_no = input("请输入卡号:") 42 pwd = input("请输入密码:") 43 r = user_login(card_no, pwd) 44 if r: 45 break 46 47 48 def user_login(card_no, pwd): 49 """ 50 用户登录 51 :param card_no: 卡号 52 :param pwd: 密码 53 :return: 54 """ 55 load_user(card_no) 56 if pwd == USER_INFO.get("password"): 57 print("登录成功") 58 print("-" * 40) 59 show_user_menu() 60 return True 61 else: 62 print("密码错误") 63 64 65 def load_user(card_no): 66 """ 67 读取用户信息 68 :param card_no: 用户卡号 69 :return: 70 """ 71 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no)): 72 print("无效卡号, 读取失败") 73 return None 74 75 global USER_INFO 76 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no), "rb") as f: 77 USER_INFO = pickle.load(f) 78 return True 79 80 81 def dump_user(card_no): 82 """ 83 写入用户信息 84 :param card_no: 用户卡号 85 :return: 86 """ 87 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no)): 88 print("无效卡号, 写入失败") 89 return None 90 91 global USER_INFO 92 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no), "wb") as f: 93 pickle.dump(USER_INFO, f, 0) 94 return True 95 96 97 def set_credit(): 98 """ 99 调整用户额度 100 :return: 101 """ 102 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 103 print("目录结构错误") 104 return None 105 106 credit = input("请输入新的额度:") 107 card_no = USER_INFO.get("card_no") 108 109 if credit.isdigit() and float(credit) > 0: 110 if load_user(card_no): 111 old_credit = float(USER_INFO.get("credit", None)) 112 old_balance = float(USER_INFO.get("balance", None)) 113 USER_INFO["credit"] = float(credit) 114 if old_credit > float(credit): 115 if old_balance > float(credit): 116 USER_INFO["balance"] = float(credit) 117 else: 118 print("无法调整为更高的额度, 请联系管理员") 119 dump_user(card_no) 120 print("调整额度完成") 121 else: 122 print("调整额度失败") 123 else: 124 print("额度输入有误") 125 126 127 def withdraw(): 128 """ 129 取款 130 :return: 131 """ 132 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 133 print("目录结构错误") 134 return None 135 136 money = input("请输入取款金额:") 137 card_no = USER_INFO.get("card_no") 138 if money.isdigit() and float(money) > 0: 139 old_saving = float(USER_INFO.get("saving", None)) 140 if old_saving >= float(money): 141 USER_INFO["saving"] = float(old_saving) - float(money) 142 else: 143 print("余额不足") 144 dump_user(card_no) 145 else: 146 print("输入有误") 147 148 149 def save_money(): 150 """ 151 取款 152 :return: 153 """ 154 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 155 print("目录结构错误") 156 return None 157 158 money = input("请输入存款金额:") 159 card_no = USER_INFO.get("card_no") 160 161 if money.isdigit() and float(money) > 0: 162 old_saving = float(USER_INFO.get("saving", None)) 163 USER_INFO["saving"] = float(old_saving) + float(money) 164 dump_user(card_no) 165 else: 166 print("输入有误") 167 168 169 def trans_money(): 170 """ 171 转账 172 :return: 173 """ 174 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 175 print("目录结构错误") 176 return None 177 178 card_no_to = input("请输入转账卡号:") 179 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no_to)): 180 print("卡号不存在") 181 return None 182 money = input("请输入转账金额:") 183 card_no = USER_INFO.get("card_no") 184 185 if money.isdigit() and float(money) > 0: 186 from_name = os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, card_no) 187 to_name = os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no_to, card_no_to) 188 with open(from_name, "rb") as f1, open(to_name, "rb") as f2: 189 data_from = pickle.load(f1) 190 data_to = pickle.load(f2) 191 192 if data_from["saving"] >= float(money): 193 data_from["saving"] -= float(money) 194 data_to["saving"] += float(money) 195 else: 196 print("余额不足") 197 return None 198 199 try: 200 data_from_new = data_from 201 data_to_new = data_to 202 with open(from_name, "wb") as f1, open(to_name, "wb") as f2: 203 pickle.dump(data_from_new, f1, 0) 204 pickle.dump(data_to_new, f2, 0) 205 except IOError as e: 206 print("出现异常, 操作撤销") 207 logging.error(e) 208 with open(from_name, "wb") as f1, open(to_name, "wb") as f2: 209 pickle.dump(data_from, f1, 0) 210 pickle.dump(data_to, f2, 0) 211 else: 212 print("输入有误") 213 214 215 def show_bill(): 216 """ 217 打印账单 218 :return: 219 """ 220 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 221 print("目录结构错误") 222 return False 223 224 card_no = USER_INFO.get("card_no") 225 226 if os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, 227 "%s-%s.ok" % (time.strftime("%Y"), time.strftime("%m")))): 228 print("本期账单已还清") 229 return False 230 231 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, 232 "%s-%s" % (time.strftime("%Y"), time.strftime("%m")))): 233 print("无账单") 234 return False 235 236 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, 237 "%s-%s" % (time.strftime("%Y"), time.strftime("%m"))), "r", encoding="utf-8") as f: 238 print(f.readline().strip("\n")) 239 return True 240 241 242 def show_balance(): 243 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 244 print("目录结构错误") 245 return False 246 balance = USER_INFO.get("balance") 247 print(‘您当前的可用额度为: %s‘%balance) 248 return True 249 250 251 def pay_credit(): 252 """ 253 信用卡还款 254 :return: 255 """ 256 if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user")): 257 print("目录结构错误") 258 return None 259 260 card_no = USER_INFO.get("card_no") 261 if not show_bill(): 262 print("无需还款") 263 return 264 money = input("请输入还款金额:") 265 if not money.isdigit(): 266 print("输入有误") 267 return 268 money = float(money) 269 if float(USER_INFO.get("saving")) >= money: 270 USER_INFO["saving"] = float(USER_INFO.get("saving")) - money 271 USER_INFO["balance"] = float(USER_INFO.get("balance")) + money 272 with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, 273 "%s-%s" % (time.strftime("%Y"), time.strftime("%m"))), "r+", encoding="utf-8") as f: 274 ls = f.readline().strip("\n").split() 275 pay = float(ls[1]) 276 pay -= money 277 if pay < 0: 278 pay = 0 279 f.seek(0) 280 f.write("%s %.2f" % (ls[0], pay)) 281 if pay == 0: 282 os.rename(os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, 283 "%s-%s" % (time.strftime("%Y"), time.strftime("%m"))), 284 os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "user", card_no, 285 "%s-%s.ok" % (time.strftime("%Y"), time.strftime("%m")))) 286 dump_user(card_no) 287 else: 288 print("还款失败, 余额不足") 289 290 291 @deco 292 def show_user_menu(): 293 """ 294 显示用户菜单 295 :return: 296 """ 297 while True: 298 print("[1]取款\n" 299 "[2]存款\n" 300 "[3]转账\n" 301 "[4]查看账单\n" 302 "[5]信用卡还款\n" 303 "[6]查看额度\n" 304 "[q]退出系统") 305 306 cmd = input("请输入选项:") 307 if cmd == "q": 308 global USER_INFO 309 USER_INFO = {} 310 break 311 312 if not cmd.isdigit(): 313 print("无效输入") 314 continue 315 316 if cmd == ‘1‘: 317 withdraw() 318 elif cmd == "2": 319 save_money() 320 elif cmd == "3": 321 trans_money() 322 elif cmd == "4": 323 show_bill() 324 elif cmd == "5": 325 pay_credit() 326 elif cmd == "6": 327 show_balance() 328 329 else: 330 print("无效输入") 331 continue
标签:
原文地址:http://www.cnblogs.com/blademaster/p/5841536.html