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

额度 15000或自定义
实现购物商城,买东西加入 购物车,调用信用卡接口结账
支持多账户登录
支持账户间转账
记录每月日常消费流水
提供还款接口
ATM记录操作日志
提供管理接口,包括添加账户、用户额度,冻结账户等。。。
用户认证用装饰器


测试信息
ATM.py              主脚本

以下文件需提前创建
db.txt              用户名密码认证文件
                    {'admin': '000','lyndon': '123', 'egon': '456', 'alex': '789'}
assest.txt          用户资产信息  #用户初始额度为15000,admin管理员没有资产记录
                    {'lyndon': ['15000', '15000'], 'egon': ['15000', '15000'], 'alex': ['15000', '15000']}
frozen_user.txt     冻结账户文件
op.log              admin操作记录(添加用户、冻结账户、调整额度)
flow.log            账户流水记录(商城结算、信用卡还款、转账)


ATM+购物商城_脚本

import os,time      # 导入所使用的模块
current_user={'user':None}      # 全局字典控制二次认证免密码登录
def auth(func):     # 认证函数
    def wrapper(*args,**kwargs):
        if current_user['user']:        # 判断是否已认证
            return func(*args,**kwargs)
        print('请输入你要登录的账号')
        name=input('input your name:').strip()
        passwd=input('input your password:').strip()
        with open('frozen_user.txt','r',encoding='utf-8') as f:     # 判断是否在冻结账户文件中
            for i in f.readlines():
                if name in i:
                    print('账户已冻结')
                    return op()
        with open('db.txt','r',encoding='utf-8') as f_read:     # 进行用户名密码认证
            user_dic=eval(f_read.read())
        if name == 'admin' and passwd == user_dic[name]:        # 判断是否为admin用户登录
            current_user['user'] = name
            return admin()
        if name in user_dic and passwd == user_dic[name]:
            current_user['user'] = name
            res=func(*args,**kwargs)
            return res
        else:
            print('name or password error!')
            exit()
    return wrapper

@auth
def op():           #主菜单
    print('''
    【1】     购物商城
    【2】     ATM管理
    【3】     切换账号
    【4】     退出
    ''')
    chooise=input('请输入你的选择:').strip()
    if chooise == '1':
        return shop()
    elif chooise == '2':
        return atm(current_user['user'])
    elif chooise == '3':
        current_user['user']=None       # 选择切换账号时重置全局变量
        return op()
    elif chooise == '4':
        exit()
    else:
        print('输入错误,请重新输入')
        return op()

def atm(user):       #ATM管理
    if user == 'admin':
        return admin()
    else:
        print('''
        【1】     还款
        【2】     转账
        【3】     返回主菜单
        ''')
        choice=input('请输入你的选择:').strip()
        if choice == '1':
            return repayment()
        elif choice == '2':
            return transfer()
        elif choice == '3':
            return op()
        else:
            print('输入错误,重新输入')
            return atm(user)

def shop():         #购物商城
    goods ={'电脑': 2000,'鼠标': 10,'游艇': 20,'美女': 998}
    goods_list =[]
    moneys=0
    tag=1
    while tag == 1:
        for key,value in goods.items():
            print(key,value)
        choice=input('请输入要购买的商品名称:').strip()
        if choice not in goods:
            print('商品不存在,请重新输入')
            continue
        count = input('输入购买数量: ').strip()
        if count.isdigit():
            goods_list.append((choice, goods[choice], int(count)))
            money=int(goods[choice])*int(count)
            moneys=moneys+money
            print('当前购物车:%s' %goods_list)
            while tag == 1:
                choices=input('''
                【1】     继续购买
                【2】     结算
                【3】     退回主菜单
                请选择:''').strip()
                if choices == '1':break
                elif choices == '3':
                    op()
                    tag=0
                elif choices == '2':
                    checkout(moneys,goods_list)     #调用结算函数时传入钱数和购物车商品
                    tag=0
                else:
                    print('输入错误')
                    continue
        else:
            print('输入错误,请重新购买')
            continue

def checkout(nums,goods):         # 购物商城下结算
    with open('assets.txt','r',encoding='utf-8') as f_read:
        with open('assets.swap.txt','w+',encoding='utf-8') as f_write:
            money_dic=eval(f_read.read())
            money=money_dic[current_user['user']][0]        # 判断钱数与额度的大小,用户资产使用字典嵌套
            if int(nums) > int(money):
                print('余额不足,请重新购买')
                goods=[]
                shop()
            money_dic[current_user['user']][0]=str(int(money) - int(nums))
            s=str(money_dic)
            f_write.writelines(s)
    os.remove('assets.txt')
    os.rename('assets.swap.txt', 'assets.txt')
    print('购买成功,当前余额为:%s' %money_dic[current_user['user']][0])
    start=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
    with open('flow.log','a',encoding='utf-8') as f:        # 写入流水日志
        f.write('%s %s 购买物品 %s 支出%s,余额%s\n' %(start,current_user['user'],goods,nums,money_dic[current_user['user']][0]))
    return shop()

def repayment():        #信用卡管理下还款
    with open ('assets.txt','r',encoding='utf-8') as f_read:
        money_dic = eval(f_read.read())
        money=money_dic[current_user['user']][0]
        quot=money_dic[current_user['user']][1]
        owe=(int(quot) - int(money))
    if owe <= 0:
        print('当前余额为 %s 不需要还款。' %money)
    else:
        print('当前账单为:%s' %owe)
        re=input('输入还款金额:').strip()
        if re.isdigit() and len(money) != 0 :
            with open('assets.swap.txt', 'w+', encoding='utf-8') as f_write:
                money_dic[current_user['user']][0] = str(int(money) + int(re))
                s = str(money_dic)
                f_write.writelines(s)
            print('还款成功,当前余额为:%s' %money_dic[current_user['user']][0])
            start = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
            with open('flow.log', 'a', encoding='utf-8') as f:
                f.write('%s %s 主动还款%s 余额%s\n' % (start, current_user['user'], re, money_dic[current_user['user']][0]))
        else:
            print('输入金额错误,请重新输入')
            repayment()
    os.remove('assets.txt')
    os.rename('assets.swap.txt', 'assets.txt')

def transfer():         #ATM管理下转账
    with open ('assets.txt','r',encoding='utf-8') as f_read:
        money_dic = eval(f_read.read())
        money=money_dic[current_user['user']][0]
        print('当前账户余额为:%s' %money)
    other=input('转入账户:').strip()
    tran_money=input('转入金额:').strip()
    if other in money_dic and tran_money.isdigit() and len(tran_money) != 0:
        with open('assets.swap.txt', 'w+', encoding='utf-8') as f_write:
            money_dic[current_user['user']][0] = str(int(money) - int(tran_money))
            other_money = money_dic[other][0]
            money_dic[other][0] = str(int(other_money) + int(tran_money))
            s = str(money_dic)
            f_write.writelines(s)
        os.remove('assets.txt')
        os.rename('assets.swap.txt', 'assets.txt')
        print('转账成功,当前余额为:%s' % money_dic[current_user['user']][0])
        start = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        with open('flow.log', 'a', encoding='utf-8') as f:
            f.write('%s %s 向 %s 转账%s 余额%s\n' % (start,current_user['user'],other,tran_money,money_dic[current_user['user']][0]))
    else:
        print('帐户不存在、已冻结或输入金额有误')
        transfer()

def admin():            #ATM管理下管理员操作
    print('''
    【1】     添加账户
    【2】     调整额度
    【3】     冻结账户
    【4】     退出管理
    ''')
    choice=input('请输入你的选择:').strip()
    if choice == '1':
        user_add()
    elif choice == '2':
        adjustment()
    elif choice == '3':
        frozen()
    elif choice == '4':
        current_user['user']=None
        op()
    else:
        print('输入错误,重新输入:')
        admin()

def user_add():         #admin管理接口下添加用户
    with open('db.txt', 'r', encoding='utf-8') as f_read:
        user_dic = eval(f_read.read())
    user_name=input('创建用户名:').strip()
    user_passwd=input('设置密码:').strip()
    passwd_ag=input('确认密码:').strip()
    if user_name not in user_dic and user_passwd == passwd_ag:
        user_dic[user_name]=user_passwd
        user_list=str(user_dic)
        with open('db.txt','w',encoding='utf-8') as f:
            f.write(user_list)
        with open('assets.txt','r',encoding='utf-8') as f1:
            with open('assets.swap.txt','w',encoding='utf-8') as f2:
                money_dic = eval(f1.read())
                money_dic[user_name]=['15000','15000']      #添加用户时,设置初始额度为15000
                s=str(money_dic)
                f2.write(s)
                print('%s 用户已添加' %user_name)
                start = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
                with open('op.log', 'a', encoding='utf-8') as f3:
                    f3.write('%s %s 添加账户:%s 密码:%s\n' % (start, current_user['user'], user_name,user_passwd))
    else:
        print('用户名已存在或两次输入密码不一致')
        admin()
    os.remove('assets.txt')
    os.rename('assets.swap.txt', 'assets.txt')
    admin()

def adjustment():       #admin管理接口下调整额度
    with open ('assets.txt','r',encoding='utf-8') as f_read:
        money_dic = eval(f_read.read())
        adjust_user = input('请输入需要调整的账户:').strip()
        quot=money_dic[adjust_user][1]
        if adjust_user not in money_dic:
            print('用户不存在')
            return admin()
        else:
            print('%s 当前额度为 %s' %(adjust_user,quot))
            adjust_quot=input('调整为:').strip()
            if adjust_quot.isdigit() and len(adjust_user) != 0:
                with open('assets.swap.txt', 'w+', encoding='utf-8') as f_write:
                    money_dic[adjust_user][0]=str(int(money_dic[adjust_user][0]) + int(adjust_quot) - int(quot))
                    money_dic[adjust_user][1] = adjust_quot
                    s=str(money_dic)
                    f_write.writelines(s)
                    print('%s 调整额度成功,当前额度为:%s' %(adjust_user,money_dic[adjust_user][1]))
                    start = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
                    with open('op.log', 'a', encoding='utf-8') as f:
                        f.write('%s %s 调整 %s 额度由%s ---> %s\n' % (start, current_user['user'], adjust_user,quot,money_dic[adjust_user][1]))
            else:
                print('输入金额错误')
                admin()
    os.remove('assets.txt')
    os.rename('assets.swap.txt', 'assets.txt')
    admin()

def frozen():           # admin管理接口下冻结账户(已知bug为如果输入为已冻结账号会重新冻结)
    frozen_name=input('请输入你要冻结的账户名(admin无法冻结):').strip()
    with open('db.txt','r',encoding='utf-8') as f_read:
        user_dic = eval(f_read.read())
    if frozen_name in user_dic and frozen_name != 'admin':
        with open('frozen_user.txt','a',encoding='utf-8') as f_write:
            print('%s 账号已冻结' % frozen_name)
            f_write.write('%s\n' % frozen_name)
        start = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        with open('op.log', 'a', encoding='utf-8') as f:
            f.write('%s %s 冻结账户 %s\n' % (start,current_user['user'],frozen_name))
        admin()
    else:
        print('账户不存在')
        return frozen()

op()