First Project -用函数写的ATM+购物商城程序

作业需求:模拟实现一个ATM + 购物商城程序

  • 额度15000或自定义
  • 实现购物商城,买东西加入 购物车,调用信用卡接口结账
  • 可以提现,手续费5%
  • 每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
  • 支持多账户登录
  • 支持账户间转账
  • 记录每月日常消费流水
  • 提供还款接口
  • ATM记录操作日志
  • 提供管理接口,包括添加账户、用户额度,冻结账户等…
  • 用户认证用装饰器

注册模块

def register():
    """注册"""
    print("\033[1;31;40m欢迎使用注册功能\033[0m")
    
    # 调用与用户交互函数
    username, pwd, user_path = input_username_pwd()
    
    # 判断用户是否被注册
    if os.path.exists(user_path):
        print('注册失败!该用户已被注册')
        return False
    
    user_info = {'username': username, 'pwd': pwd, 'account': 10000, 'extra': 15000, 'is_locked': 0}
    # 将注册信息写入json文件中
    write_file(user_path, user_info)
    print('注册成功')
    return True

登录模块

def login():
    """登录"""
    print("\033[1;31;40m欢迎使用登录功能\033[0m")

    global active_user
    count = 0
    
    # 登录三次机会,三次后账户冻结
    while count < 3:
        username, pwd, user_path = input_username_pwd()
        
        # 判断用户是否存在
        if not os.path.exists(user_path):
            print('登录失败,该用户未注册')
            count += 1
            continue

        user_dict = read_file(user_path)
        # 判断账户是否被冻结
        if user_dict['is_locked'] == 1:
            relieve = input('该账户被冻结,请前往会员中心解锁\n输入q退出,否则按任意键解锁:')
            if relieve == 'q':
                return False
            
            # 调用账户解封函数
            return account_unlock()
        
        # 判断用户名、密码匹配
        elif username == user_dict['username'] and pwd == user_dict['pwd']:
            print('登录成功')
            active_user = user_dict
            return True
        else:
            active_user = dict()
            print('登录失败,用户名或密码错误')
            count += 1
            
            # 三次登录失败后,账户冻结
            if count == 3:
                user_dict['is_locked'] = 1
                write_file(user_path, user_dict)

登录装饰器

def login_deco(func):
    def wrapper(*args, **kwargs):
        while True:
            # 通过当前是否有用户信息来判断是否登录
            if active_user:
                res = func(*args, **kwargs)
                return res
            else:
                print('请先登录')
                login()
    return wrapper

查看账户余额信息

def check_balance():
    """查看余额"""
    print("\033[1;31;40m欢迎进入余额查询界面\033[0m")
    print(f'{"账户信息".center(50,"*")}\n姓名:{active_user["username"]}\n您当前所剩余额为{active_user["account"]}')
    print("*" * 50)

转账模块

def transfer():
    """转账"""
    print("\033[1;31;40m欢迎使用转账功能\033[0m")

    while True:
        transfer_account = input("请输入要转入的账户(输入q退出转账):").strip()

        if transfer_account == 'q':
            return False

        transfer_money = input('请输入转出的金额(输入q退出转账):').strip()

        if transfer_money == 'q':
            return False

        # 判断非法输入
        if not transfer_money.isdigit():
            print('非法输入')
            continue

        transfer_money = int(transfer_money)
        transfer_confirm = input(f'请确认是否转给账户{transfer_account},金额{transfer_money}\n继续转账输入"Y"或"y",否则,按任意键放弃转账')
        if not (transfer_confirm == 'Y' or transfer_confirm == 'y'):
            print('放弃转账')
            return False
        
        # 余额不足转入失败
        if active_user['account'] < transfer_money:
            print('转账失败,余额不足')
            print("*" * 50)
            continue

        user_path_accept = os.path.join(r'F:\dragon_boat\ATM\db\user', f'{transfer_account}.user')
        # 判断转入的账户是否存在
        if not os.path.exists(user_path_accept):
            print('转入失败,转入账户不存在!')
            print("*" * 50)
            return False

        user_path = os.path.join(r'F:\dragon_boat\ATM\db\user', f'{active_user["username"]}.user')
        
        # 判断转入是否为自己
        if user_path_accept == user_path:
            print('转账失败!不能给自己转账,需充值请前往充值功能')
            print("*" * 50)
            return False

        # 转出账户金额减少
        active_user['account'] -= transfer_money
        write_file(user_path, active_user)
        
        # 转入账户金额增加
        accept_user = read_file(user_path_accept)
        accept_user['account'] += transfer_money
        write_file(user_path_accept, accept_user)
        
        # 记录转出信息
        expense_path = os.path.join(r"F:\dragon_boat\ATM\db\bank", f'{active_user["username"]}.txt')
        record = f"{time.strftime('%Y-%m-%d %X')} 转给账户{accept_user['username']}金额{transfer_money}元\t\t-{transfer_money}\n" 
        consumption_record(expense_path, record)
        
        # 记录转入信息
        expense_path = os.path.join(r"F:\dragon_boat\ATM\db\bank", f'{accept_user["username"]}.txt')
        record = f"{time.strftime('%Y-%m-%d %X')} 收到{active_user['username']}转入的{transfer_money}元\t\t+{transfer_money}\n"
        consumption_record(expense_path, record)
        
        print('转账成功')
        print("*" * 50)

还款&充值模块

def pay_back():
    """还款&充值"""
    print("\033[1;31;40m欢迎使用还款&充值功能\033[0m")
    print(f'当前账户余额为:{active_user["account"]}')
    while True:
        pay_money = input('请输入金额(输入q退出):').strip()
        if pay_money == 'q':
            return False
        if not pay_money.isdigit():
            print('非法输入,请输入还款&充值数字金额')
            continue
        
        # 账户充值
        active_user['account'] += int(pay_money)
        user_path = os.path.join(r'F:\dragon_boat\ATM\db\user', f'{active_user["username"]}.user')
        write_file(user_path, active_user)
        print(f'充值成功,当前账户余额为{active_user["account"]}')

提现模块

def with_draw():
    """提现"""
    print("\033[1;31;40m欢迎使用提现功能\033[0m")

    while True:
        account_drawn = input('请输入要提取的金额(输入q退出):').strip()

        if account_drawn == 'q':
            break

        if not account_drawn.isdigit():
            print('非法输入,请输入数字')
            continue
        account_drawn = int(account_drawn)

        # 判断提取金额是否大于剩余金额
        if account_drawn * (1 + 0.05) > active_user['account']:
            print('余额不足,无法提取')
            continue
        
        # 计算账户余额,扣除手续费
        active_user['account'] -= account_drawn * (1 + 0.05)
        user_path = os.path.join(r"F:\dragon_boat\ATM\db\user",f'{active_user["username"]}.user')
        write_file(user_path, active_user)
        
        # 记录提现信息 
        expense_path = os.path.join(r"F:\dragon_boat\ATM\db\bank", f'{active_user["username"]}.txt')
        record = f"{time.strftime('%Y-%m-%d %X')} 提取现金{account_drawn}元\t\t-{account_drawn}\n"
        consumption_record(expense_path, record)

        print(f'提现{account_drawn},收取手续费{account_drawn*0.05}当前余额为{active_user["account"]}')

查询消费记录模块

def consumer_details():
    """消费明细"""
    print("\033[1;31;40m账单\033[0m".center(50, "*"))
        
    # 读取用.txt记录的消费记录
    user_path = os.path.join(r'F:\dragon_boat\ATM\db\bank', f"{active_user['username']}.txt")
    billing = read_record(user_path)

    print(f'消费记录:{billing}')
    print("*" * 50)

购物模块

def shopping():
    """购物"""
    print("\033[1;31;40m欢迎使用购物功能\033[0m")

    global shopping_car_dict
    goods_list = {
        '0': ('Alpaca', 100),
        '1': ('bird', 200),
        '2': ('Cat', 300),
        '3': ('Dog', 400),
        '4': ('Elephant', 500)
    }

    while True:
        # 打印商品信息
        print('本店有以下商品')
        for goods_id, goods in goods_list.items():
            print(goods_id, goods)

        shopping_goods_id = input('请输入要购买的商品编号(输入q退出):').strip()

        if shopping_goods_id == 'q':
            break

        if shopping_goods_id not in goods_list:
            print('非法输入,你输入的商品暂不提供')
            continue
        shopping_goods_num = input('请输入购买的商品数量(输入q退出):').strip()

        if shopping_goods_num == 'q':
            break

        if not shopping_goods_num.isdigit():
            print('非法输入,请输入数字')
            continue

        shopping_goods = goods_list[shopping_goods_id]
        goods_num = int(shopping_goods_num)
        print(f'你往购物车内添加了商品:{shopping_goods},数量:{goods_num}个')
        
        # 往购物车添加商品
        if shopping_car_dict.get(shopping_goods):
            shopping_car_dict[shopping_goods] += goods_num
        else:
            shopping_car_dict[shopping_goods] = goods_num

购物车结算模块

def shopping_car_check():
    """购物车结算购物商品"""
    print("\033[1;31;40m欢迎进入购物车\033[0m")

    global goods_price_total
    global shopping_car_dict
    while shopping_car_dict:
        goods_price_total = 0   # 记录商品价格

        print('当前购物车有以下商品:')
        for shopping_goods, goods_num in shopping_car_dict.items():
            print(shopping_goods, goods_num)
            goods_price_total += shopping_goods[1] * goods_num
        
        # 一次性消费最高额度
        if goods_price_total > active_user['extra']:
            print(f'最高一次性可消费{active_user["extra"]},当前商品总金额为{goods_price_total}\n购物车有以下商品,请修改商品')

            for ind, shopping_goods in enumerate(shopping_car_dict):
                print(ind, shopping_goods, shopping_car_dict[shopping_goods])
            
            # 修改购物车内商品信息
            modify_goods_id = input('请输入要修改的商品编号:').strip()
            shopping_list = [goods for _, goods in enumerate(shopping_car_dict)]
            modify_goods = shopping_list[int(modify_goods_id)]
            modify_num = int(input('请输入商品修改后的数量:').strip())
            
            # 将购物车内数量为0的商品删除
            if modify_num == 0:
                del shopping_car_dict[modify_goods]
            else:
                shopping_car_dict[modify_goods] = modify_num
        else:
            print('可以去结账了')
            
            # 调用结账函数
            check_res = check()
            if check_res == True:
                shopping_car_dict = dict()
    print('当前购物车内无商品,可前往购物')

主功能界面

def func_main():
    """主功能界面"""

    func_dict = {
        '1': register,
        '2': login,
        '3': check_balance,
        '4': transfer,
        '5': pay_back,
        '6': with_draw,
        '7': consumer_details,
        '8': shopping,
        '9': shopping_car_check
    }

    func_msg = """
        1: register 注册
        2: login 登录
        3: check_balance 查看余额
        4: transfer 转账
        5: pay_back 还款充值
        6: with_draw 提现
        7: consumer_details 消费明细
        8: shopping 购物
        9: shopping_car_check 前往购物车结账
        q: quit 退出
        """

    while True:

        # 打印功能列表
        print(func_msg)

        func_choice = input('请输入选择的功能(输入q退出)》》》').strip()

        # 是否退出
        if func_choice == 'q':
            print('你已退出')
            break

        # 非法输入
        if not func_choice.isdigit() or func_choice not in func_dict:
            print('非法输入,请重新输入功能对应的序号')
            continue

        func_dict[func_choice]()

读写文件

import json

# 写json文件
def write_file(filename, content):
    with open(filename, 'w', encoding='utf8') as fw:
        json.dump(content, fw)
        fw.flush()

    return True
# 读json文件
def read_file(filename):
    with open(filename, 'r', encoding='utf8') as fr:
        user_dict = json.load(fr)

    return user_dict

# 记录消费信息
def consumption_record(filename, content):
    with open(filename, 'a', encoding='utf8')as fa:
        fa.write(content)
        fa.flush()
    return True

# 读消费信息
def read_record(filename):
    with open(filename, 'r', encoding='utf8') as fr:
        sum = 0
        for i in fr:
            print(i, end="")
            sum += int(i.split()[-1])
    return sum

结账模块

def check():
    """结账接口"""

    from ATM.core.src import goods_price_total, active_user
    print("输入付款账户、密码")
    username, pwd, user_path = input_username_pwd()
    check_account = read_file(user_path)
    
    # 验证付款账户密码结账,支持用其他非登录账户结账功能
    if check_account['username'] == username and check_account['pwd'] == pwd:
        check_account['account'] -= goods_price_total
        write_file(user_path, check_account)
        print(f"结账成功,该账户余额为{check_account['account']}")
        if check_account['username'] == active_user['username']:
            active_user['account'] = check_account['account']
            
        # 记录结账扣费
        expense_path = os.path.join(r"F:\dragon_boat\ATM\db\bank", f'{check_account["username"]}.txt')
        record = f"{time.strftime('%Y-%m-%d %X')} 购物消费{goods_price_total}元\t\t-{goods_price_total}\n"
        consumption_record(expense_path, record)
        return True
    else:
        print('验证失败,请重新支付')
        return False

账户解锁模块

def account_unlock():
    """账户解锁"""
    print('\033[1;31;40m欢迎来到会员中心\033[0m')
    username, pwd, user_path = input_username_pwd()
    user_info = read_file(user_path)
    
    # 用户名与密码匹配,解锁
    if username == user_info['username'] and user_info['pwd'] == pwd:
        user_info['is_locked'] = 0
        write_file(user_path, user_info)
        print('解锁成功,请重新登录')
        return True
    else:
        print('验证失败')
        return False

用户交互模块

import os
def input_username_pwd():
    """输入账户名和密码"""

    username = input('请输入用户名》》》').strip()
    pwd = input('请输入密码》》》').strip()
    user_path = os.path.join(r"F:\dragon_boat\ATM\db\user", f'{username}.user')    # 账户文件路径

    return username, pwd, user_path
上一篇:ATM取款机-C语言期末大作业


下一篇:PTA题目集7-9的总结