ATM功能實現項目

模擬實現一個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的流水:

 八、購物:

 

 

 

 

 

 

 

 九、查看購物車:

 

 十、退出登入(退出後須要從新登入)

感謝觀看!記得雙擊麼麼噠!

相關文章
相關標籤/搜索