首页 > 代码库 > ATM

ATM

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             break18 19         if not cmd.isdigit():20             print("无效输入")21             continue22 23         if cmd == 1:24             admin.show_admin_menu()25         elif cmd == "2":26             user.show_user_menu()27         else:28             print("无效输入")29             continue30 31 32 if __name__ == "__main__":33     show_main_menu()
main.py

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 =http://www.mamicode.com/ 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 None114 115     username = input("请输入新用户名:")116     card_no = input("请输入卡号:")117     pwd = input("请输入新密码:")118     credit = input("请输入额度:")119 120     USER_INFO["username"] = username121     USER_INFO["card_no"] = card_no122     USER_INFO["password"] = pwd123     USER_INFO["credit"] = float(credit)124     USER_INFO["balance"] = float(credit)125     USER_INFO["saving"] = 0.00126     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 None146 147     global USER_INFO148     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 True151 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 None162 163     global USER_INFO164     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 True167 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 None177 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 None207 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"] = 1214             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"] = 0221             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 None237 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 =http://www.mamicode.com/ 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 None259 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 =http://www.mamicode.com/ 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_INFO275                             USER_INFO = data276                             dump_user(USER_INFO.get("card_no"))277                         else:278                             print("卡号%s还款失败, 余额不足" % data["card_no"])279 280 281 @deco282 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_INFO300             ADMIN_INFO = {}301             break302 303         if not cmd.isdigit():304             print("无效输入")305             continue306 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
admin.py

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 None105 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 None135 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 None157 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 None177 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 None182     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 None198 199         try:200             data_from_new = data_from201             data_to_new = data_to202             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 False223 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 False230 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 False235 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 True240 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 False246     balance = USER_INFO.get("balance")247     print(您当前的可用额度为: %s%balance)248     return True249 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 None259 260     card_no = USER_INFO.get("card_no")261     if not show_bill():262         print("无需还款")263         return264     money = input("请输入还款金额:")265     if not money.isdigit():266         print("输入有误")267         return268     money = float(money)269     if float(USER_INFO.get("saving")) >= money:270         USER_INFO["saving"] = float(USER_INFO.get("saving")) - money271         USER_INFO["balance"] = float(USER_INFO.get("balance")) + money272         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 -= money277             if pay < 0:278                 pay = 0279             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 @deco292 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_INFO309             USER_INFO = {}310             break311 312         if not cmd.isdigit():313             print("无效输入")314             continue315 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
user.py

 

ATM