ATM + 購(gòu)物車
需求分析
'''
- 額度 15000或自定義
- 實(shí)現(xiàn)購(gòu)物商城,買東西加入 購(gòu)物車,調(diào)用信用卡接口結(jié)賬
- 可以提現(xiàn),手續(xù)費(fèi)5%
- 支持多賬戶登錄
- 支持賬戶間轉(zhuǎn)賬
- 記錄每月日常消費(fèi)流水
- 提供還款接口
- ATM記錄操作日志
- 提供管理接口,包括添加賬戶、用戶額度,凍結(jié)賬戶等...
- 用戶認(rèn)證功能
'''
一個(gè)項(xiàng)目是如何從無(wú)到有的
# 1、需求分析:
'''
開發(fā)項(xiàng)目前,都必須找到相應(yīng)的客戶,讓客戶給企業(yè)提出項(xiàng)目的需求,以及需要實(shí)現(xiàn)的功能有哪些,拿到需求后再提取出一些列功能。
'''
# 2、設(shè)計(jì)程序以及程序的架構(gòu)
'''
在所有一線開發(fā)的企業(yè)里,在一個(gè)項(xiàng)目開發(fā)前,都應(yīng)該設(shè)計(jì)程序,那樣會(huì)讓程序解開耦合,從而提高項(xiàng)目的管理以及開發(fā)的效率。
'''
# 3、分任務(wù)開發(fā)
'''
在公司里面,開發(fā)項(xiàng)目需要這幾種崗位人才:
UI設(shè)計(jì): 軟件的外觀設(shè)計(jì)者,通過一些炫酷的設(shè)計(jì),提高用戶的對(duì)軟件的體驗(yàn)感。
前端開發(fā): UI設(shè)計(jì)僅僅只是把一些外觀圖設(shè)計(jì)出來(lái),那前端開發(fā)需要把UI的設(shè)計(jì)圖拿到之后,對(duì)軟件界面的進(jìn)行排版。
后端開發(fā)(python): 項(xiàng)目里業(yè)務(wù)以及功能的邏輯處理!
'''
# 4、項(xiàng)目測(cè)試
'''
測(cè)試工程師: 對(duì)后端以及前端開發(fā)好的項(xiàng)目進(jìn)行功能和性能測(cè)試,測(cè)試的過程中出現(xiàn)bug就會(huì)立即讓開發(fā)人員去修整,待整個(gè)項(xiàng)目幾乎沒有bug,以及性能達(dá)到項(xiàng)目實(shí)際的預(yù)期,就會(huì)準(zhǔn)備上線運(yùn)行。
測(cè)試分為兩種:
1.黑盒測(cè)試:
通過對(duì)軟件界面的功能進(jìn)行測(cè)試,測(cè)試一些能讓用戶看到的bug。(例如穿越火線的卡箱子等等...)
2.白盒測(cè)試:
對(duì)軟件進(jìn)行性能測(cè)試,例如每秒鐘能承受多少用戶量的訪問等...
'''
# 5、上線運(yùn)行
'''
運(yùn)維工程師(linux): 拿到前面整個(gè)項(xiàng)目編寫完的代碼,部署到服務(wù)器,上線運(yùn)行!
'''
程序架構(gòu)
程序目錄設(shè)計(jì)
# 接下來(lái)我們寫的功能都在按照這個(gè)文件目錄來(lái)寫,請(qǐng)認(rèn)真閱讀這個(gè)目錄所對(duì)應(yīng)的功能。
'''
- ATM
- conf 配置文件文件夾
- setting.py
- lib 公共方法文件夾
- common.py 公共方法文件
- interface 接口層文件夾
- user.py 用戶接口文件
- bank.py 銀行接口文件
- core 用戶功能文件夾
- src.py 視圖文件
- db 數(shù)據(jù)處理層文件夾
- db_handler.py 數(shù)據(jù)處理功能文件
- start.py 程序的入口文件,啟動(dòng)文件
- readme 程序的說(shuō)明文件
'''
程序模塊
# confs
## settings.py(主要存一些常量,主要是功能界面,商品列表,日志路徑,數(shù)據(jù)路徑)
import os
import sys
########
#功能展示#
#########
FUNC_MSG = {
'0': "注銷",
'1': "登錄",
'2': "注冊(cè)",
'3': "查看余額",
'4': "轉(zhuǎn)賬",
'5': "還款",
'6': "取現(xiàn)",
'7': "查看流水",
'8': "購(gòu)物",
'9': "購(gòu)物車",
}
SHOP_DIST = [
['餅干', 10],
['薯片', 10],
['火腿腸', 20],
['雪糕', 10],
['別墅', 1000000]
]
# LOG_PATH = os.path
ATM_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DB_PATH = os.path.join(ATM_PATH, 'db')
#core
## src.py(主界面,主要是和用戶交互的界面)
from libs import common
from db import db_handler
from interface import user
from interface import bank
from confs import settings
#設(shè)置一個(gè)字典類型的全局變量,用于判斷是否登錄
user_info = {
'user': None
}
# 注銷功能
def logout():
user_info['user'] = None # 將values值設(shè)置為空
print('注銷成功')
# 登錄模塊
def login():
count = 0 #計(jì)數(shù),連續(xù)三次注冊(cè)失敗,退出功能
print("歡迎來(lái)到登錄功能")
while True:
username, pwd = common.input_username_pwd() # 調(diào)用輸入接口,接收輸入信息
flag = common.check_user(username) # 調(diào)用核對(duì)用戶接口,驗(yàn)證用戶是否已經(jīng)存在
if not flag:
print('未注冊(cè)')
break
flag, msg = user.login_interface(username, pwd)
if flag:
user_info['user'] = username #登錄成功,賦值
print(user_info['user'])
print(msg)
break
else:
print(msg)
count += 1
if count == 3:
break
#注冊(cè)模塊
def register():
print("歡迎來(lái)到注冊(cè)模塊")
username, pwd = common.input_username_pwd()
flag = common.check_user(username) #先判斷是否存在
if flag:
print("無(wú)需注冊(cè),用戶已經(jīng)存在")
else:
msg = user.register_interface(username, pwd) # 調(diào)用注冊(cè)接口
print(msg)
@common.login_auth # 加語(yǔ)法糖,查看余額前先登錄
def check_extra():
print("歡迎來(lái)到查看余額模塊")
msg = user.check_extra(user_info.get('user')) # 調(diào)用查看余額接口
print(msg)
# 轉(zhuǎn)賬,需要有發(fā)起人,接收人和錢
@common.login_auth
def transfer():
print("歡迎來(lái)到轉(zhuǎn)賬模塊")
while True:
from_username = user_info.get('user')
to_username = input('請(qǐng)輸入你要轉(zhuǎn)賬的用戶名:')
flag = common.check_user(to_username) #先判斷用戶是否存在
if flag:
money = input("請(qǐng)輸入你要轉(zhuǎn)賬的金額").strip()
if not money.isdigit():
print("請(qǐng)輸入數(shù)字")
continue
money = int(money)
msg = bank.transfer_interface(from_username, to_username, money) #調(diào)用轉(zhuǎn)賬接口
print(msg)
break
print("用戶不存在")
@common.login_auth
#還款模塊
def repay():
print("歡迎來(lái)到還款模塊")
msg = bank.repay_interface(user_info['user']) #調(diào)用還款接口
print(msg)
@common.login_auth
#取現(xiàn)功能
def withdraw():
print("歡迎來(lái)到取現(xiàn)功能")
while True:
money = input("請(qǐng)輸入取現(xiàn)金額:")
if not money.isdigit():
print("輸入必須是數(shù)字")
continue
else:
money = int(money)
msg = bank.withdraw_interface(user_info['user'], money)#調(diào)用取現(xiàn)模塊
print(msg)
break
@common.login_auth
#查看流水模塊
def history():
print("歡迎來(lái)到查看流水模塊")
msg = bank.bank_flow_interface(user_info['user'])#調(diào)用查看流水模塊
print(msg)
@common.login_auth
#購(gòu)物模塊
def shopping():
print("歡迎來(lái)到購(gòu)物模塊")
while True:
for index, goods in enumerate(settings.SHOP_DIST): #用列表存儲(chǔ)的商品輸出,得到索引和有兩個(gè)元素的商品小列表
print(f'{index} {goods}')
goods_n = input("請(qǐng)輸入你要的商品編號(hào),按q退出:")
if goods_n == 'q':
break
if not goods_n.isdigit():
print("輸入有誤")
continue
goods_n = int(goods_n)
goods = settings.SHOP_DIST[goods_n] # 拿到的商品是一個(gè)有兩個(gè)值(第一個(gè)是商品名,第二個(gè)是價(jià)格)的列表
goods_name = goods[0] # 列表第一個(gè)元素是商品名
user_dic = db_handler.read_json(user_info['user']) # 拿到當(dāng)前用戶的數(shù)據(jù)字典
my_money = user_dic['extra'] # 把用戶字典中的查看額度取出來(lái)
if goods[-1] <= my_money: # 如果商品金額小于額度,可以買
if goods_name in user_dic['shop_car']:
user_dic['shop_car'][goods_name] += goods[-1] # 如果我的字典里面的購(gòu)物車字典有該商品,把價(jià)格加上去
else:
user_dic['shop_car'][goods_name] = goods[-1] # 如果我的字典里面的購(gòu)物車字典沒有該商品,把商品名加上去,價(jià)格加上去
db_handler.save_json(user_dic) # 做完修改要保存
print(f'{goods_name}加入購(gòu)物車成功')
else:
print("余額不足")
break
print(f"你的購(gòu)物車是{user_dic['shop_car']}") # 買完之后要打印一下
@common.login_auth
# 購(gòu)物車模塊
def shopping_car():
print("歡迎來(lái)到購(gòu)物車模塊")
while True:
user_dic = db_handler.read_json(user_info['user']) #用戶數(shù)據(jù)讀取
goods_dic = user_dic['shop_car'] # 拿到用戶數(shù)據(jù)字典的購(gòu)物車字典
cost_choice = input(f"購(gòu)物車是{goods_dic},是否選擇購(gòu)買y/n:") # 判斷是否購(gòu)買
if cost_choice == 'n':
break
elif cost_choice == 'y':
cost = sum(goods_dic.values()) # 把用戶購(gòu)物車字典中的值求和得到總價(jià)
if cost > user_dic['extra']:
print('余額不足,支付失敗')
break
user_dic['extra'] -= cost # 支付就是把用戶字典的額度減去總價(jià)
db_handler.save_json(user_dic) # 操作完了保存
print("支付成功")
break
def run():
FUNC_DICT = {
'0':logout,
'1':login,
'2':register,
'3':check_extra,
'4':transfer,
'5':repay,
'6':withdraw,
'7':history,
'8':shopping,
'9':shopping_car,
}
from confs.settings import FUNC_MSG
while True:
for k, v in FUNC_MSG.items(): # 把功能列表打印出來(lái)展示給用戶,包括序號(hào)和值
print(f'{k}: {v}')
func_choice = input("請(qǐng)輸入你需要的功能,按q退出>>>>>").strip()
if func_choice == 'q':
break
if not FUNC_DICT.get(func_choice):
print('輸入有誤,請(qǐng)重新輸入')
continue
func = FUNC_DICT.get(func_choice)
func()
if __name__ == '__main__':
run()
# db
## db_handler(數(shù)據(jù)處理模塊,主要是用戶存取數(shù)據(jù),格式是json)
import os
import json
from confs import settings
import sys
def save_json(user_dic): #存數(shù)據(jù),記得存的是字典,所有拼接名字的時(shí)候要把字典里面的用戶名取出來(lái)
user_path = os.path.join(settings.DB_PATH,
f'{user_dic.get("username")}.json') #拼接路徑
with open(user_path, 'w', encoding='utf8') as fw:
json.dump(user_dic, fw) # 存進(jìn)去,第一個(gè)參數(shù)是數(shù)據(jù),第二個(gè)是文件,就是把第一個(gè)數(shù)據(jù)存到第二個(gè)文件中
def read_json(username):# 讀數(shù)據(jù), 拼路徑,讀出來(lái)數(shù)據(jù)就可以了,記得返回
user_path = os.path.join(settings.DB_PATH, f'{username}.json')
if os.path.exists(user_path):
with open(user_path, 'r', encoding='utf8') as fr:
data = json.load(fr)
return data
#interface(主要就是銀行和用戶兩個(gè)接口)
## bank.py
from db import db_handler
def transfer_interface(from_username, to_username, money):# 轉(zhuǎn)賬接口,
from_user_dic = db_handler.read_json(from_username) # 讀當(dāng)前用戶數(shù)據(jù)
to_user_dict = db_handler.read_json(to_username) # 讀要轉(zhuǎn)賬用戶數(shù)據(jù)
my_money = from_user_dic['extra'] # 把用戶的錢單獨(dú)拿出來(lái)
if money > my_money:
return '錢不夠'
else:
from_user_dic['extra'] -= money # 我減錢
to_user_dict['extra'] += money # 對(duì)方加錢
msg_f = f'已向{to_username}轉(zhuǎn)賬{money}元' #記錄我的信息
msg_t = f'已收到{from_username}轉(zhuǎn)賬{money}元' #記錄對(duì)方信息
from_user_dic['bank_flow'].append(msg_f) #加我流水
to_user_dict['bank_flow'].append(msg_t) #加對(duì)方流水
db_handler.save_json(from_user_dic) #存數(shù)據(jù)
db_handler.save_json(to_user_dict) #存數(shù)據(jù)
return msg_f #返回操作信息
def repay_interface(username): #還款接口
while True:
money = input("請(qǐng)輸入你的還款金額:").strip()
if not money.isdigit():
print('請(qǐng)輸入數(shù)字')
else:
money = int(money)
user_dic = db_handler.read_json(username) #拿用戶數(shù)據(jù)
user_dic['extra'] += money # 字典里面加錢
db_handler.save_json(user_dic) #保存數(shù)據(jù)
return f'{username}已成功還款{money}' #返回信息
def withdraw_interface(username, money):# 取現(xiàn)接口
user_dic = db_handler.read_json(username) #拿用戶信息
if money*1.005 > user_dic['extra']:
return "錢不夠"
else:
user_dic['extra'] -= money*1.05 # 減錢
db_handler.save_json(user_dic) # 存數(shù)據(jù)
return f'{username}已成功取現(xiàn){money}元'
def bank_flow_interface(username): # 銀行流水信息
user_dic = db_handler.read_json(username) # 拿用戶數(shù)據(jù)
return user_dic['bank_flow'] #返回用戶字典里的流水
## user.py(用戶接口)
from db import db_handler
from confs import settings
import os
def register_interface(username, pwd): #注冊(cè)接口
#新生成的用戶的信息字典
user_dic = {
'username': username,
'pwd': pwd,
'extra': 1500000,
'bank_flow':[],
'shop_car':{}
}
db_handler.save_json(user_dic) #保存數(shù)據(jù)
return f'{username}注冊(cè)成功'
def login_interface(username, pwd): #登錄模塊
user_data = db_handler.read_json(username) # 拿數(shù)據(jù)
if user_data['pwd'] == pwd:
return True, '登錄成功'
else:
return False, '密碼輸入錯(cuò)誤'
def check_extra(username):# 查看余額接口
user_data = db_handler.read_json(username) # 拿數(shù)據(jù)
extra = user_data['extra']
return f'{username}查看了余額,余額為{extra}元'
# libs
## common.py(通用模塊)
import logging
import os
from db import db_handler
from confs import settings
import logging.config
def input_username_pwd():# 用戶輸入的模塊
username = input('請(qǐng)輸入用戶名>>>>').strip()
pwd = input("請(qǐng)輸入密碼>>>>").strip()
return username, pwd
def check_user(username): # 檢查用戶是否存在模塊
user_path = os.path.join(settings.DB_PATH, f'{username}.json') #拼接用戶路徑,判斷是否有該路徑
if os.path.exists(user_path):
return True
else:
return False
def login_auth(func): # 裝飾函數(shù),用于驗(yàn)證是否登錄,套用裝飾函數(shù)模板
from core import src
def inner(*args, **kwargs):
if src.user_info.get('user'):
res = func(*args, **kwargs)
return res
else:
print('未登錄,請(qǐng)去登錄!')
src.login()
return inner
#start.py (開始模塊,項(xiàng)目的起始點(diǎn))
from core import src
import os
import sys
sys.path.append(os.path.dirname(__file__)) #一定要把當(dāng)前路徑加入環(huán)境變量里
if __name__ == '__main__':
src.run()
注意點(diǎn)
1. 首先要把項(xiàng)目單獨(dú)打開,即作為根目錄。
2. 記住寫項(xiàng)目,尤其是需要導(dǎo)入模塊時(shí),一定要寫開始的函數(shù)(start.py),可以避免出現(xiàn)循環(huán)導(dǎo)入問題,造成一些變量傳入出錯(cuò)。
3. 有些時(shí)候Pycharm不能識(shí)別數(shù)據(jù)類型,就沒有提示,但不代表是錯(cuò)的,只要可以運(yùn)行就可以。
4. 保存的是字典,所以拼接路徑時(shí)要注意名字,取字典里key = username對(duì)應(yīng)的值作為名字
5. 登錄成功后把user_info['user']賦值為輸入的用戶名
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
