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


               记得上次小编上传了一个购物车程序,这次呢稍微复杂一点,还是那句话,上传在这里不是为了炫耀什么,只是督促小编学习,如果大神有什么意见和建议,欢迎指导。

      于2018.3.11开始动笔,继续完成这个项目。

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

         

    要求如下:
    
           1.额度15000或者自定义
    
           2.实现购物商城,买东西加入购物车,调用信用卡接口结账
    
           3.可以提现,手续费5%
    
            4.支持多账户登陆
    
            5.支持账户间转账
    
            6.记录每月日常消费流水
    
            7.提供还款接口
    
            8.ATM记录操作日志
    
            9.提供管理接口,包括添加账户,用户额度,冻结账户等
    
            10.用户认证用装饰器
    

    二,分析功能需求

    ATM的角色:
          管理员功能:
                  1,增删改查,加钱,减钱
                  2,记录日志
                  3,基本信息
                  4,额度 15000
                
          普通用户功能:
                  1,可以提现,手续费5%
                  2,支持多账户登录
                  3,支持账户间转账
                  4,记录每月日常消费流水
                  5,提供还款接口
                  6,ATM记录操作日志    
            
    购物车程序:
                  1,可以进入程序购买商品
                  2,支持多账户登录
                  3,购完东西显示余额和购买的东西
         
            
    

      

     三,文件创建

      文件的创建是有开发规范的,比如下面:

        bin  用于执行可执行文件
    
        conf  配置文件
    
        core    用于存放核心代码   
     
        db  用于存放用户数据
    
        log  日志,记录相关信息
    

      

    四,思路流程图

     

     

     五,简要说明

    1,本程序思路是写了一个ATM和购物商城的程序
        其中购物商场简单的实现了功能,并没有调用ATM中的信用卡结账
        ATM写了信用卡操作和管理员操作,没有实现记录每月日常消费流水
    2,对于购物商城:
        调用/shopping_mall/shopping_run.py文件执行
        简单的实现了用户进入商城,选择购物,则对账户余额进行扣款,推出时打印购买商品和余额
    3,对于ATM有两个入口:
        (1):普通用户对信用卡操作
                 调用/atm-learn/bin/atm.py文件执行,可以打印账户信息、还款、取款、转账、账单、退出等操作
          ①账户信息
      ②还款
      ③取款
      ④转账
      ⑤账单
      ⑥退出
        (2):管理用户对信用卡操作
                 调用/atm-learn/bin/atm_manage.py文件执行则可以对用户进行管理,解冻用户、冻结用户、申领新卡等操作
      ①添加账户
      ②冻结账户
      ③解冻账户
      ④退出
    

      

    概述
    
    本次作业文件夹一共包含了以下6个文件:
    
    流程图一:ATM用户登录思路流程图
    流程图二:ATM管理登陆思路流程图
    流程图三:购物车思路流程图
    程序结构图:整个ATM+shopping的程序文件结构
    程序文件: ATM + shopping
    程序说明文件:README.md
    程序介绍
    
    本程序思路是写了一个ATM和购物商城的程序
    
    ATM写了信用卡操作和管理员操作,没有实现记录每月日常消费流水
    购物商场简单的实现了功能,并没有调用ATM中的信用卡结账
    1,对于ATM有两个入口:
    
    (1):普通用户对信用卡操作
    
    调用/atm/bin/atm.py文件执行,可以打印账户信息、还款、取款、转账、账单、退出等操作
    (2):管理用户对信用卡操作
    
    调用/atm-learn/bin/atm_manage.py文件执行则可以对用户进行管理,解冻用户、冻结用户、申领新卡等操作
    2,对于购物商城:
    
    调用/shopping/shopping_run.py文件执行
    简单的实现了用户进入商城,选择购物,则对账户余额进行扣款,推出时打印购买商品和余额
    程序结构
    
    备注
    
    目前还不会在windows中用树的结构,所以做出程序结构的txt版本,放在文件外面
    对几个实例json文件的说明
    
    0000.json 一个用户账户示例文件(这个是账号正常,但是账号过期,不在使用范围内)
    123.json 一个用户账户示例文件(这个是账号正常)
    1234.json 一个用户账户示例文件(这个是账号被锁定,除非登陆管理端修改被冻结的状态,才能正常使用)
    admin.json 一个管理账户示例文件(如果不知道管理者的账户和密码,可以查看)
    不足及其改进的方面
    
    1,未实现购物商城调用信用卡接口结账
    
    2,账户之间的转账
    
    3,ATM中查看账单,未能实现调用每个月的流水帐单,只是简单的查看信用额度和账户余额
    
    4,购物商场比较简单,每次买一个东西就自己结账退出
    

      

    六,程序结构

    atm+shopping``
    ├── README
    ├── atm #ATM主程序目录
    │   ├── __init__.py
    │   ├── bin #ATM 执行文件 目录
    │   │   ├── __init__.py
    │   │   ├── atm.py  #ATM 执行程序
    │   │   └── manage.py #ATM 管理端 执行程序
    │   ├── conf #配置文件
    │   │   ├── __init__.py
    │   │   └── settings.py
    │   ├── core #主要程序逻辑都 在这个目录 里
    │   │   ├── __init__.py
    │   │   ├── accounts.py  #用于从文件里加载和存储账户数据
    │   │   ├── atm_main.py   #atm 主逻辑交互程序
    │   │   ├── auth.py      #用户认证模块
    │   │   ├── db_handler.py   #数据库连接引擎
    │   │   ├── logger.py       #日志记录模块
    │   │   ├── manage_main.py         #atm管理端主逻辑交互程序
    │   │   └── transaction.py  #记账还钱取钱等所有的与账户金额相关的操作都 在这
    │   ├── db  #用户数据存储的地方
    │   │   ├── __init__.py
    │   │   ├── account_sample.py #一个存用户的账户数据的例子
    │   │   └── accounts #存各个用户的账户数据 ,一个用户一个文件
    │   │       └── 0000.json #一个用户账户示例文件(这个是账号正常,但是账号过期,不在使用范围内)
    │   │       └── 123.json #一个用户账户示例文件(这个是账号正常)
    │   │       └── 1234.json #一个用户账户示例文件(这个是账号被锁定,除非登陆管理端修改被冻结的状态,才能正常使用)
    │   │       └── admin.json #一个管理账户示例文件(如果不知道管理者的账户和密码,可以查看)
    │   └── log #日志目录
    │       ├── __init__.py
    │       ├── access.log #用户访问和操作的相关日志
    │       └── transactions.log    #所有的交易日志
    └── shopping #购物车目录
        └── __init__.py
        └── 123.json            #一个购物用户账户示例文件(包括用户id,密码,余额)
        └── shopping_main.py    #主逻辑交互程序
        └── shopping_run.py     #购物车 执行程序

     七,程序代码

    7.1 ATM代码

    bin下atm.py

    # _*_ coding: utf-8 _*_
    
    import os
    import sys
    
    #添加环境变量
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  #找到路径
    sys.path.append(BASE_DIR)          #添加路径
    
    
    #将main.py里面所有代码封装成main变量
    
    from core import atm_main
    '''ATM程序的执行文件'''
    
    if __name__ == '__main__':
        atm_main.run_atm()
    

      

    bin下atm_manage.py

    # _*_ coding: utf-8 _*_
    import os
    import sys
    
    #添加环境变量
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  #找到路径
    sys.path.append(BASE_DIR)          #添加路径
    
    
    
    
    from core import manage_main
    '''管理程序的执行文件'''
    
    if __name__ == '__main__':
        manage_main.run_manage()
    

      

    conf/setting.py

    # _*_ coding: utf-8 _*_ 
    '''初始化的配置'''
    
    import logging
    import os
    import sys
    
    #到ATM目录,方便后面创建账户文件
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    
    DATABASE = {
        'engine':'file_storage',       #文件存储,这里可扩展成数据库形式的
        'name':'accounts',              #db下的文件名
        'path':'%s/db' %BASE_DIR
    }
    
    LOGIN_LEVEL = logging.INFO     #初始化日志记录级别为INFO,INFO以下的可以直接打印
    #日志类型
    LOGIN_TYPE = {
        'access':'access.log',
        'transaction':'transaction.log'
    }
    
    TRANSACTION_TYPE = {
        'repay':{'action':'plus','interest':0},
        'withdraw':{'action':'minus','interest':0.05},
        'transfer':{'action':'minus','interest':0.05},
        'consume':{'action':'minus','interest':0},
    }
    

      

    core/accounts.py

    # _*_ coding: utf-8 _*_ 
    import os
    import sys
    import json
    import logging
    import time
    import datetime
    
    
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)  #添加环境变量
    
    from core import auth
    from core import db_handler
    from conf import settings
    
    
    def load_current_balance(account_id):
        '''
         # 把数据load下,返回账户余额和其他基础信息
        :param account_id: 用户账户的名字
        :return: 返回最新读到的数据文件中的最新数据
        '''
        db_path = db_handler.db_handler(settings.DATABASE)
        account_file = "%s/%s.json"%(db_path,account_id)
        with open(account_file,'r',encoding='utf-8') as f:
            acc_data = json.load(f)
            return acc_data
    
    def  dump_account(account_dic):
        '''
        在更新完后,把数据dump到文件中,文件地址为atm-learn/db/accounts
        :param account_data:
        :return:
        '''
        db_path =db_handler.db_handler(settings.DATABASE)
        account_file = "%s/%s.json" %(db_path,account_dic['id'])
        with open(account_file,'w',encoding='utf-8') as f:
            acc_data = json.dump(account_dic,f)
    

      

    core/atm_main.py

    # _*_ coding: utf-8 _*_ 
    '''主逻辑交互模块'''
    import logging
    import sys
    from core import auth
    from core import logger
    from core import accounts
    from core import transaction
    from core import db_handler
    
    
    #用户数据信息
    user_data = {
        'account_id':None ,      #账户ID
        'is_authenticated':False,   #是否认证
        'account_data':None     #账户数据
    }
    
    #调用log文件下的log方法,返回日志对象
    access_logger = logger.logger('access')
    trans_logger = logger.logger('transaction')
    
    
    
    def account_info(func):
        '''
        用户账号信息,acc_data:包括ID,is_authenticaed,用户帐号信息,主要看是否被锁住
        :return:
        '''
        def wrapper(acc_data):
            account_id=acc_data["account_id"]
            account_data=acc_data["account_data"]
            status=acc_data['account_data']["status"]
            if int(status) ==0:
                func(acc_data)
                return  True
            else:
                print("33[32;1msorry your account was locked33[0m")
                exit()
    
        return wrapper
    
    @account_info
    def disp_account_info(acc_data):
        '''
        展示账户信息
        #去除 password 字段显示
        :param account_data: 账户信息
        :return:
        '''
        print("--------------ACCOUNT INFO---------------")
        for i in acc_data['account_data']:
            print("{:^20}:33[32;1m{:^20}33[0m".format(i, acc_data['account_data'][i]))
    
    
    @account_info
    def repay(acc_data):
        '''
        存款
        acc_data:包括ID,is_authenticaed,用户帐号信息
        :return:
        '''
        account_data = accounts.load_current_balance(acc_data['account_id'])
        current_balance = '''---------------------BALANCE INFO-----------------
        Credit :    %s
        Balance:    %s'''%(account_data['credit'],account_data['balance'])
        print(current_balance)
        back_flag = False
        while not back_flag:
            repay_amount = input("33[32;1mInput repay amout(input 'b' is back):33[0m").strip()
            if len(repay_amount) >0 and repay_amount.isdigit():
                new_balance = transaction.make_transaction(
                    trans_logger,account_data,'repay',repay_amount)
                if new_balance:
                    print('''33[34;1mNEW Balance:%s33[0m'''%(new_balance['balance']))
            elif repay_amount == 'b':
                back_flag = True
            else:
                print("33[31;1m%s is not valid amount ,Only accept interger!33[0m"%repay_amount)
    
    @account_info
    def withdraw(acc_data):
        '''
        打印当前余下的钱,并且让用户做取钱的功能
        :param acc_data:
        :return:
        '''
        account_data = accounts.load_current_balance(acc_data['account_id'])
        current_balance ='''---------------------BALANCE INFO-----------------
        Credit :    %s
        Balance:    %s'''%(account_data['credit'],account_data['balance'])
        print(current_balance)
        back_flag = False
        while not back_flag:
            withdraw_amount = input("33[33;1mInput withdraw amout(input 'b' is back):33[0m").strip()
            if len(withdraw_amount) > 0 and withdraw_amount.isdigit():
                new_balance = transaction.make_transaction(
                    trans_logger, account_data, 'withdraw', withdraw_amount)
                if new_balance:
                    print('''33[32;1mNEW Balance:%s33[0m''' % (new_balance['balance']))
            elif withdraw_amount == 'b':
                back_flag = True
            else:
                print('33[31;1m[%s] is not a valid amount , only accept integer33[0m'%withdraw_amount)
    
    @account_info
    def transfer(acc_data):
        '''
        转账
        :return:
        '''
        account_data = accounts.load_current_balance(acc_data['account_id'])
        current_balance = '''---------------------BALANCE INFO-----------------
            Credit :    %s
            Balance:    %s''' % (account_data['credit'], account_data['balance'])
        print(current_balance)
        back_flag = False
        while not back_flag:
            transfer_amount = input("33[33;1mInput transfer amount(input 'b' is back):33[0m").strip()
            if len( transfer_amount) > 0 and  transfer_amount.isdigit():
                new_balance = transaction.make_transaction(
                    trans_logger, account_data, 'transfer',  transfer_amount)
                if new_balance:
                    print('''33[32;1mNEW Balance:%s33[0m''' % (new_balance['balance']))
            elif transfer_amount == 'b':
                back_flag = True
            else:
                print('33[31;1m[%s] is not a valid amount , only accept integer33[0m' % transfer_amount)
    
    @account_info
    def paycheck(acc_data):
        '''
        账单检查,记录每月日常消费流水
        :return:
        '''
        account_data = accounts.load_current_balance(acc_data['account_id'])
        current_balance = '''---------------------BALANCE INFO-----------------
            Credit :    %s
            Balance:    %s''' % (account_data['credit'], account_data['balance'])
        print(current_balance)
    
    
    @account_info
    def logout(acc_data):
        '''
        退出登陆
        :return:
        '''
        print("33[32;1m-------Looking forward to your next visit-------33[0m")
        exit()
    
    def interactive(acc_data):
        '''
        用户交互
        :return:
        '''
        msg = (
            '''
            ------------------CHINA BANK --------------
                            33[31;1m1.账户信息
                            2.存款
                            3.取款
                            4.转账
                            5.账单
                            6.退出
            33[0m'''
        )
        menu_dic = {
            "1":disp_account_info,
            "2":repay,
            "3":withdraw,
            "4":transfer,
            "5":paycheck,
            "6":logout,
        }
        exit_flag = False
        while not exit_flag:
            print(msg)
            user_choice = input(">>>>").strip()
            if user_choice in menu_dic:
                menu_dic[user_choice](acc_data)
            else:
                print("33[31;1mYou choice doesn't exist!33[0m")
    
    def run_atm():
        '''
        当程序启动时候,调用,主要用于实现主要交互逻辑
        :return:
        '''
        # 调用认证模块,返回用户文件json.load后的字典,传入access_logger日志对象
        access_data = auth.access_login(user_data,access_logger)
    
        if user_data['is_authenticated']:       #如果用户认证成功
            user_data["account_data"] = access_data
            interactive(user_data)      #用户交互开始
    

      

    core/auth.py

    # _*_ coding: utf-8 _*_
    
    import os
    import json
    import time
    
    from core import accounts
    from core import db_handler
    from conf import settings
    from bin import atm_manage
    from core import atm_main
    
    
    def access_auth(account,password,log_obj):
        '''
        下面access_login调用access_auth方法,用于登陆
        :param account: 用户名
        :param password: 密码
        :return: 如果为超期,返回字典,超期则打印相应提示
        '''
        db_path = db_handler.db_handler(settings.DATABASE)       #调用db_handle下的handle方法,返回路径/db/accounts
        account_file = '%s/%s.json'%(db_path, account)     #用户文件
        #判断文件和i否存在,如果存在的话 则执行下面的
        if os.path.isfile(account_file):        #如果用户文件存在(即用户存在)
            with open(account_file,'r',encoding='utf-8') as f:  #打开文件
                account_data = json.load(f)     #file_data为字典形式
                if account_data['password']  == password:
                    expire_time = time.mktime(time.strptime(account_data['expire_date'],'%Y-%m-%d'))
                    if time.time() > expire_time:        #如果信用卡已经过期,当前时间戳大于国企的时间戳
                        log_obj.error("Account [%s] had expired,Please contract the bank" % account)
                        print("33[31;1mAccount %s had expired,Please contract the bank"%account)
                    else:       #信用卡未过期,返回用户数据的字典
                        log_obj.info("Account [%s] logging success" % account)
                        return account_data
                else:
                    log_obj.error("Account or Password does not correct!")
                    print("33[31;1mAccount or Passwordoes not correct!33[0m")
        else:       #用户不存在
            log_obj.error("Account [%s] does not exist!" % account)
            print("33[31;1mAccount [%s] does not exist!33[0m"%account)
    
    def access_login(user_data,log_obj):
        '''
        用户登陆,当登陆失败超过三次
        :param user_date:main.py里面的字典,用户信息数据,只存在内存中
        :return:若用户账号密码正确,且信用卡未过期,则返回用户数据的字典
        '''
        retry_count = 0
        while  user_data['is_authenticated'] is not True and retry_count < 3:
            account = input('33[32;1mplease input Acount:33[0m').strip()
            password = input('33[32;1mplease input Password:33[0m').strip()
            #用户账号密码正确而且信用卡未过期,返回用户数据的字典
            auth = access_auth(account, password,log_obj)
            if auth:
                user_data['is_authenticated'] = True        #用户认证为True
                user_data['account_id'] = account            #用户账号ID为账号名
                # print("welcome")
                return auth
            retry_count += 1
        else:
            print("Account [%s] try logging too many times..."%account)
            log_obj.error("Account [%s] try logging too many times..." % account)
            exit()
    

      

    core/db_handler.py

    # _*_ coding: utf-8 _*_ 
    '''处理与数据之间的交互,如果file_db_storage,返回路径'''
    import json
    import time
    from conf import settings
    
    
    def file_db_handle(conn_params):
        '''
        parse the db file path  对文件路径做语法分析
        :param conn_params:
        :return:
        '''
        db_path = '%s/%s' %(conn_params['path'],conn_params['name'])
        return db_path
    
    def db_handler(conn_parms):
        '''
    
        :param conn_parms: the db connection params set in settings
        :return: a
        DATABASE = {
        'engine':'file_storage',       #文件存储,这里可扩展成数据库形式的
        'name':'accounts',              #db下的文件名
        'path':'%s/db' %BASE_DIR
    }
        '''
    
        if conn_parms['engine']  == 'file_storage':
            return file_db_handle(conn_parms)
    

      

    core/logger.py

    # _*_ coding: utf-8 _*_ 
    
    '''操作所有的日志工作'''
    
    import logging
    from conf import settings
    
    def logger(log_type):
    
        logger = logging.getLogger(log_type)
        logger.setLevel(settings.LOGIN_LEVEL)
    
        #创建屏幕对象和设置等级debug
        # ch = logging.StreamHandler()
        # ch.setLevel(settings.LOGIN_LEVEL)
    
        #创建文件对象,给文件对象设置等级
        log_file = "%s/log/%s"%(settings.BASE_DIR,settings.LOGIN_TYPE[log_type])
        fh = logging.FileHandler(log_file)
        fh.setLevel(settings.LOGIN_LEVEL)
        # 设置输出对象格式
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
        #把格式添加到配置中
        # ch.setFormatter(formatter)
        fh.setFormatter(formatter)
    
        #把日志打印到指定的handler
        # logger.addHandler(ch)
        logger.addHandler(fh)
    
        return logger
    

      

    core/manage_main.py

    # _*_ coding: utf-8 _*_ 
    '''管理端,提供管理接口,包括添加账户,用户额度,冻结账户,解冻账户'''
    import os
    import sys
    import json
    
    from core import auth
    from core import accounts
    from core import transaction
    from core import db_handler
    from conf import settings
    
    
    # 解冻账户
    def unlock_account():
        '''解冻账户的初步思路是读取用户文件,把status的状态一更改就ok '''
        account = input("33[34;1mPlease input the account that you want to unlock:33[0m")
        read_data = unlock_accountcore(account)
        return read_data
    
    
    def unlock_accountcore(account):
        '''
        解冻账户,读取用户文件,读到status,把状态更改为0
        #0 = naormal,1 = locked ,
        :param account:
        :return:
        '''
        # 调用db_handle下的handle方法,返回路径/db/accounts
        db_path = db_handler.db_handler(settings.DATABASE)
        account_file = '%s/%s.json' % (db_path, account)
        account_new = '%s/%s.json' % (db_path, account)
        if os.path.isfile(account_file):
            with open(account_file, 'r', encoding='utf-8') as f:
                account_data = json.load(f)
                account_data['status'] = 0
            with open(account_new, 'w', encoding='utf-8') as fnew:
                new_data = json.dump(account_data, fnew)
    
    
    # 冻结账户
    def lock_account():
        '''
        冻结账户,思路与解冻刚好相反
        :param acc_data:
        :return:
        '''
        account = input("33[34;1mPlease input the account that you want to lock:33[0m")
        read_data = lock_accountcore(account)
        return read_data
    def lock_accountcore(account):
        '''
        冻结账户,读取用户文件,读到status,把状态更改为1
        #0 = naormal,1 = locked ,
        :param account:
        :return:
        '''
        # 调用db_handle下的handle方法,返回路径/db/accounts
        db_path = db_handler.db_handler(settings.DATABASE)
        account_file = '%s/%s.json' % (db_path, account)
        account_new = '%s/%s.json' % (db_path, account)
        if os.path.isfile(account_file):
            with open(account_file, 'r', encoding='utf-8') as f:
                account_data = json.load(f)
                account_data['status'] = 1
            with open(account_new, 'w', encoding='utf-8') as fnew:
                new_data = json.dump(account_data, fnew)
    
    # 添加账户
    def add_account():
        '''
        添加账户,是admin添加的用户,下次就可以登陆添加的账户了
        :return:
        '''
        acc_dic = {
            'id':None,
            'balance':None,
            'password': None,
            'credit': None,
            'enroll_date': None,
            'expire_date': None,
            'status': None  # 0 = naormal,1 = locked , 2 = disabled
        }
        menu = {
            0:"请输入要添加的账户:",
            1:"请输入要添加的余额:",
            2:"请输入要添加的密码:",
            3:"请输入要添加的信用额度(only more than 0)",
            4:"请输入要添加的办卡日期(such as 2018-8-8)",
            5:"请输入要添加的卡到期时间(such as 2018-8-8)",
            6:"请输入是否锁定添加账号的状态(only input 0 or 1)",
        }
        menu_user = {
            0: "id",
            1: "balance",
            2: "password",
            3: "credit",
            4: "enroll_date",
            5: "expire_date",
            6: "status",
        }
        print("33[31;1m		welcome to add account33[0m")
        print('*'.center(40,'*'))
        for i in range(7):
            data = input('%s'%menu[i]).strip()
            acc_dic["%s" % menu_user[i]] = data
        accounts.dump_account(acc_dic)
        print("33[32;1mcongratulations  you account was created successfully33[0m")
        return True
    # 退出程序
    def logout():
        '''
        退出登陆
        :return:
        '''
        print("33[32;1m-------Looking forward to your next visit-------33[0m")
        exit()
    
    def auth_login():
        '''
        登陆管理员密码账号
        :return:
        '''
        print("33[34;1m-------Welcome into the management interface--------33[0m")
        managename = input("33[34;1mplease input Username:33[0m")
        password = input("33[34;1mplease input Password:33[0m")
        account = account_auth(managename,password)
        return account
    
    def account_auth(managename,password):
        '''
        管理员认证信息
        {"id": admin,"password": "root" }
        :return:
        '''
        db_path = db_handler.db_handler(settings.DATABASE)  # 调用db_handle下的handle方法,返回路径/db/accounts
        managename_file = '%s/%s.json'%(db_path,managename)
        if os.path.isfile(managename_file):
            with open(managename_file,'r',encoding='utf-8') as f:
                manage_data = json.load(f)
                # print(manage_data)
                if manage_data['password'] == password:
                    print("33[31;1m-------Welcome to the administrator--------33[0m")
                    return manage_interactive(managename)
                else:
                    print("33[31;1mAccount or Passwordoes not correct!33[0m")
    
    # 管理界面主程序
    def manage_interactive(managename):
        menu = '''
        33[31;1m-----------management console-----------
                1,add_account         
                2,lock_account
                3,unblock_account
                4, exit33[0m'''
        menu_dic = {
        '1':add_account,
        '2':lock_account,
        '3':unlock_account,
        '4': logout
        }
        exit_flag = False
        while not exit_flag:
            print(menu)
            user_option = input('please input your choice>>>').strip()
            if user_option in menu_dic:
                print(menu_dic[user_option]())
    
            else:
                print("33[31;1mYou choice doesn't exist!33[0m")
    
    def run_manage():
        '''
        当程序启动的时候调用,主要用于实现主要交互逻辑,客户认证登陆
        :return:
        '''
        auth_login()
    

      

    core/tranction.py

    # _*_ coding: utf-8 _*_
    import json
    from conf import settings
    from core import accounts
    
    
    def make_transaction(log_obj,account_data,tran_type,amount,**others):
        '''
        处理所有的用户的交易
        :param log_obj:
        :param amount_data: user account data
        :param tran_type: transaction type
        :param amount: transaction amount
        :param other: mainly for logging usage
        :return:
        '''
        # 将字符串类型转换为float类型
        amount = float(amount)
        # tran_type   交易类型
        if tran_type in settings.TRANSACTION_TYPE:
            # 利息金额
            interest =amount * settings.TRANSACTION_TYPE[tran_type]['interest']
            old_balance = account_data['balance']
            if tran_type in settings.TRANSACTION_TYPE:
                # 利息金额
                interest = amount * settings.TRANSACTION_TYPE[tran_type]["interest"]
                # 用户原金额
                old_balace = account_data["balance"]
                if settings.TRANSACTION_TYPE[tran_type]['action'] == 'plus':
                    new_balance = float(old_balance) + amount + float(interest)
                elif settings.TRANSACTION_TYPE[tran_type]['action'] == 'minus':
                    new_balance = float(old_balance) - amount - float(interest)
                    # 做一个判断小于0的操作,减钱时对帐户金额进行检查,防止超额
                    if new_balance <0:
                        print('33[31;1mYour credit [%s] is not enough for this transaction'
                              '[%s]'%(account_data['credit'],(amount + interest),old_balance))
                        return
    
            account_data['balance'] = new_balance
            # 保存新的余额返回到文件中
            accounts.dump_account(account_data)
            log_obj.info("account:%s   action:%s  amount:%s  interest:%s "
                         %(account_data['id'],tran_type,amount,interest))
            return account_data
        else:
            print("33[31;1mTransaction type [%s] is not exist33[0m"%tran_type)
    

      

    db/account_sample/py(此处只举一个例子)

    # _*_ coding: utf-8 _*_ 
    
    import json
    
    acc_dic = {
        'id':1234,
        'password':'abc',
        'credit':15000,
        'balance':15000,
        'enroll_date':'2018-01-01',
        'expire_date':'2023-01-01',
        # 'pay_day':22,  #支付日期(但是现在没有要求,可以不考虑)
        'status':0      #0 = naormal,1 = locked , 2 = disabled
    }
    print(acc_dic,type(acc_dic))
    a = json.dumps(acc_dic)
    print(a,type(a))
    

      

    7.2 shopping代码

     shopping_main.py

    # _*_ coding: utf-8 _*_
    import datetime
    import os
    import json
    
    
    
    def auth_login():
        '''
        登陆密码账号
        :return:
        '''
        print("-------welcome to shopping_mall--------")
        username = input("33[32;1mplease input Username:33[0m")
        password = input("33[32;1mplease input Password:33[0m")
        account = account_auth(username,password)
    
        return account
    
    def account_auth(username,password):
        '''
        用户认证账户信息格式化读取模块,并验证账号密码是否正确
        :return:
        '''
        username_file = '%s.json'%username
        if os.path.isfile(username_file):
            with open(username_file,'r',encoding='utf-8') as f:
                username_data = json.load(f)
                if username_data['password'] == password:
                    balance = username_data['balance']
                    print("33[32;1myou balance is %s33[0m"% balance)
                    return account_shopping(username,balance)
                else:
                    print("33[31;1mAccount or Passwordoes not correct!33[0m")
    
    def account_shopping(username,balance):
        '''用户购物操作
        这次只能买一件东西,不能重复买
        '''
        goods = [
            {"name": "电脑", "price": 6999},
            {"name": "鼠标", "price": 300},
            {"name": "游艇", "price": 2000},
            {"name": "美女", "price": 9980},
        ]
        print("*".center(40, '*'))
        print("goods".center(40, '-'))
        for index,item in enumerate(goods):
            print(index,item)
        print('end'.center(40,'-'))
        while True:
            choice = input("请输入要想购买的商品编号(或者按q直接退出):")
            if choice.isdigit():  #判断是否为数字
                choice = int(choice)
                if choice>=0 and choice<len(goods):   #判断是否在商品范围里面
                    choice_goods = goods[choice].get('name')
                    print("you will buy 33[32;1m%s33[0m"%choice_goods)
                    if balance > goods[choice].get('price'):
                        new_balance = balance - goods[choice].get('price')
                        print("now your balance is 33[32;1m%s33[0m"% new_balance)
                    else:
                        print("sorry your balance is 33[32;1m%s33[0m,unable to purchase" %balance)
                        continue
                else:
                    print("33[31;1mplease input the correct goods number33[0m")
            elif choice == 'q':
                exit()
    
            return write_data(username,new_balance)
    
    
    def write_data(username, new_balance):
        '''
        买了东西之后,余额信息更新一下
        :param username: 用户姓名
        :param new_balance: 余额信息
        :return:
        '''
        username_file = '%s.json' % username
        usernew_file = '%s.json' % username
        f =  open(username_file, 'r', encoding='utf-8')
        username_data = json.load(f)
        username_data['balance'] = new_balance
        f.close()
        fnew = open(usernew_file, 'w', encoding='utf-8')
        new_data = json.dump(username_data,fnew)
    
        fnew.close()
    
    
    def run_shopping():
        '''
        当程序启动的时候,调用,主要用于实现主要交互逻辑,客户认证登陆函数
        :return:
        '''
        userdata = auth_login()
    
    
    
    
    
    def account_recharge(balance):
        '''用户充值操作,此思路是接ATM'''
        recharge_money = input("please input recharge money: ")
        recharge_money =int(recharge_money)
        balance = balance + recharge_money
        print("Congratulations. Recharge success. balance is 33[32;1m%s33[0m" %balance)
    
        return balance
    
    def legout():
        '''
        退出程序
        :return:
        '''
        print("33[32;1m-------Looking forward to your next visit-------33[0m")
        exit()
    
    def interactive(acc_data):
        '''
        用户交互
        :param acc_data:
        :return:
        '''
        msg = (
            '''
            ------------------SHOPPING INFO --------------
                            33[31;1m1.购物
                            2.充值
                            3.退回
            33[0m'''
        )
        menu_dic = {
            "1": account_shopping,
            "2": account_recharge,
            "3": legout,
    
        }
        exit_flag = False
        while not exit_flag:
            print(msg)
            user_choice = input(">>>>").strip()
            if user_choice in menu_dic:
                menu_dic[user_choice]()
            else:
                print("33[31;1mYou choice doesn't exist!33[0m")
    
    def manage_accountauth():
        '''
        管理员账户认证函数,
        :return:
        '''
        manage_account = []
        with open('manageinfo.txt', 'r', encoding='utf-8') as f:
            for i in f.readlines():
                i_space = i.replace('
    ', '')
                manage_account.append(i_space)
    
        return manage_account
    
    def account_balance():
        '''
        账户余额信息格式化读取模块
        :return:
        '''
        balance = []
        with open('account_balance.txt', 'r', encoding='utf-8') as f:
            for i in f.readlines():
                i_space = i.replace('
    ', '')
                balance.append(i_space)
    
        return balance
    
    def account_save(account,cash):
        '''
        把账户及其余额信息持久化到本地,以消除文件内容,然后以读写的方式打开文件
        :param account: 用户信息
        :return:
        '''
        save_info = open('account_balance.txt','w+',encoding='utf-8')
        save_info.write(account)
        save_info.write('
    ')
        save_info.write(str(cash))
        save_info.close()
    
    def account_auth_changshi(username,password):
        '''
        用户认证账户信息格式化读取模块,尝试登陆三次,
        {"id": 123,"password": "123", "balance": 20000 }
        :return:
        '''
        retry_count = 0
        while username_data['password'] is not True and retry_count <3:
            username_file = '%s.json'%username
            if os.path.isfile(username_file):
                with open(username_file,'r',encoding='utf-8') as f:
                    username_data = json.load(f)
                    print(username_data['password'])
                    print(password)
                    if username_data['password'] == password:
                        return account_shopping
                    else:
                        print("33[31;1mAccount or Passwordoes not correct!33[0m")
            retry_count += 1
        else:
            print("Account [%s] try logging too many times..." % username)
            exit()
    

      

    shopping_run.py

    # _*_ coding: utf-8 _*_
    import os
    import sys
    
    #添加环境变量
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))   #找到路径
    sys.path.append(BASE_DIR)          #添加路径
    
    
    
    
    from shopping import shopping_main
    '''购物车程序的执行文件'''
    
    if __name__ == '__main__':
        shopping_main.run_shopping()
    

      

     

                                                                                                                  

  • 相关阅读:
    mysql锁表与解锁
    问题汇总
    安装一台Centos7桌面版的跳板机
    Centos7二进制部署k8s-v1.20.2 ipvs版本(部署mysql、nacos)
    Centos7二进制部署k8s-v1.20.2 ipvs版本(Prometheus监控k8s)
    CV2 安装异常
    PostgreSQL VACUUM 没有效果(无法清理死元组)的原因
    SQL Server 进程运行状态解析
    mysql 几种启动和关闭mysql服务的方法和区别
    MySQL学习(九)小结(转载)
  • 原文地址:https://www.cnblogs.com/wj-1314/p/7501455.html
Copyright © 2020-2023  润新知