模擬實現一個ATM + 購物商城程序git
一、額度 15000或自定義
二、實現購物商城,買東西加入 購物車,調用信用卡接口結帳
三、能夠提現,手續費5%
四、支持多帳戶登陸
五、支持帳戶間轉帳
六、記錄每個月平常消費流水
七、提供還款接口
八、ATM記錄操做日誌
九、提供管理接口,包括添加帳戶、用戶額度,凍結帳戶等。。。
十、用戶認證用裝飾器
示例代碼 https://github.com/triaquae/py3_training/tree/master/atmgithub
簡易流程圖:https://www.processon.com/view/link/589eb841e4b0999184934329json
首先畫一個流程圖讓思路更清晰:app
目錄結構圖:iphone
啓動文件函數
start.py源代碼:工具
1 import os, sys 2 3 path = os.path.dirname(__file__) 4 sys.path.append(path) 5 from core import src 6 7 if __name__ == '__main__': 8 src.run()
配置文件相關編碼
setting.py源代碼:spa
1 import os 2 3 BASE_PATH = os.path.dirname(os.path.dirname(__file__)) # ATM的路徑 4 BASE_DB = os.path.join(BASE_PATH, 'db') # db 文件的路徑 5 BASE_LOG = os.path.join(BASE_PATH, 'log') # 日誌路徑 6 7 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ 8 '[%(levelname)s][%(message)s]' # 其中name爲getlogger指定的名字 9 10 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' 11 12 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' 13 14 # 定義日誌輸出格式 結束 15 16 # 若是不存在定義的日誌目錄就建立一個 17 if not os.path.isdir(BASE_LOG): 18 os.mkdir(BASE_LOG) 19 20 # log文件的全路徑 21 logfile_path = os.path.join(BASE_LOG, 'log.log') 22 23 # log配置字典 24 LOGGING_DIC = { 25 'version': 1, 26 'disable_existing_loggers': False, 27 'formatters': { 28 'standard': { 29 'format': standard_format 30 }, 31 'simple': { 32 'format': simple_format 33 }, 34 }, 35 'filters': {}, 36 'handlers': { 37 # 打印到終端的日誌 38 'console': { 39 'level': 'DEBUG', 40 'class': 'logging.StreamHandler', # 打印到屏幕 41 'formatter': 'simple' 42 }, 43 # 打印到文件的日誌,收集info及以上的日誌 44 'default': { 45 'level': 'DEBUG', 46 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 47 'formatter': 'standard', 48 'filename': logfile_path, # 日誌文件 49 'maxBytes': 1024 * 1024 * 5, # 日誌大小 5M 50 'backupCount': 5, 51 'encoding': 'utf-8', # 日誌文件的編碼,不再用擔憂中文log亂碼了 52 }, 53 54 }, 55 'loggers': { 56 # logging.getLogger(__name__)拿到的logger配置 57 '': { 58 'handlers': ['default', 'console'], # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 59 'level': 'INFO', 60 'propagate': True, # 向上(更高level的logger)傳遞 61 }, 62 }, 63 }
核心邏輯3d
src.py源代碼:
1 from interface import user, bank, shopping 2 from lib import common 3 4 user_data = { 5 'name': None 6 # 判斷用戶是否登入 7 } 8 9 10 def logout(): 11 ''' 12 退出. 13 :return: 14 ''' 15 user_data['name'] = None 16 17 18 def login(): 19 ''' 20 登入. 21 :return: 22 ''' 23 print('登陸。。。') 24 if user_data['name']: 25 print('你已經登入過了') 26 count = 0 27 while True: 28 name = input('請輸入用戶名>>:').strip() 29 if name.lower() == 'q': break 30 password = input('請輸入密碼>>:').strip() 31 flag, msg = user.login_interface(name, password) 32 if flag: 33 user_data['name'] = name 34 print(msg) 35 break 36 else: 37 count += 1 38 if count == 3: 39 user.locked_interface(name) 40 print('錯誤次數過多,已鎖定') 41 else: 42 43 print(msg) 44 45 46 def register(): 47 ''' 48 註冊. 49 :return: 50 ''' 51 print('註冊。。。') 52 if user_data['name']: 53 print('你已經登入過了') 54 while True: 55 name = input('請輸入用戶名>>:').strip() 56 if name.lower() == 'q': break 57 password = input('請輸入密碼>>:').strip() 58 password2 = input('再次輸入密碼>>:').strip() 59 if password == password2: 60 flag, msg = user.register_interface(name, password) 61 if flag: 62 print(msg) 63 break 64 else: 65 print('用戶已存在') 66 else: 67 print('兩次密碼不一致') 68 69 70 @common.login_auth 71 def check_balance(): 72 ''' 73 查看餘額. 74 :return: 75 ''' 76 print('查看餘額。。。') 77 balance = bank.check_balance_interface(user_data['name']) 78 print(balance) 79 80 81 @common.login_auth 82 def transfer(): 83 ''' 84 轉帳. 85 :return: 86 ''' 87 print('轉帳。。。') 88 while True: 89 to_name = input('輸入轉帳的用戶>>:').strip() 90 balance = input('輸入轉帳金額>>:').strip() 91 if balance.isdigit(): 92 balance = int(balance) 93 flag, msg = bank.transfer_interface(user_data['name'], to_name, balance) 94 if flag: 95 print(msg) 96 break 97 else: 98 print(msg) 99 else: 100 print('必須輸入數字') 101 102 103 @common.login_auth 104 def repay(): 105 ''' 106 還款. 107 :return: 108 ''' 109 print('還款。。。') 110 balance = input('請輸入還款金額>>:').strip() 111 if balance.isdigit(): 112 balance = int(balance) 113 falg, msg = bank.repay_interface(user_data['name'], balance) 114 if falg: 115 print(msg) 116 else: 117 print(msg) 118 else: 119 print('必須輸入數字') 120 121 122 @common.login_auth 123 def withdraw(): 124 ''' 125 取款. 126 :return: 127 ''' 128 print('取款。。。') 129 balance = input('輸入取款金額>>:').strip() 130 if balance.isdigit(): 131 balance = int(balance) 132 falg, msg = bank.withdraw_interface(user_data['name'], balance) 133 if falg: 134 print(msg) 135 else: 136 print(msg) 137 else: 138 print('必須輸入數字') 139 140 141 @common.login_auth 142 def check_record(): 143 ''' 144 查看流水. 145 :return: 146 ''' 147 print('查看流水。。。') 148 bankflow = bank.check_bankflow_interface(user_data['name']) 149 for flow in bankflow: 150 print(flow) 151 152 153 @common.login_auth 154 def shop(): 155 ''' 156 1 先循環打印出商品 157 2 用戶輸入數字選擇商品(判斷是不是數字,判斷輸入的數字是否在範圍內) 158 3 取出商品名,商品價格 159 4 判斷用戶餘額是否大於商品價格 160 5 餘額大於商品價格時,判斷此商品是否在購物車裏 161 5.1 在購物車裏,個數加1 162 5.1 不在購物車裏,拼出字典放入({‘good’:{‘price’:10,‘count’:1}}) 163 6 用戶餘額減掉商品價格 164 7 花費加上商品價格 165 8 當輸入 q時,購買商品 166 8.1 消費爲0 ,直接退出 167 8.2 打印購物車 168 8.3 接受用戶輸入,是否購買 當輸入y,直接調購物接口實現購物 169 :return: 170 ''' 171 print('購物。。。') 172 goods_list = [ 173 ['coffee', 10], 174 ['chicken', 20], 175 ['iphone', 8000], 176 ['macPro', 15000], 177 ['car', 100000] 178 ] 179 money = 0 180 user_balance = bank.check_balance_interface(user_data['name']) 181 shopping_cart = {} 182 while True: 183 for i, v in enumerate(goods_list): 184 print(f'{i}: {v}') 185 choice = input('請輸入須要購買商品的編號(數字)(q退出)>>:').strip() 186 if choice.isdigit(): 187 choice = int(choice) 188 if choice >= len(goods_list): 189 print('商品不存在') 190 continue 191 shop_name = goods_list[choice][0] 192 shop_price = goods_list[choice][1] 193 if user_balance >= shop_price: 194 if shop_name in shopping_cart: 195 shopping_cart[shop_name]['count'] += 1 196 else: 197 shopping_cart[shop_name] = {'price': shop_price, 'count': 1} 198 user_balance -= shop_price 199 money += shop_price 200 print(f'{shop_name}已加入購物車') 201 else: 202 print('餘額不足') 203 continue 204 elif choice.lower() == 'q': 205 if money == 0: 206 break 207 print(shopping_cart) 208 user = input('是否購買Y/N>>:').strip() 209 if user.lower() == 'y': 210 falg, msg = shopping.shopping_interface(user_data['name'], money, shopping_cart) 211 if falg: 212 print(msg) 213 break 214 else: 215 print(msg) 216 break 217 elif user.lower() == 'n': 218 print('你什麼都沒有購買') 219 break 220 else: 221 print('無選項') 222 continue 223 224 else: 225 print('輸入非法字符') 226 227 228 @common.login_auth 229 def check_shopping_cart(): 230 ''' 231 查看購物車. 232 :return: 233 ''' 234 print('查看購物車。。。') 235 shoppingcart = shopping.check_shoppingcart(user_data['name']) 236 if shoppingcart: 237 print(shoppingcart) 238 else: 239 print('無商品') 240 241 242 func_dic = { 243 '1': login, 244 '2': register, 245 '3': check_balance, 246 '4': transfer, 247 '5': repay, 248 '6': withdraw, 249 '7': check_record, 250 '8': shop, 251 '9': check_shopping_cart, 252 '10': logout 253 } 254 255 256 def run(): 257 ''' 258 功能選擇接口. 259 :return: 260 ''' 261 while True: 262 print('''選擇須要的功能: 263 一、登入 264 二、註冊 265 三、查看餘額 266 四、轉帳 267 五、還款 268 六、取款 269 七、查看流水 270 八、購物 271 九、查看購買商品 272 十、退出程序 273 ''') 274 choice = input('編號>>:').strip() 275 if choice in func_dic: 276 func_dic[choice]()
用戶數據
db_handler.py源代碼:
1 import os 2 import json 3 from conf import setting 4 5 6 def save(user_dic): 7 ''' 8 保存用戶信息文件. 9 :param user_dic: 用戶信息 10 :return: 11 ''' 12 user_path = os.path.join(setting.BASE_DB, '%s.json' % user_dic['name']) 13 with open(user_path, 'w', encoding='utf-8')as f: 14 json.dump(user_dic, f) 15 f.flush() 16 17 18 # 19 def select(name): 20 """ 21 查詢用戶文件. 22 :param name: str --> 用戶名 23 :return: None, user_dic 24 """ 25 user_path = os.path.join(setting.BASE_DB, '%s.json' % name) 26 if os.path.exists(user_path): 27 with open(user_path, 'r', encoding='utf-8')as f: 28 user_dic = json.load(f) 29 return user_dic 30 else: 31 return None
銀行接口
bank.py源代碼:
1 from db import db_handler 2 from core import src 3 from lib import common 4 5 bank_logger = common.get_logger('bank') 6 7 8 def check_balance_interface(name): 9 ''' 10 查詢餘額接口. 11 :param name:帳戶名 12 :return:balance 13 ''' 14 user_dic = db_handler.select(name) 15 balance = user_dic['balance'] 16 return balance 17 18 19 def transfer_interface(from_name, to_name, balance): 20 ''' 21 轉帳接口. 22 :param from_name:轉帳用戶 23 :param to_name: 收款用戶 24 :param balance: 轉帳金額 25 :return:True,False 26 ''' 27 if from_name == to_name: 28 return False, '不能給本身轉帳' 29 to_dic = db_handler.select(to_name) 30 if to_dic: 31 from_dic = db_handler.select(from_name) 32 if from_dic['balance'] >= balance: 33 to_dic['balance'] += balance 34 from_dic['balance'] -= balance 35 from_dic['bankflow'].append('你向%s轉帳%s元' % (to_name, balance)) 36 to_dic['bankflow'].append('你收到%s的轉帳%s元' % (from_name, balance)) 37 bank_logger.info('%s向%s轉帳%s元' % (from_name, to_name, balance)) 38 db_handler.save(from_dic) 39 db_handler.save(to_dic) 40 return True, '轉帳成功' 41 else: 42 return False, '餘額不足' 43 else: 44 return False, '用戶不存在' 45 46 47 def repay_interface(name, balance): 48 ''' 49 還款接口. 50 :param name: 還款用戶 51 :param balance: 還款金額 52 :return:True,False 53 ''' 54 user_dic = db_handler.select(name) 55 if user_dic['balance'] >= balance: 56 user_dic['balance'] -= balance 57 user_dic['bankflow'].append('還款%s' % balance) 58 bank_logger.info('%s還款了%s元' % (name, balance)) 59 db_handler.save(user_dic) 60 return True, '還款成功' 61 else: 62 return False, '餘額不足以還款' 63 64 65 def withdraw_interface(name, balance): 66 ''' 67 取款接口. 68 :param name: 取款用戶 69 :param balance: 取款金額 70 :return:True,False 71 ''' 72 user_dic = db_handler.select(name) 73 if user_dic['balance'] >= balance * 1.05: # 0.5%的手續費 74 user_dic['balance'] -= balance * 1.05 75 user_dic['bankflow'].append('取款%s,手續費%s' % (balance, balance * 0.05)) 76 bank_logger.info('你取款了%s元,手續費%s元' % (balance, balance * 0.05)) 77 db_handler.save(user_dic) 78 return True, '取款成功,取出金額%s' % balance 79 else: 80 return False, '餘額不足' 81 82 83 def consume_interface(name, money): 84 ''' 85 消費接口. 86 :param name: 消費用戶 87 :param money: 消費金額 88 :return:True,False 89 ''' 90 user_dic = db_handler.select(name) 91 if user_dic['balance'] >= money: 92 user_dic['balance'] -= money 93 db_handler.save(user_dic) 94 return True, '扣款成功' 95 else: 96 return False, '餘額不足' 97 98 99 def check_bankflow_interface(name): 100 ''' 101 銀行流水. 102 :param name: 帳戶名 103 :return:user_bankflow 104 ''' 105 user_dic = db_handler.select(name) 106 user_bankflow = user_dic['bankflow'] 107 return user_bankflow
購物接口
shopping.p源代碼:
1 from db import db_handler 2 from interface import bank 3 4 5 def shopping_interface(name, money, shoppingcart): 6 ''' 7 購物接口. 8 :param name:用戶名 9 :param money: 消費金額 10 :param shoppingcart: 購物車清單 11 :return:True,False 12 ''' 13 flag, msg = bank.consume_interface(name, money) 14 if flag: 15 user_dic = db_handler.select(name) 16 user_dic['shoppingcart'] = shoppingcart 17 db_handler.save(user_dic) 18 return True, '購買成功' 19 else: 20 return False, '餘額不足' 21 22 23 def check_shoppingcart(name): 24 ''' 25 查看購物車接口. 26 :param name: 用戶名 27 :return:user_dic['shoppingcart'] 28 ''' 29 user_dic = db_handler.select(name) 30 31 return user_dic['shoppingcart']
用戶信息接口
user.py源代碼:
1 from db import db_handler 2 from lib import common 3 4 user_logger = common.get_logger('user') 5 6 7 def login_interface(name, password): 8 ''' 9 登入接口. 10 :param name:用戶名 11 :param password: 用戶密碼 12 :return:True,False 13 ''' 14 user_dic = db_handler.select(name) 15 if user_dic: # {'name': 'song', 'password': '123'} 16 if password == user_dic['password'] and not user_dic['locked']: 17 user_logger.info('用戶%s登入了帳戶' % name) 18 return True, '登入成功' 19 else: 20 return False, '用戶名密碼錯誤或被鎖定' 21 else: 22 return False, '用戶不存在' 23 24 25 def register_interface(name, password, balance=15000): 26 ''' 27 註冊接口. 28 :param name:用戶名 29 :param password: 密碼 30 :param balance: 確認密碼 31 :return:True,False 32 ''' 33 user_dic = db_handler.select(name) 34 if user_dic: 35 return False, '用戶已存在' 36 else: 37 user_dic = {'name': name, 'password': password, 'balance': balance, 38 'locked': False, 'bankflow': [], 'shoppingcart': {}} 39 db_handler.save(user_dic) 40 user_logger.info('用戶%s註冊成功' % name) 41 return True, '註冊成功' 42 43 44 def locked_interface(name): 45 ''' 46 鎖定接口. 47 :param name:用戶名 48 :return: 49 ''' 50 user_dic = db_handler.select(name) 51 if user_dic: 52 user_dic['locked'] = True 53 db_handler.save(user_dic) 54 55 56 def un_locked_interface(name): 57 ''' 58 解鎖用戶. 59 :param name:用戶名 60 :return: 61 ''' 62 user_dic = db_handler.select(name) 63 if user_dic: 64 user_dic['locked'] = False 65 db_handler.save(user_dic)
模塊工具
common.py源代碼:
1 from core import src 2 import logging.config 3 from conf import setting 4 5 6 def login_auth(func): 7 ''' 8 裝飾器 9 :param func: 函數名 10 :return: wrapper 11 ''' 12 13 def wrapper(*args, **kwargs): 14 if not src.user_data['name']: 15 src.login() 16 else: 17 return func(*args, **kwargs) 18 19 return wrapper 20 21 22 def get_logger(name): 23 ''' 24 盜用日誌字典. 25 :param name:日誌名字 26 :return: 27 ''' 28 logging.config.dictConfig(setting.LOGGING_DIC) # 使用這個日誌字典 29 logger = logging.getLogger('name') 30 return logger
功能演示:
一、註冊:
二、登入:
三、查看餘額:
四、轉帳:
log文件記錄的日誌:
五、還款:
六、取款:
七、查看流水:
查看song的流水:
八、購物:
九、查看購物車:
十、退出登入(退出後須要從新登入)
感謝觀看!記得雙擊麼麼噠!