项目: ATM+购物车

ATM+购物车

项目文件:

介绍

以下为文件夹层次和内容:


readme.md

1. 需求

模拟银行取款 + 购物全过程

1.注册

2.登录

3.提现

4.还款

5.转账

6.查看余额

7.查看购物车

8.查看消费流水

9.添加购物车

10.记录日志

11.用装饰器判断用户状态

2. 编程思想

分层架构

  • 用户层: 实现用户交互. 接收用户想完成的操作
  • 接口层: 将用户操作封装成方法. 调用数据库并对数据库进行修改. 记录用户行为
  • 数据库层: 通过接口层的调用将用户数据返回给前两层进行操作. 将用户数据保存
  • 日志: 将get_logger封装成方法放置在接口层. 记录用户每一次的操作

3.总结

  1. 编程的思想值得学习. 一个项目第一步主要就是确定架构. 然后向各个模块内填写代码
  2. 各个模块之间相互调用一定要逻辑清晰. 否则容易出现bug
  3. 该项目为面向过程编程. 在打下python基础的同时为面向对象编程做基础

bin

start.py

import os
import sys


path = os.path.dirname(os.path.dirname(__file__))  # 取根目录
sys.path.append(path)  # 添加根目录
from core.user_command import run  # 导包


if __name__ == '__main__':
    # 程序入口
    run()

conf

setting.py

import os


base_path = os.path.dirname(os.path.dirname(__file__))
db_path = os.path.join(base_path, "db")
log_path = os.path.join(base_path, "log")
user_dic = {"name": None}  # 加上用户登录状态

# -*- encoding:utf-8 -*-
# @time: 2022/6/1 22:57
# @author: Maxs_hu


"""
logging配置
"""

# 定义三种日志输出格式 开始
# standard_format = '%(asctime)s - %(filename)s:%(lineno)d - %(levelname)s - %(message)s'
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'

simple_format = '%(asctime)s - %(levelname)s - %(message)s'

id_simple_format = '[%(asctime)s] %(message)s'


# log文件的全路径
logfile1_path = os.path.join(log_path, "log.log")
logfile2_path = os.path.join(log_path, "another.log")

# log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'formatter1': {
            'format': standard_format
        },
        'formatter2': {
            'format': simple_format
        },
    },
    'filters': {},
    'handlers': {
        # 打印到终端的日志
        'sm': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'formatter1'
        },
        # 打印到文件的日志,收集info及以上的日志
        'h1': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'formatter': 'formatter1',
            'filename': logfile1_path,  # 日志文件
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
        'h2': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'formatter': 'formatter2',
            'filename': logfile2_path,  # 日志文件
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },

    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置
        'logger1': {
            'handlers': ['h1', 'h2', 'sm'],
            'level': 'DEBUG',
            'propagate': False,  # 向上(更高level的logger)传递
        },
    },
}

core

user_command.py

from interface import user, bank, shop
from conf.setting import user_dic  # 用户登录状态
from lib.common import login_auth


def register():
    while True:
        print("***注册***")
        username = input("请输入用户名:").strip()
        password = input("请输入密码:").strip()
        # 调用接口
        state, msg = user.register_interface(username, password)
        if state:
            print(msg)
            user_dic['name'] = username
            break
        else:
            print(msg)


def login():
    while True:
        print("***登录***")
        username = input("请输入用户名:").strip()
        password = input("请输入密码:").strip()
        state, msg = user.login_interface(username, password)
        if state:
            user_dic["name"] = username
            print(msg)
            break
        else:
            print(msg)


@login_auth  # check_balance = login_auth(check_balance)
def check_balance():
    print("***查看余额***")
    balance = bank.balance_interface(user_dic['name'])
    print(balance)


@login_auth
def transfer():
    while True:
        print("***转账***")
        username = user_dic['name']
        to_username = input("请输入转账对象用户名:").strip()
        amount = int(input("请输入转账金额:").strip())
        state, msg = user.transfer_interface(username, to_username, amount)
        if state:
            print(msg)
            break
        else:
            print(msg)


@login_auth
def repay():
    while True:
        print("***还款***")
        username = user_dic['name']
        amount = int(input("请输入还款金额:").strip())
        state, msg = user.repay_interface(username, amount)
        if state:
            print(msg)
            break
        else:
            print(msg)


@login_auth
def withdraw():
    while True:
        print("***取款***")
        username = user_dic['name']
        amount = int(input("请输入取款金额:").strip())
        state, msg = bank.withdraw_interface(username, amount)
        if state:
            print(msg)
            break
        else:
            print(msg)


@login_auth
def check_records():
    while True:
        print("***查看流水***")
        username = user_dic['name']
        msg = user.check_interface(username)
        if msg:
            print(msg)
            break
        else:
            print("暂无流水")
            break


@login_auth
def shopping():
    print("***购物***")
    username = user_dic['name']
    goods_list = [
        ["coffee", 20],
        ["car", 100000],
        ["pen", 5],
        ["ice_cream", 25],
        ["mac_pro", 1000]
    ]
    shopping_cart = {}  # {"name": {"price": price, "count": count}, ......}
    cost = 0
    count = 0
    # 查看账户
    balance = bank.balance_interface(user_dic['name'])
    # 开始购物
    while True:
        for i, goods in enumerate(goods_list):
            print(i + 1, goods)
        choice = input("请输入你要购买的商品编号(buy退出并购买, q只退出不购买):").strip()
        if choice.isdigit():
            choice = int(choice)
            if 0 < choice <= len(goods_list) + 1:
                goods_price = goods_list[choice - 1][1]
                goods_name = goods_list[choice - 1][0]
                if goods_price <= balance:
                    count += 1  # 商品数量
                    balance -= goods_price
                    cost += goods_price
                    shopping_cart[goods_name] = {"price": goods_price, "count": count}
                    print("添加购物车成功")
                else:
                    print("余额不足")
            else:
                print("商品不存在")
        elif choice == "q":
            state, msg = shop.save_shopping(username, shopping_cart)
            if state:
                print(msg)
                break
            else:
                print(msg)
                break
        elif choice == 'buy':
            # 调用银行接口
            state, msg = shop.shopping_interface(username, cost, shopping_cart)
            if state:
                print(msg)
                break
            else:
                print(msg)
                break
        else:
            print("请输入数字")


@login_auth
def check_shopping_cards():
    while True:
        print("***查看购物车***")
        username = user_dic['name']
        res = shop.check_shopping_interface(username)
        if res:
            print(res)
            break
        else:
            print("购物车为空")
            break


func_dic = {
    "1": register,
    "2": login,
    "3": check_balance,
    "4": transfer,
    "5": repay,
    "6": withdraw,
    "7": check_records,
    "8": shopping,
    "9": check_shopping_cards
}


def run():
    while True:
        print("""请选择需要办理的业务:
1.注册
2.登录
3.查看余额
4.转账
5.还款
6.取款
7.查看消费流水
8.购物
9.查看购物车
        """)

        choice = input("请输入数字实现功能(q退出):").strip()
        if choice == 'q':
            print("欢迎下次光临")
            break
        if choice not in func_dic:
            continue
        func_dic[choice]()  # 加上括号直接调用

db

db_handle.py

import os
from conf import setting
import json


# 查数据
def select(username):
    db_path = setting.db_path
    user_info_path = os.path.join(db_path, "%s.json" % username)  # 创建json地址
    # 判断是否存在该用户
    if os.path.exists(user_info_path):
        with open(user_info_path, 'r', encoding='utf-8') as f:
            return True, json.load(f)
    else:
        return False, "该用户不存在"


# 存数据
def save(user_dic):
    db_path = setting.db_path
    user_path = os.path.join(db_path, "%s.json" % user_dic["username"])
    # 将用户信息存到用户地址里面
    with open(user_path, "w", encoding='utf-8') as f:
        json.dump(user_dic, f)  # 将字典转化成json格式
        f.flush()  # 将数据强行刷入硬盘

interface

bank.py

from db.db_handle import select
from db.db_handle import save
from lib import common

bank_logger = common.get_logger("bank")


def balance_interface(username):
    state, msg = select(username)
    if state:
        bank_logger.info("查看余额")
        return msg["balance"]
    else:
        return "出现未知错误"


def withdraw_interface(username, amount):
    state, msg = select(username)
    amount = amount * 1.08  # 加上手续费
    if state:
        if msg['balance'] > amount:
            msg['balance'] -= amount
            msg['bank_flow'].append("取款%s" % amount)
            save(msg)
            bank_logger.info("取款")
            return True, "取款成功"
        else:
            return False, "余额不足"
    else:
        return False, msg


def consume_interface(username, cost):
    state, msg = select(username)
    if state:
        msg['balance'] -= cost
        msg['bank_flow'].append("消费%s" % cost)
        save(msg)
        bank_logger.info("消费")
        return True, "消费成功"
    else:
        return False, msg

shop.py

from db import db_handle
from interface import bank
from lib import common

shop_logger = common.get_logger("shop")


def check_shopping_interface(username):
   state, msg = db_handle.select(username)
   shop_logger.info("查看购物车")
   return msg["shopping_cart"]


def shopping_interface(username, cost, shopping_cart):
   state, msg = bank.consume_interface(username, cost)
   if state:
       state, msg = db_handle.select(username)
       msg["shopping_cart"] = shopping_cart
       db_handle.save(msg)
       shop_logger.info("购物")
       return True, "购物成功"
   else:
       return False, msg


def save_shopping(name, shopping_cart):
   state, msg = db_handle.select(name)
   if state:
       msg["shopping_cart"] = shopping_cart
       db_handle.save(msg)
       shop_logger.info("存入购物车")
       return True, "存入购物车成功"
   else:
       return False, "存入购物车失败"

user.py

# -*- encoding:utf-8 -*-
# @time: 2022/5/29 23:00
# @author: Maxs_hu
from db import db_handle
from lib import common

user_logger = common.get_logger("user")


def register_interface(username, password, balance=1500):
   # 调用数据库
   state, msg = db_handle.select(username)
   if not state:
       user_account = {
           "username": username,
           "password": password,
           "balance": balance,
           "credit": balance,
           "locked": False,
           "bank_flow": [],
           "shopping_cart": {}
       }
       db_handle.save(user_account)
       user_logger.info("注册")
       return True, "注册完成"
   else:
       return False, "用户已存在"


def login_interface(name, password):
   state, msg = db_handle.select(name)
   if state:
       if msg["password"] == password:
           user_logger.info("登录成功")
           return True, "登录"
       else:
           return False, "密码错误"
   else:
       return False, msg


def transfer_interface(username, to_username, amount):
   state, msg = db_handle.select(username)
   # 账户扣款
   if state:
       if int(msg['balance']) > amount:
           msg['balance'] -= amount
           msg['bank_flow'].append("转账给%s%s" % (to_username, amount))
           # 将修改的数据保存下来
           db_handle.save(msg)
       else:
           return False, "余额不足"
   else:
       return False, msg
   # 转账
   flag, info = db_handle.select(to_username)
   if flag:
       info['balance'] += amount
       info['bank_flow'].append("收到%s转账%s" % (username, amount))
       # 将修改的数据保存下来
       db_handle.save(info)
       user_logger.info("转账")
       return True, "转账成功"
   else:
       return False, info


def repay_interface(username, amount):
   state, msg = db_handle.select(username)
   if state:
       msg['credit'] += amount
       msg['bank_flow'].append("还款%s" % amount)
       db_handle.save(msg)
       user_logger.info("还款")
       return True, "还款成功"
   else:
       return False, msg


def check_interface(username):
   state, msg = db_handle.select(username)
   user_logger.info("查看流水")
   return msg['bank_flow']

lib

common.py

# -*- encoding:utf-8 -*-
# @time: 2022/5/29 22:59
# @author: Maxs_hu
from conf.setting import user_dic, LOGGING_DIC
from core import user_command
import logging.config


# 用户登录状态装饰器
def login_auth(func):
   def inner(*args, **kwargs):
       if user_dic['name']:
           res = func(*args, **kwargs)
           return res
       else:
           user_command.login()  # 调用login方法去登录
   return inner


# 日志
def get_logger(name):
   logging.config.dictConfig(LOGGING_DIC)
   my_logger = logging.getLogger('logger1')
   return my_logger

log

another.log

log.log

posted on 2022-06-06 16:26  huxiaofeng  阅读(32)  评论(0)    收藏  举报

导航