作业需求:模拟实现一个ATM + 购物商城程序
- 额度15000或自定义
- 实现购物商城,买东西加入 购物车,调用信用卡接口结账
- 可以提现,手续费5%
- 每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
- 支持多账户登录
- 支持账户间转账
- 记录每月日常消费流水
- 提供还款接口
- ATM记录操作日志
- 提供管理接口,包括添加账户、用户额度,冻结账户等…
- 用户认证用装饰器
完整代码链接:https://pan.baidu.com/s/1c6fFexf01g03tZBpGliTVQ#list/path=%2F
注册模块
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