模拟实现一个ATM + 购物商城程序
记得上次小编上传了一个购物车程序,这次呢稍微复杂一点,还是那句话,上传在这里不是为了炫耀什么,只是督促小编学习,如果大神有什么意见和建议,欢迎指导。
于2018.3.11开始动笔,继续完成这个项目。
一,需求:模拟实现一个ATM + 购物商城程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 要求如下: 1.额度15000或者自定义 2.实现购物商城,买东西加入购物车,调用信用卡接口结账 3.可以提现,手续费5% 4.支持多账户登陆 5.支持账户间转账 6.记录每月日常消费流水 7.提供还款接口 8.ATM记录操作日志 9.提供管理接口,包括添加账户,用户额度,冻结账户等 10.用户认证用装饰器 |
二,分析功能需求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ATM的角色: 管理员功能: 1 ,增删改查,加钱,减钱 2 ,记录日志 3 ,基本信息 4 ,额度 15000 普通用户功能: 1 ,可以提现,手续费 5 % 2 ,支持多账户登录 3 ,支持账户间转账 4 ,记录每月日常消费流水 5 ,提供还款接口 6 ,ATM记录操作日志 购物车程序: 1 ,可以进入程序购买商品 2 ,支持多账户登录 3 ,购完东西显示余额和购买的东西 |
三,文件创建
文件的创建是有开发规范的,比如下面:
1 2 3 4 5 6 7 8 9 | bin 用于执行可执行文件 conf 配置文件 core 用于存放核心代码 db 用于存放用户数据 log 日志,记录相关信息 |
四,思路流程图
五,简要说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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文件执行则可以对用户进行管理,解冻用户、冻结用户、申领新卡等操作 ①添加账户 ②冻结账户 ③解冻账户 ④退出 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 概述 本次作业文件夹一共包含了以下 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # _*_ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # _*_ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # _*_ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # _*_ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | # _*_ 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 ( "\033[32;1msorry your account was locked\033[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}:\033[32;1m{:^20}\033[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 ( "\033[32;1mInput repay amout(input 'b' is back):\033[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 ( '''\033[34;1mNEW Balance:%s\033[0m''' % (new_balance['balance'])) elif repay_amount = = 'b' : back_flag = True else : print ( "\033[31;1m%s is not valid amount ,Only accept interger!\033[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 ( "\033[33;1mInput withdraw amout(input 'b' is back):\033[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 ( '''\033[32;1mNEW Balance:%s\033[0m''' % (new_balance['balance'])) elif withdraw_amount = = 'b' : back_flag = True else : print ( '\033[31;1m[%s] is not a valid amount , only accept integer\033[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 ( "\033[33;1mInput transfer amount(input 'b' is back):\033[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 ( '''\033[32;1mNEW Balance:%s\033[0m''' % (new_balance['balance'])) elif transfer_amount = = 'b' : back_flag = True else : print ( '\033[31;1m[%s] is not a valid amount , only accept integer\033[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 ( "\033[32;1m-------Looking forward to your next visit-------\033[0m" ) exit() def interactive(acc_data): ''' 用户交互 :return: ''' msg = ( ''' ------------------CHINA BANK -------------- \033[31;1m1.账户信息 2.存款 3.取款 4.转账 5.账单 6.退出 \033[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 ( "\033[31;1mYou choice doesn't exist!\033[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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | # _*_ 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 ( "\033[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 ( "\033[31;1mAccount or Passwordoes not correct!\033[0m" ) else : #用户不存在 log_obj.error( "Account [%s] does not exist!" % account) print ( "\033[31;1mAccount [%s] does not exist!\033[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 ( '\033[32;1mplease input Acount:\033[0m' ).strip() password = input ( '\033[32;1mplease input Password:\033[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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # _*_ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # _*_ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | # _*_ 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 ( "\033[34;1mPlease input the account that you want to unlock:\033[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 ( "\033[34;1mPlease input the account that you want to lock:\033[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 ( "\033[31;1m\t\twelcome to add account\033[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 ( "\033[32;1mcongratulations you account was created successfully\033[0m" ) return True # 退出程序 def logout(): ''' 退出登陆 :return: ''' print ( "\033[32;1m-------Looking forward to your next visit-------\033[0m" ) exit() def auth_login(): ''' 登陆管理员密码账号 :return: ''' print ( "\033[34;1m-------Welcome into the management interface--------\033[0m" ) managename = input ( "\033[34;1mplease input Username:\033[0m" ) password = input ( "\033[34;1mplease input Password:\033[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 ( "\033[31;1m-------Welcome to the administrator--------\033[0m" ) return manage_interactive(managename) else : print ( "\033[31;1mAccount or Passwordoes not correct!\033[0m" ) # 管理界面主程序 def manage_interactive(managename): menu = ''' \033[31;1m-----------management console----------- 1,add_account 2,lock_account 3,unblock_account 4, exit\033[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 ( "\033[31;1mYou choice doesn't exist!\033[0m" ) def run_manage(): ''' 当程序启动的时候调用,主要用于实现主要交互逻辑,客户认证登陆 :return: ''' auth_login() |
core/tranction.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | # _*_ 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 ( '\033[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 ( "\033[31;1mTransaction type [%s] is not exist\033[0m" % tran_type) |
db/account_sample/py(此处只举一个例子)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # _*_ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | # _*_ coding: utf-8 _*_ import datetime import os import json def auth_login(): ''' 登陆密码账号 :return: ''' print ( "-------welcome to shopping_mall--------" ) username = input ( "\033[32;1mplease input Username:\033[0m" ) password = input ( "\033[32;1mplease input Password:\033[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 ( "\033[32;1myou balance is %s\033[0m" % balance) return account_shopping(username,balance) else : print ( "\033[31;1mAccount or Passwordoes not correct!\033[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 \033[32;1m%s\033[0m" % choice_goods) if balance > goods[choice].get( 'price' ): new_balance = balance - goods[choice].get( 'price' ) print ( "now your balance is \033[32;1m%s\033[0m" % new_balance) else : print ( "sorry your balance is \033[32;1m%s\033[0m,unable to purchase" % balance) continue else : print ( "\033[31;1mplease input the correct goods number\033[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 \033[32;1m%s\033[0m" % balance) return balance def legout(): ''' 退出程序 :return: ''' print ( "\033[32;1m-------Looking forward to your next visit-------\033[0m" ) exit() def interactive(acc_data): ''' 用户交互 :param acc_data: :return: ''' msg = ( ''' ------------------SHOPPING INFO -------------- \033[31;1m1.购物 2.充值 3.退回 \033[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 ( "\033[31;1mYou choice doesn't exist!\033[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( '\n' , '') 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( '\n' , '') 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( '\n' ) 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 ( "\033[31;1mAccount or Passwordoes not correct!\033[0m" ) retry_count + = 1 else : print ( "Account [%s] try logging too many times..." % username) exit() |
shopping_run.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # _*_ 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() |
不经一番彻骨寒 怎得梅花扑鼻香
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步