1. 程式人生 > 實用技巧 >ATM+購物車程式碼實現

ATM+購物車程式碼實現

conf:

settings.

# 存放配置資訊

import os

# 獲取專案的 根目錄路徑
BASE_PATH = os.path.dirname(
    os.path.dirname(__file__)
)


# goods_list檔案目錄路徑
GOODS_PATH = os.path.join(BASE_PATH, 'db', 'goods_list.json')

# 獲取 user_data 資料夾的 目錄路徑
USER_DATA_PATH = os.path.join(
    BASE_PATH, 'db', 'user_data'
)


"""
logging配置
""" # 定義三種日誌輸出格式 開始 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ '[%(levelname)s][%(message)s]' # 其中name為getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' id_simple_format
= '[%(levelname)s][%(asctime)s] %(message)s' # 定義日誌輸出格式 結束 # ****************注意1: log檔案的目錄 BASE_PATH = os.path.dirname(os.path.dirname(__file__)) logfile_dir = os.path.join(BASE_PATH, 'log') # print(logfile_dir) # ****************注意2: log檔名 logfile_name = 'log.log' # 如果不存在定義的日誌目錄就建立一個 if not os.path.isdir(logfile_dir): os.mkdir(logfile_dir)
# log檔案的全路徑 logfile_path = os.path.join(logfile_dir, logfile_name) LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, }, 'filters': {}, 'handlers': { # 列印到終端的日誌 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 列印到螢幕 'formatter': 'simple' }, # 列印到檔案的日誌,收集info及以上的日誌 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 儲存到檔案 'formatter': 'standard', 'filename': logfile_path, # 日誌檔案 'maxBytes': 1024 * 1024 * 5, # 日誌大小 5M 'backupCount': 5, 'encoding': 'utf-8', # 日誌檔案的編碼,再也不用擔心中文log亂碼了 }, }, 'loggers': { # logging.getLogger(__name__)拿到的logger配置 '': { 'handlers': ['default', 'console'], # 這裡把上面定義的兩個handler都加上,即log資料既寫入檔案又列印到螢幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, }, }

core:

admin.py

from core import src
from interface import admin_interface


# 新增使用者
def add_user():
    src.register()


# 修改使用者額度
def change_balance():
    while True:
        # 1.輸入修改的使用者名稱
        change_user = input('請輸入需要修改額度的使用者:').strip()

        # 2.輸入修改使用者額度
        money = input('請輸入需要修改的使用者額度:').strip()
        if not money.isdigit():
            continue

        # 3.呼叫修改額度介面
        flag, msg = admin_interface.change_balance_interface(
            change_user, money
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 凍結使用者
def lock_user():
    while True:
        # 1.輸入懂的使用者名稱
        to_lock_user = input('請輸入需要凍結的使用者:').strip()

        # 2.呼叫凍結使用者介面
        flag, msg = admin_interface.lock_user_interface(
            to_lock_user
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 解凍使用者
def unlock_user():
    while True:
        # 1.輸入懂的使用者名稱
        to_unlock_user = input('請輸入需要解凍的使用者:').strip()

        # 2.呼叫凍結使用者介面
        flag, msg = admin_interface.unlock_user_interface(
            to_unlock_user
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 管理員功能字典
admin_dic = {
    '1': add_user,
    '2': change_balance,
    '3': lock_user,
    '4': unlock_user
}


def admin_run():
    while True:
        print('''
        ======== 管理員功能 ========
        |       1.新增賬戶         |
        |       2.修改額度         |
        |       3.凍結賬戶         |
        |       4.解凍賬戶         |
        ========= THE END =========
            ''')
        choice = input('請輸入管理員功能編號(按q退出):').strip()

        if choice.lower() == 'q':
            break

        # 判斷功能編號是否存在
        if choice not in admin_dic:
            print('請輸入正確的功能編號!')
            continue

        # 呼叫用於選擇的功能函式
        admin_dic.get(choice)()  # admin_dic.get('1')() ---> add_user()

src.py

'''
使用者檢視層
'''
from interface import user_interface
from interface import bank_interface
from interface import shop_interface
from lib import common

# 全域性變數,記錄使用者是否已登入
login_user = None


# 1.註冊功能
def register():
    print('註冊功能執行中...')
    while True:
        # 1.讓使用者輸入使用者名稱與密碼進行校驗
        username = input('請輸入使用者名稱: ').strip()
        password = input('請輸入密碼: ').strip()
        re_password = input('請確認密碼: ').strip()
        # 可以輸入自定義的金額

        # 小的邏輯處理: 比如兩次密碼是否一致
        if password == re_password:
            # 2.呼叫介面層的註冊介面,將使用者名稱與密碼交給介面層來進行處理

            # res ---> (False, '使用者名稱已存在!')
            # res = user_interface.register_interface(
            # flag, msg ---> (flag---> False, msg --> '使用者名稱已存在!')

            # (True, 使用者註冊成功),  (False, 註冊失敗)
            flag, msg = user_interface.register_interface(
                username, password
            )

            # 3.根據flag判斷使用者註冊是否成功,flag控制break的結束
            if flag:
                print(msg)
                break

            else:
                print(msg)


# 2.登入功能
def login():
    print('登入功能執行中...')
    # 登入檢視
    while True:
        # 1.讓使用者輸入使用者名稱與密碼
        username = input('請輸入使用者名稱: ').strip()
        password = input('請輸入密碼: ').strip()

        # 2.呼叫介面層,將資料傳給登入介面
        # (True, f'使用者: [{username}] 登入成功!'),
        # (return False, '密碼錯誤'), (False, '使用者不存在,請重新輸入!')
        flag, msg = user_interface.login_interface(
            username, password
        )
        if flag:
            print(msg)
            # 記錄使用者資訊,已登入
            global login_user
            login_user = username
            break

        else:
            print(msg)


# 3.檢視餘額
@common.login_auth
def check_balance():
    print('檢視餘額功能執行中...')
    # 1.直接呼叫檢視餘額介面,獲取使用者餘額
    balance = user_interface.check_bal_interface(
        login_user
    )

    print(f'使用者[{login_user}] 賬戶餘額為: [{balance}元]!')


# 4.提現功能
@common.login_auth
def withdraw():
    print('提現功能執行中...')
    while True:
        # 1.讓使用者輸入提現金額
        input_money = input('請輸入提現金額: ').strip()

        # 2.判斷使用者輸入的金額是否是數字
        if not input_money.isdigit():
            print('請重新輸入')
            continue

        # 3.使用者提現金額,將提現的金額交付給介面層來處理
        flag, msg = bank_interface.withdraw_interface(
            login_user, input_money
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 5.還款功能
@common.login_auth
def repay():
    print('還款功能執行中...')
    while True:
        # 1.讓使用者輸入還款金額
        input_money = input('請輸入還款金額: ').strip()

        # 2.判斷使用者輸入的金額是否是數字
        if not input_money.isdigit():
            print('請重新輸入')
            continue

        input_money = int(input_money)
        if input_money > 0:
            # 3.使用者還款金額,將還款的金額交付給介面層來處理
            flag, msg = bank_interface.repay_interface(
                login_user, input_money
            )

            if flag:
                print(msg)
                break
            else:
                print(msg)

        else:
            print('輸入的金額不能小於等於0!')


# 6.轉賬功能
@common.login_auth
def transfer():
    print('轉賬功能執行中...')
    '''
    1.接收使用者輸入的 轉賬目標使用者
    2.接收使用者輸入的 轉賬金額
    '''
    while True:

        # 1.讓使用者輸入轉賬使用者和金額
        to_user = input('請輸入轉賬目標使用者:').strip()
        money = input('請輸入轉賬金額:').strip()

        # 2.判斷使用者輸入金額是否是數字或者>0
        if not money.isdigit():
            print('請輸入正確的金額!')
            continue

        money = int(money)

        if money > 0:
            # 3.呼叫轉賬介面
            flag, msg = bank_interface.transfer_interface(
                # 當前使用者,目標使用者,轉賬金額
                login_user, to_user, money
            )
            if flag:
                print(msg)
                break
            else:
                print(msg)

        else:
            print('請輸入正確的金額!')


# 7.檢視流水
@common.login_auth
def check_flow():
    print('檢視流水功能執行中...')
    flow_list = bank_interface.check_flow_interface(
        login_user
    )

    if flow_list:
        for flow in flow_list:
            print(flow)

    else:
        print('當前使用者沒有流水!')


# 8.購物功能
@common.login_auth
def shopping():
    print('購物功能執行中...')
    while True:
        # 獲取全部商品資訊並列印
        goods_dic = shop_interface.get_goods_interface()
        print('=================== Welcome To Hardware World ===================\n')
        for number, goods_info in goods_dic.items():
            print(f'| 編號:[{number}] 商品名:[{goods_info.get("goods_name")}] 價格:[{goods_info.get("price")}]元')
        print('')
        print("============================ THE END ============================")
        goods_id = input("請輸入要購買的商品編號(按q返回上一層):").strip()
        if goods_id.lower() == 'q':
            break
        count = input("請輸入購買的數量:").strip()
        if not count.isdigit() or count == '0':
            print("輸入錯誤")
            continue
        if goods_id not in goods_dic:
            print('該商品不存在')
            continue
        # 將對應編號的商品加入購物車
        shop_interface.add_shop_car_interface(goods_dic[goods_id], int(count))
        print(f"{goods_dic[goods_id]['goods_name']}已加入購物車,請到購物車結算")


# 作業:清空購物車功能
# 清空購物車
def clean_shop_car():
    inp_clear = input("是否清空購物車?(Y/N):").strip()
    if inp_clear.lower() != 'y':
        print("清空購物車失敗,使用者取消操作")
        return False
    msg = shop_interface.clean_shop_car_interface(login_user)
    print(msg)
    return True


# 9.檢視購物車
@common.login_auth
def check_shop_car():
    print('檢視購物車功能執行中...')
    shop_car_dic = shop_interface.check_shop_car_interface(login_user)
    while True:
        shop_id = 0
        print("========================  購物車內容  =========================")
        print('')
        for goods_name, goods_info in shop_car_dic.items():
            print(f'| ID:[{shop_id}] 商品名 {goods_name} 數量 {goods_info.get("count")}個 總價 {goods_info.get("total")}元')
            shop_id += 1
        print('')
        print("========================== THE END  ==========================")
        pay_id = input("請選擇需要付款的商品ID(按q離開購物車,按c清空購物車):").strip()
        if pay_id.lower() == 'c':
            flog = clean_shop_car()
            if flog:
                return
            continue
        if pay_id.lower() == 'q':
            break
        if int(pay_id) not in range(len(shop_car_dic)):
            print("商品不存在")
            continue
        # 獲取選擇付款商品的商品資訊並列印
        buy_goods_name = list(shop_car_dic.keys())[int(pay_id)]
        buy_goods_count = shop_car_dic[buy_goods_name].get('count')
        buy_goods_total = shop_car_dic[buy_goods_name].get('total')
        print(f"您將付款的商品為:{buy_goods_name},數量為:{buy_goods_count}個, 總價為:{buy_goods_total}元")
        # 付款
        inp_buy = input("確認付款(Y/n):").strip()
        if inp_buy.lower() == 'y':
            flog, msg = shop_interface.payment_interface(login_user, buy_goods_name, buy_goods_total)
            if flog:
                print(msg)
                break
            else:
                print('msg')
        print("付款失敗,使用者取消支付")


@common.login_auth
# 10.管理員功能
def admin():
    print('管理員功能執行中...')
    from core import admin
    if login_user == 'admin':
        admin.admin_run()
    else:
        print('你沒有資格!')


# 建立函式功能字典
func_dic = {
    '1': register,
    '2': login,
    '3': check_balance,
    '4': withdraw,
    '5': repay,
    '6': transfer,
    '7': check_flow,
    '8': shopping,
    '9': check_shop_car,
    '10': admin,
}


# 檢視層主程式
def run():
    while True:
        print('''
        ======= ATM + 購物車 =======
        |       1.註冊功能          |
        |       2.登入功能          |
        |       3.檢視餘額          |
        |       4.提現功能          |
        |       5.還款功能          |
        |       6.轉賬功能          |
        |       7.檢視流水          |
        |       8.購物功能          |
        |       9.檢視購物車         |
        |       10.管理員功能        |
        =========== END ===========
        ''')

        choice = input('請輸入功能編號: ').strip()

        if choice not in func_dic:
            print('請輸入正確的功能編號!')
            continue

        func_dic.get(choice)()  # func_dic.get('1')() ---> register()

db:

userdata

用於存放使用者資訊

db_handler.py

'''
資料處理層
    專門用於處理資料的
'''

import os
import json
from conf import settings


# 檢視資料
def select(username):
    # 1.接收介面層傳過來的username使用者名稱,拼接使用者json檔案路徑
    user_path = os.path.join(
        settings.USER_DATA_PATH, f'{username}.json'
    )

    # 2.校驗使用者json檔案是否存在
    if os.path.exists(user_path):
        # 3.開啟資料,並返回給介面層
        with open(user_path, mode='rt', encoding='UTF-8') as f:
            user_dic = json.load(f)
            return user_dic


# 儲存資料(新增新資料或者更新資料)
def save(user_dic):
    # 1.拼接使用者的資料字典
    username = user_dic.get('username')

    user_path = os.path.join(
        settings.USER_DATA_PATH, f'{username}.json'
    )
    # 2.儲存使用者資料
    with open(user_path, mode='wt', encoding='UTF-8') as f:
        # ensure_ascii=False讓檔案中的中文資料,顯示更美觀
        json.dump(user_dic, f, ensure_ascii=False)


# 獲取商品資料
def select_goods():
    with open(settings.GOODS_PATH, mode='rt', encoding='UTF-8') as f:
        goods_dic = json.load(f)
        return goods_dic

goods_list.json

{
  "0": {"goods_name": "logitech-G703", "price": 549},
  "1": {"goods_name": "Antec-HCG750W", "price": 799},
  "2": {"goods_name": "ROG-M11E-Z390", "price": 6999},
  "3": {"goods_name": "G.SKILL-16G-RGB", "price": 769},
  "4": {"goods_name": "Intel-i9-9900KF", "price": 3599},
  "5": {"goods_name": "SAMSUNG-970Pro-1T", "price": 2699},
  "6": {"goods_name": "Segotep-K1(ATX3.0)", "price": 499},
  "7": {"goods_name": "ROG-RTX-2080Ti-11G", "price": 11999},
  "8": {"goods_name": "CHERRY-MX6.0-BLUE RGB", "price": 1399},
  "9": {"goods_name": "ASUS-ROG-360mm-RGB Aura", "price": 2299},
  "10": {"goods_name": "SAMSUNG-27inch-Space-2K/144Hz", "price": 3499}
}

interface:

admin_interface.py

from db import db_handler
from lib import common

# 根據不同的介面型別傳入不同的日誌物件
admin_logger = common.get_logger(log_type='admin')


# 修改額度介面
def change_balance_interface(username, money):
    user_dic = db_handler.select(username)

    if user_dic:
        # 修改額度
        user_dic['balance'] = int(money)

        # 儲存修改後使用者的資料
        db_handler.save(user_dic)
        msg = f'管理員修改使用者: [{username}]額度修改成功!'
        admin_logger.info(msg)

        return True, '額度修改成功!'

    return False, '該使用者不存在!'


# 凍結介面
def lock_user_interface(username):
    user_dic = db_handler.select(username)

    if user_dic:
        if not user_dic['locked']:
            # 將locked的預設值改為True
            user_dic['locked'] = True
            db_handler.save(user_dic)

            msg = f'使用者:[{username}]凍結成功!'
            admin_logger.info(msg)
            return True, msg
        else:
            return False, '該使用者已被凍結,無需再次凍結!'

    return False, '凍結使用者不存在!'


# 解凍介面
def unlock_user_interface(username):
    user_dic = db_handler.select(username)

    if user_dic:
        if user_dic['locked']:
            # 將locked的預設值改為False
            user_dic['locked'] = False
            db_handler.save(user_dic)

            msg = f'使用者:[{username}]解凍成功!'
            admin_logger.info(msg)
            return True, msg
        else:
            return False, '該使用者未被凍結,無需解凍!'

    return False, '解凍使用者不存在!'

bank_interface.py

# 銀行相關業務的介面
import time
from db import db_handler
from lib import common

# 根據不同的介面型別傳入不同的日誌物件
bank_logger = common.get_logger(log_type='bank')

# 記錄當前操作的時間
start_time = time.strftime('%Y-%m-%d %H:%M:%S')


# 提現介面(手續費5%)
def withdraw_interface(username, money):
    # 1.先獲取使用者字典
    user_dic = db_handler.select(username)

    # 賬戶中的金額
    balance = int(user_dic.get('balance'))

    # 提現本金 + 手續費
    money2 = int(money) * 1.05  # ---> float

    # 判斷使用者金額是否足夠
    if balance >= money2:
        # 2.修改使用者字典中的金額
        balance -= money2

        user_dic['balance'] = balance

        # 3.記錄流水
        flow = f'{start_time} 使用者:[{username}] 提現金額:[{money}元]成功,手續費為: [{money2 - float(money)}元]'
        user_dic['flow'].append(flow)

        # 4.再儲存資料,或更新資料
        db_handler.save(user_dic)
        bank_logger.info(flow)
        return True, flow

    return False, '提現金額不足,請重新輸入!'


# 還款介面(無需手續費)
def repay_interface(username, money):
    # 1.先獲取使用者字典
    user_dic = db_handler.select(username)

    # 2.直接做加錢操作
    # user_dic['balance'] ==> int
    user_dic['balance'] += money
    new_money = user_dic['balance']

    # 3.記錄流水
    flow = f'{start_time} 使用者:[{username}]  還款:[{money}]成功!'
    user_dic['flow'].append(flow)

    # 4.呼叫資料處理層,將修改後的資料更新
    db_handler.save(user_dic)
    bank_logger.info(f'{start_time} 使用者:{username} 還款成功,還款金額:[{money}]元')
    return True, flow


# 轉賬介面
def transfer_interface(login_user, to_user, money):
    '''
    1.獲取“當前使用者”資料
    2.獲取“目標使用者”資料
    3.獲取“轉賬金額”資料
    :return:
    '''

    # 1.獲取“當前使用者”字典
    login_user_dic = db_handler.select(login_user)

    # 2.獲取“目標使用者”字典
    to_user_dic = db_handler.select(to_user)

    # 3.判斷目標使用者是否存在
    if not to_user_dic:
        bank_logger.warning(f'{start_time} 使用者:[{login_user}] 轉賬失敗,使用者:[{to_user}]不存在')
        return False, '目標使用者不存在!'

    # 4.若使用者存在,則判斷“當前使用者轉賬金額”是否足夠
    if login_user_dic['balance'] >= money:
        # 5.若足夠,則開始給目標使用者轉賬
        # 5.1.給當前使用者的資料,做減錢操作
        login_user_dic['balance'] -= money

        # 5.2.給目標使用者的資料,做加錢操作
        to_user_dic['balance'] += money

        # 5.3.記錄當前使用者 與 目標使用者 的流水
        # 當前使用者流水
        login_user_flow = f'{start_time} 使用者:[{login_user}] 給 使用者:[{to_user}] 轉賬:[{money}元]'
        login_user_dic['flow'].append(login_user_flow)

        # 目標使用者流水
        to_user_flow = f'{start_time} 使用者:[{to_user}] 接收 使用者:[{login_user}] 轉賬:[{money}元]'
        to_user_dic['flow'].append(to_user_flow)

        # 6.呼叫資料處理層的save功能,儲存使用者資料
        # 6.1.儲存當前使用者資料
        db_handler.save(login_user_dic)

        # 6.2.儲存目標使用者資料
        db_handler.save(to_user_dic)
        bank_logger.info(f'{login_user} 轉賬成功,對方使用者:[{to_user}],轉賬金額[{money}]元')
        return True, login_user_flow

    else:
        bank_logger.warning(f'{start_time} 使用者:[{login_user}] 轉賬失敗,餘額不足')
        return False, '餘額不足,轉賬失敗!'


# 檢視流水介面
def check_flow_interface(login_user):
    user_flow_dic = db_handler.select(login_user)
    return user_flow_dic['flow']


# 支付介面
def pay_interface(login_user, cost):
    user_dic = db_handler.select(login_user)

    # 判斷使用者金額是否足夠
    if user_dic.get('balance') >= cost:
        # 扣費
        user_dic['balance'] -= cost

        # 記錄消費流水
        flow = f'使用者消費金額:[{cost}元]'
        user_dic['flow'].append(flow)

        # 儲存資料
        db_handler.save(user_dic)

        # return True 或者 return False 交給購物介面來操作
        return True

    return False

shop_interface.py

# 商品購買介面
import time
from db import db_handler
from lib import common

# 根據不同的介面型別傳入不同的日誌物件log_type=
shop_logger = common.get_logger(log_type='shop')

start_time = time.strftime('%Y-%m-%d %H:%M:%S')


# 獲取商品資訊介面
def get_goods_interface():
    goods_dic = db_handler.select_goods()
    return goods_dic


# 商品準備結算介面
def payment_interface(login_user, buy_goods_name, buy_goods_total):
    user_dic = db_handler.select(login_user)
    # 獲取使用者購物車字典
    shop_car_dic = user_dic['shop_car']
    # 獲取使用者餘額
    balance = user_dic['balance']
    if buy_goods_total > balance:
        shop_logger.warning(f'使用者:[{login_user}] 支付失敗,餘額不足')
        return False, '支付失敗,餘額不足'
    balance -= buy_goods_total
    shop_car_dic.pop(buy_goods_name)
    # 修改使用者餘額
    user_dic['balance'] = balance
    # 刪除已付款商品
    user_dic['shop_car'] = shop_car_dic
    # 增加流水
    user_dic['flow'].append(f'{start_time} 使用者:[{login_user}] 購買商品:[{buy_goods_name}] 消費:[{buy_goods_total}]元')
    # 更新使用者資料
    db_handler.save(user_dic)
    shop_logger.info(f'{start_time} 使用者:{login_user} 付款成功! 商品:[{buy_goods_name}] 等待發貨')
    return True, '支付成功'


# 購物車新增介面
def add_shop_car_interface(goods_dic, count):
    from core import src
    total = goods_dic["price"] * count
    goods_name = goods_dic['goods_name']
    shop_dic = {
        f"{goods_name}": {"count": count, "total": total}
    }
    user_dic = db_handler.select(src.login_user)
    # 使用者購物車內商品資訊
    shop_car_dic = user_dic['shop_car']
    # 如果購物車為空則直接加入
    if user_dic.get('shop_car') == {}:
        user_dic['shop_car'] = shop_dic
    else:
        # 如果商品不在購物車中則直接加入
        if goods_name not in shop_car_dic:
            shop_car_dic.update(shop_dic)
            user_dic['shop_car'] = shop_car_dic
        else:
            # 商品在購物車中,修改商品數量以及總價
            user_dic['shop_car'].get(goods_name)['count'] += count
            user_dic['shop_car'].get(goods_name)['total'] += total
    db_handler.save(user_dic)
    shop_logger.info(f'{start_time} 使用者:{src.login_user} 新增商品:[{goods_name}]至購物車成功')

    return True, '新增購物車成功!'


# 獲取購物車資訊介面
def check_shop_car_interface(login_user):
    user_dic = db_handler.select(login_user)
    shop_car_dic = user_dic["shop_car"]
    shop_logger.info(f'{start_time} 使用者:[{login_user}] 檢視購物車')
    return shop_car_dic


# 清空購物車
def clean_shop_car_interface(login_user):
    user_dic = db_handler.select(login_user)
    user_dic['shop_car'] = {}
    db_handler.save(user_dic)
    shop_logger.info(f'{start_time} 使用者:[{login_user}] 清空了購物車')
    return '清空購物車成功'

userface_interface.py

# 邏輯介面層
#     使用者介面

from db import db_handler
from lib import common

# 根據不同的介面型別傳入不同的日誌物件
user_logger = common.get_logger(log_type='user')


# 註冊介面
def register_interface(username, password, balance=15000):
    # 2.檢視使用者是否存在
    # 2.1.呼叫 資料處理層 中的 select函式,會返回 使用者字典 或 None
    user_dic = db_handler.select(username)

    # {user: user, pwd: pwd...}   or  None
    # 若使用者存在,則return,告訴使用者重新輸入
    if user_dic:
        # return (False, '使用者名稱已存在!')
        return False, '使用者名稱已存在!'

    # 3.若使用者不存在,則儲存使用者資料
    # 做密碼加密
    password = common.get_pwd_md5(password)

    if username == 'admin':
        user_dic = {
            'username': username,
            'password': password,
            'balance': balance,
            # 用於記錄使用者流水的列表
            'flow': [],
            # 用於記錄使用者購物車
            'shop_car': {},
            # locked:用於記錄使用者是否被凍結
            # False: 未凍結   True: 已被凍結
            'is_admin': True
            }

    # 3.1.組織使用者的資料的字典資訊
    user_dic = {
        'username': username,
        'password': password,
        'balance': balance,
        # 用於記錄使用者流水的列表
        'flow': [],
        # 用於記錄使用者購物車
        'shop_car': {},
        # locked:用於記錄使用者是否被凍結
        # False: 未凍結   True: 已被凍結
        'locked': False,
        'is_admin': False

    }

    # 3.2.儲存資料
    db_handler.save(user_dic)
    msg = f'{username} 新使用者註冊成功, 初始額度為:{balance}元'

    # 3.3.記錄日誌
    user_logger.info(msg)

    return True, msg


# 登入介面
def login_interface(username, password):
    # 1.先檢視當前使用者資料是否存在
    # {使用者資料字典}  or  None
    user_dic = db_handler.select(username)

    # 2.判斷使用者是否存在
    if user_dic:
        # 若有凍結使用者,則需要判斷是否被鎖定
        if user_dic.get('locked'):
            return False, '當前使用者已被凍結,好好反省一下自己做了什麼!'

        # 給使用者輸入的密碼做一次加密
        password = common.get_pwd_md5(password)

        # 3.校驗密碼是否一致
        if password == user_dic.get('password'):
            msg = f'使用者: [{username}] 登入成功!'
            user_logger.info(msg)
            return True, msg

        else:

            msg = f'使用者: [{username}]密碼錯誤!'
            user_logger.warn(msg)
            return False, msg

    msg = f'使用者: [{username}]使用者不存在,請重新輸入!!'
    return False, msg


# 檢視餘額介面
def check_bal_interface(username):
    user_dic = db_handler.select(username)
    return user_dic['balance']

lib:

common.py

# 存放公共方法

import hashlib
from conf import settings
import logging.config


# md5加密
def get_pwd_md5(password):
    md5_obj = hashlib.md5()
    md5_obj.update(password.encode('UTF-8'))
    salt = '急急如律令!'
    md5_obj.update(salt.encode('UTF-8'))
    return md5_obj.hexdigest()


# 登入認證裝飾器
def login_auth(func):
    from core import src

    def inner(*args, **kwargs):
        if src.login_user:
            res = func(*args, **kwargs)
            return res
        else:
            print('未出示證明,無法享受美好的功能服務!')
            src.login()

    return inner


# 新增日誌功能: (日誌功能在介面層 使用)
def get_logger(log_type):  # log_type ---> user
    '''
    :param log_type: 比如是 user日誌,bank日誌,購物商城日誌
    :return:
    '''
    # 1.載入日誌配置資訊
    logging.config.dictConfig(
        settings.LOGGING_DIC
    )

    # 2.獲取日誌物件
    logger = logging.getLogger(log_type)

    return logger

log:

log.log

存放日誌資訊 readme:

readme:

專案說明書
專案:ATM + 購物車

專案需求:
1.額度 15000或自定義
2.實現購物商城,買東西加入 購物車,呼叫信用卡介面結賬
3.可以提現,手續費5%
4.支援多賬戶登入
5.支援賬戶間轉賬
6.記錄每月日常消費流水
7.提供還款介面
8.ATM記錄操作日誌
9.提供管理介面,包括新增賬戶、使用者額度,凍結賬戶等。。。
10.使用者認證用裝飾器
-開發軟體的公司:幫甲方開發軟體的

-客戶:指的是某些服務行業的客戶,需要找人開發某些軟體(甲方)

-使用者:甲方的軟體已經開始上線,提供給我們(使用者)使用

一個專案是如何從無到有
1.需求分析

需求文件:

額度 15000或自定義  ------------->1.註冊功能 (15000預設的額度)
實現購物商城,買東西加入 購物車,呼叫信用卡介面結賬 ------> 2.購物車功能 3.支付功能
可以提現,手續費5% ---->4.提現功能
支援多賬戶登入  ---->5.登入功能
支援賬戶間轉賬 ----->6.轉賬功能
記錄每月日常消費流水 ----->7.記錄消費流水(設定金額)
提供還款介面----->8.還款功能
ATM記錄操作日誌----->9.記錄軟體使用日誌功能
提供管理介面,包括新增賬戶、使用者額度,凍結賬戶等。。。----->10.管理員功能
使用者認證用裝飾器----->11.登入認證裝飾器
提取出來的功能:

1.註冊功能
2.購物車功能
3.支付功能
4.提現功能
5.登入功能
6.轉賬功能
7.'記錄'消費流水
8.還款功能
9.記錄日誌功能
10.管理員功能
11.登入認證裝飾器
提供給使用者選擇與操作的功能:

1.註冊功能
2.登入功能
3.檢視餘額
4.提現功能
5.還款功能
6.轉賬功能
7.檢視流水
8.購物功能
9.檢視購物車
10.管理員功能
2.軟體的架構設計

1、程式設計的好處
    1) 思路清晰
    2) 不會出現寫一半程式碼時推翻重寫
    3) 方便自己或以後的同事更好維護
2、三層架構設計的好處
    1) 把每個功能都分層三部分,邏輯清晰
    2) 如果使用者更換不同的使用者介面或不同,
    的資料儲存機制都不會影響介面層的核心
    邏輯程式碼,擴充套件性強。
    3) 可以在介面層,準確的記錄日誌與流水。
三層架構:

使用者檢視層(第一層):提供給使用者選擇的功能介面

職責:用於與使用者進行互動,接受使用者輸入的資料,交給介面層進行處理,介面層最終會將一個結果給使用者檢視層,展示給使用者看的
邏輯介面層(第二層):所有核心邏輯都放在介面中,提供給使用者檢視層來使用(呼叫)的

登入介面:
     接收使用者檢視層傳遞過來的引數,根據邏輯判斷呼叫資料層加以處理,並返回一個結果給使用者檢視層。
    1.檢視使用者名稱,是否存在,若存在,則繼續校驗密碼,若不存在,則返回結果給使用者檢視層,讓使用者重新輸入
    2.若使用者存在,做密碼的校驗,若密碼正確返回登入給使用者檢視層
職責:相當於使用者檢視層與資料處理層的橋樑。專門負責接收使用者檢視層傳過來的資料,並進行'核心的邏輯'校驗過程中,回去訪問'資料層'進行資料的增刪改查,通過或不通過後會返回一個結果給使用者檢視層進行展示
資料處理層:(第三層):接受介面層傳過來的引數,返回相應的資料給介面層,或者儲存資料,做資料的處理

- 儲存資料  save()
- 檢視資料  select()
- 更新資料  update()
- 刪除資料  delete()
根據使用者名稱查詢資料,若有則返回使用者資料給介面層,若沒有則預設返回None
3.分任務開發

多個人同步去開發專案,高效開發專案
- 不同的崗位:
    - UI介面設計:
        - 設計軟體的佈局,會分局軟體的外觀切成一張張圖片。
    
    - 前端:
        - 拿到UI交給他的圖片,然後去搭建網頁面。
        - 設計一些頁面中,哪些位置需要接收資料,需要進行資料互動。
    
    - 後端:
        - 直接核心的業務邏輯,排程資料庫進行資料的增刪查改。
    
    - 測試:
        - 會給程式碼進行全面測試,比如壓力測試,介面測試(CF卡箱子)。
    
    - 運維:
        - 部署專案。
4.測試

    4.1手動測試
    4.2自動化測試
5.上線執行

統計程式碼
file  ==>  settings  ==>  Plugins  ==>  Statistic  ==>  Installer

三層架構圖

start.py:

'''
程式的入口
'''
import sys
import os

#新增直譯器的環境變數
sys.path.append(
    os.path.dirname(__file__)
)

from core import src
#開始執行專案函式
if __name__ == '__main__':

# 1.先執行使用者檢視層
    src.run()