作业需求及初步思路
需求 | 思路 | |
1 | 自定义信用卡额度 e.g 15000 | 见下数据存储模式 |
2 | 实现购物商城,买东西加入购物车,调用信用卡结构结账 | 改下购物车的扣款接口 |
3 | 可以提现,手续费5% | 【提现】注意有利息,同时打印日志 |
4 | 支持多账户登陆(admin, client) |
【信用卡中心】for client 【管理员中心】for admin |
5 | 支持账户间转账 | 【转账】打印日志 |
6 | 记录每月日常消费流水 | 【消费流水】transaction.log; 呈现购物车消费,提现,转账,还款的日志 |
7 | 提供还款结构 | 【还款】 |
8 | ATM记录操作日志 | access.log; 呈现账户操作日志 |
9 | 提供管理接口(admin),包括添加账户、用户额度、冻结账户等 | 【管理员中心】 |
10 | 用户认证用装饰器 | 登陆之后,在其他接口时,用于验证登陆状态 |
知识点
1. 程序的解耦:以下引用知乎的一个解释
解耦即增加正交性,通俗的讲就是减少模块间的互相干扰,让各个模块的修改变化尽可能小的影响其它模块。
完全不耦合是不可能的,完全不耦合的程序不可能进行数据和指令的传递与交换。
解耦的基本方法是面向接口进行开发,也就是说各个模块只和接口发生耦合,要么调用接口要么实现接口,因此接口本身的设计是程序模块化的重中之重,大型程序中接口设计的优劣常常直接决定整个系统的优劣。
一个常见且基本的例子是图形处理。在正交的程序中,当你得到一个shape对象,可以通过该对象的draw方法直接把它画出来,而不必关心它实际上是一个 circle,rectangle,还是triangle。而在一个非正交的程序中,你必须分别知道它们的圆心位置和半径,长和宽,各顶点位置等信息再进行具体的绘制。简单说,前一种情况只依赖了draw方法,而后一种情况需要依赖各个图形的具体参数。在ATM作业中,比较典型的解耦例子:auth 和 transaction
2. 多线程操作下的文件存储方式:每个client account 建立一个 json文件。 目的是,当某个用户在操作账户时,另一个客户也可以同时操作更改账户信息。
3. 数据类型接口: 为了能够对接不同的数据库,一般设置鉴别数据存贮的方式。 具体操作是,在conf/settings中,设置以下database的字典。这种操作和Django里一样。 这样操作主要是为了任意更换数据库类型, 可以是file, mysql, postegresal等。
DATABASE = dict(engine="file_storage", # engine为数据库类型;可扩张成不同数据源如mysql, postegresal等 database_path= os.path.join(BASE_DIR,"database"), # 数据库路径 name="accounts") # 数据库名称,每个数据库一个json文件,为了支持多线程操作。
数据库接口代码如下:
但是,写数据库接口 db api 中,要注意统一不同数据库的解析语言(mysql)。接口对象有:
4. logging 模块: 写入不同的文件(handler); 读取日志,有条件地读取日志信息(show_logger)
MY WORK
#!usr/bin/env python #-*- 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 main if __name__ == '__main__': main.sys_run()
#!usr/bin/env python #-*- coding:utf-8 -*- import os, sys, logging # 主程序目录 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 数据库 DATABASE = dict(engine="file", # engine为数据库类型;可扩张成不同数据源如mysql, postegresal等 database_path= os.path.join(BASE_DIR,"database"), name="accounts") # 数据库名称,每个数据库一个json文件,为了支持多线程操作。 # 日志 LOG_LEVEL = logging.INFO LOG_TYPES = dict(transactions="transactions.log", access="access.log") LOG_DATABASE = dict(engine="file", # 可扩张成不同数据源如mysql, postegresal等 database_path= os.path.join(BASE_DIR,"log"), name="accounts") # 参数 BILL_DAY = 22 TRANSACTION_TYPE = { 'repay': {'action': 'plus', 'interest': 0}, # 还款 'receive': {'action': "plus", 'interest': 0}, # 接收 'withdraw': {'action': 'minus', 'interest':0.05}, # 提款 'transfer': {'action': 'minus', 'interest':0.05}, # 转出 'pay': {'action': 'minus', 'interest': 0}, # 支付 } SHOPPING_MENU = {'海鲜水产': {'竹节虾': {'单价': 68, '数量': 5}, '面包蟹': {'单价': 75, '数量': 5}, '石斑鱼': {'单价': 50, '数量': 5}, '活蛏子': {'单价': 20, '数量': 10} }, '新鲜水果': {'阳山水蜜桃': {'单价': 33, '数量': 5}, '8424西瓜': {'单价': 60, '数量': 5}, '巨峰葡萄': {'单价': 21, '数量': 5}, '仙居杨梅': {'单价': 40, '数量': 5}, '小台农芒果': {'单价': 13, '数量': 20} }, '肉禽蛋品': {'土鸡蛋': {'单价': 9, '数量': 4}, '澳洲上脑牛排': {'单价': 30, '数量': 5}, '黑毛猪小排': {'单价': 28, '数量': 5}, '澳洲冰鲜牛腩': {'单价': 45, '数量': 5}, '帝王鸡': {'单价': 100, '数量': 5} }, '乳制品': {'低脂鲜牛奶': {'单价': 17, '数量': 5}, '全脂牛奶': {'单价': 20, '数量': 4}, '酸奶': {'单价': 21, '数量': 2} } }
#!usr/bin/env python #-*- coding:utf-8 -*- OPEN_WIN = ''' |------------------------------------MyBank\'s ATM SYSTEM--------------------------------------| | | | 1. Admin | | 2. Existing Client | | | | Please contact our local service counter for a new credit card application. | |----------------------------------------------------------------------------------------------| ''' CLIENT_WIN = ''' |------------------------------------MyBank\'s ATM SYSTEM--------------------------------------| | Dear {}, | | 1. Online Shopping 2. My Account 3. Repayment | | 4. Withdrawal 5. Transfer 6. Account Statement | | 7. Log Out | | | |----------------------------------------------------------------------------------------------| ''' ADMIN_WIN = ''' |------------------------------------MyBank\'s ATM SYSTEM--------------------------------------| | Dear {}, | | 1. Create 2. Reactivate 3. Freeze | | 4. Credit update 5. Log Out | | | | | |----------------------------------------------------------------------------------------------| ''' STATEMENT_TEMP = ''' |---------------------------------------------------STATEMENT REPORT----------------------------------------------------| Dear {}, Your desired reporting period: \033[31;1m{}\033[0m to \033[31;1m{}\033[0m |-----------------------------------------------------------------------------------------------------------------------| ''' SHOPPING_WIN = ''' |--------------------------MyBank\'s Online Shopping Mall--------------------------------------| | Dear {}, | | 1. Shopping 2. Historical shopping log | | | | | |----------------------------------------------------------------------------------------------| '''
1 #!usr/bin/env python 2 #-*- coding:utf-8 -*- 3 4 import os,json,datetime 5 from conf import settings 6 from core import db_handler 7 from core import update_acc_info 8 from core import logger 9 10 def login(user_data, log_type): 11 ''' 12 系统登录,将读取的json信息作为account_data 更新到user_data 字典中去 13 :param user_data: from main 14 :return: 15 ''' 16 login_count = 0 17 max_count = 3 18 account_id = input("Accout ID: ").strip() 19 while user_data["is_authenticated"] is not True: 20 if login_count < max_count: 21 password = input("Password: ").strip() 22 acc_file = "%s.json" % account_id 23 db_file_path = db_handler.db_handler(settings.DATABASE) 24 acc_path = os.path.join(db_file_path, acc_file) # 获取单个acc 路径,支持多线程操作 25 if os.path.isfile(acc_path): 26 with open(acc_path, "r+", encoding="utf-8") as f: 27 account_data = json.load(f) 28 if account_data["password"] == password: 29 exp_date_stamp = datetime.datetime.strptime(account_data["expire_date"], "%Y-%m-%d") 30 acc_status = account_data["status"] 31 if acc_status == 0 or acc_status == 8: 32 if exp_date_stamp < datetime.datetime.today(): 33 print("Your account is expired. please contact admin for renew.") 34 else: 35 return account_data 36 else: 37 exit("Your account is frozen. Please contact admin for updates") 38 else: 39 print("Incorrect password ") 40 login_count +=1 41 continue 42 else: 43 exit("Account does not exit! Please contact admin") 44 else: 45 log_type.error("account is frozen for trying too many times") 46 account_data = update_acc_info.load_account(account_id) 47 account_data["status"] = 2 48 update_acc_info.dump_account(account_data) 49 exit()
1 #!usr/bin/env python 2 #-*- coding:utf-8 -*- 3 4 import datetime 5 from conf import settings 6 7 def get_bill_date(year_month): 8 ''' 9 获取账单时间内的账单。每月账单日22日 10 :param year_month_date: 11 :return: 12 ''' 13 bill_day = "%s-%s" % (year_month, settings.BILL_DAY) 14 bill_bday = datetime.datetime.strptime(bill_day, "%Y-%m-%d") 15 year = bill_bday.year 16 month = bill_bday.month 17 if month == 12: 18 year +=1 19 month =1 20 else: 21 month +=1 22 bill_eday = datetime.datetime(year, month, settings.BILL_DAY) 23 return bill_bday,bill_eday
1 #!usr/bin/env python 2 #-*- coding:utf-8 -*- 3 4 5 def db_handler(conn_params): 6 ''' 7 数据库接口解析。可扩展到mysql, postgresql等其他数据库方式。现在只用file 存储 8 :param conn_params: settings.DATABASE 9 :return: file读取,返回数据库路径 10 ''' 11 if conn_params["engine"] == "file": 12 return conn_params["database_path"] 13 else: 14 print('Current system does not support other databases')
1 #!usr/bin/env python 2 #-*- coding:utf-8 -*- 3 4 import logging 5 import os 6 import datetime 7 from conf import settings 8 from conf import templates 9 from core import billdate 10 11 def logger(log_type): 12 ''' 13 写日志到屏幕和不同文件 14 :param log_type: transaction 或 access 15 :return: 16 ''' 17 # 创建logger 18 logger = logging.getLogger(log_type) 19 logger.setLevel(settings.LOG_LEVEL) 20 21 # 屏幕handler 22 ch = logging.StreamHandler() 23 ch.setLevel(settings.LOG_LEVEL) 24 25 # 文件handler 26 log_file = os.path.join(os.path.join(settings.BASE_DIR,"log"),settings.LOG_TYPES[log_type]) 27 fh = logging.FileHandler(log_file) 28 fh.setLevel(settings.LOG_LEVEL) 29 30 # handler输出的格式设置 31 formatter = logging.Formatter("%(asctime)s-%(name)s-%(levelno)s-%(message)s") 32 33 # 关联handler和formatter 34 ch.setFormatter(formatter) 35 fh.setFormatter(formatter) 36 37 # 告诉logger输出不同的handler 38 logger.addHandler(ch) 39 logger.addHandler(fh) 40 41 return logger 42 43 44 def show_logger(acc_id, log_obj, year_month): 45 ''' 46 47 :param acc_id: 48 :param log_obj: 49 :param year_month: 50 :return: 51 ''' 52 53 bill_bday, bill_eday = billdate.get_bill_date(year_month) 54 print(templates.STATEMENT_TEMP.format(acc_id, bill_bday, bill_eday)) 55 log_path = os.path.join(settings.LOG_DATABASE["database_path"], settings.LOG_TYPES[log_obj]) 56 with open(log_path,"r+", encoding="utf-8") as file: 57 for i in file: 58 log_time = datetime.datetime.strptime(i.split(",")[0], "%Y-%m-%d %H:%M:%S") 59 account_id = i.split("-")[5].split(":")[1] 60 if acc_id == account_id and bill_bday <= log_time < bill_eday: 61 print(i) 62 print("")
1 #!usr/bin/env python 2 #-*- coding:utf-8 -*- 3 4 import os, sys, json 5 from prettytable import PrettyTable 6 from conf import settings 7 from conf import templates 8 from core import auth 9 from core import shopping 10 from core import logger 11 from core import transaction 12 from core import update_acc_info 13 14 15 TRANSACTION_LOGGER = logger.logger("transactions") 16 ACCESS_LOGGER = logger.logger("access") 17 18 # 登陆成功后,将信息更新入tmp USER_DATA 19 USER_DATA = { 20 "account_id": None, 21 "is_authenticated": False, # 在客户进行不同操作时,都需要验证是否登陆 22 "account_data": None # json文件信息 23 } 24 25 def verify(func): 26 ''' 27 装饰器,每次在客户转账,还款,取现等现金操作时,验证是已经登陆。 28 :param func: 29 :return: 30 ''' 31 def wrapper(*args,**kwargs): 32 if USER_DATA["is_authenticated"]: 33 res = func(*args,**kwargs) 34 else: 35 print("please log in again!") 36 return wrapper 37 38 @verify 39 def shopping_menu(acc_data): 40 ''' 41 购物车 42 :param acc_data: 43 :return: 44 ''' 45 shopping.shopping(acc_data) 46 47 48 # 写日志 49 def get_acc_info(acc_data): 50 ''' 51 client function 2: 获取账户信息 52 :param acc_data: 53 :return: 54 ''' 55 print("2.account information") 56 table = PrettyTable(["Account Id", "Credit", "Current Balance", "Expired Date"]) 57 table.add_row( 58 [acc_data["id"], acc_data["credit"], acc_data["balance"], acc_data["expire_date"]]) 59 print(table) 60 client_portal() 61 62 63 @verify 64 def repayment(acc_data): 65 ''' 66 打印current balance, 并且还款 67 :param acc_data: 68 :return: 69 ''' 70 table = PrettyTable(["Account Id", "Credit", "Current Balance"]) 71 table.add_row([acc_data["id"],acc_data["credit"], acc_data["balance"]]) 72 print(table) 73 back_flag = False 74 while not back_flag: 75 repay_amount = input("\033[33;1mPlease input repay amount\033[0m or press [b] for back").strip() 76 if len(repay_amount) > 0 and repay_amount.isdigit(): 77 n_acc_data = transaction.transaction(acc_data, TRANSACTION_LOGGER, "repay", repay_amount) 78 new_balance = n_acc_data["balance"] 79 if new_balance: 80 print("Your credit card has been repaid. Current balance is %s" % acc_data["balance"]) 81 client_portal() 82 elif repay_amount == "b": 83 back_flag = True 84 else: 85 print("Please input a valid number") 86 back_flag = True 87 88 @verify 89 def withdrawal(acc_data): 90 ''' 91 取款 92 :param acc_data: 93 :return: 94 ''' 95 print("Current balance: %s" % acc_data["balance"]) 96 back_flag = False 97 while not back_flag: 98 withdraw_amount = input("\033[33;1mPlease input amount for withdrawal\033[0m or press [b] for back>>>").strip() 99 if len(withdraw_amount) > 0 and withdraw_amount.isdigit(): 100 n_acc_data= transaction.transaction(acc_data, TRANSACTION_LOGGER, "withdraw", withdraw_amount) 101 new_balance = n_acc_data["balance"] 102 print("You have withdrawn %s and your current balance is %s" %(withdraw_amount, new_balance)) 103 client_portal() 104 elif withdraw_amount == "b": 105 back_flag = True 106 else: 107 print("Please input a valid number") 108 back_flag = True 109 110 111 @verify 112 def transfer(acc_data): 113 ''' 114 转账 115 :param acc_data: 116 :return: 117 ''' 118 print("Current balance: %s" % acc_data["balance"]) 119 back_flag = False 120 while not back_flag: 121 transferee_acc_id = input('press [b] for back or please input transferee\'s account id:').strip() 122 transfer_amount = input("\033[33;1mPlease input amount for transfer(extra 5% transaction fee)\033[0m>>>").strip() 123 if len(transfer_amount) > 0 and transfer_amount.isdigit(): 124 transferee_acc_data = update_acc_info.load_account(transferee_acc_id) 125 transaction.transaction(acc_data, TRANSACTION_LOGGER, "transfer", transfer_amount) 126 transaction.transaction(transferee_acc_data,TRANSACTION_LOGGER,"receive", transfer_amount) 127 print("Successfully transferred. ") 128 client_portal() 129 elif transferee_acc_data == "b": 130 back_flag = True 131 else: 132 print("Please input a valid number") 133 continue 134 135 136 def statement(acc_data): 137 ''' 138 查询账单 139 :param acc_data: 140 :return: 141 ''' 142 143 back_flag = False 144 while not back_flag: 145 bill_month = input("Please input your desired year-month (e.g. 2001-02) or press [b] for back >>>").strip() 146 if len(bill_month) > 6: 147 acc_id = acc_data["id"] 148 logger.show_logger(acc_id, "transactions", bill_month) 149 elif bill_month == "b": 150 back_flag = True 151 else: 152 print("Please input a valid year and month") 153 back_flag 154 155 def logout(acc_id): 156 exit("Thank you for your trust to MyBank!") 157 158 159 def get_user_data(): 160 account_data = auth.login(USER_DATA, ACCESS_LOGGER) # 登陆验证func 161 if account_data["status"] == 8: 162 exit("Please choose Admin portal!") 163 else: 164 USER_DATA["account_id"] = account_data["id"] 165 USER_DATA["account_data"] = account_data 166 USER_DATA["is_authenticated"] = True 167 return USER_DATA 168 169 170 def client_portal(): 171 ''' 172 客户接口, 登陆后更新USER_DATA。 173 :return: 174 ''' 175 if USER_DATA["is_authenticated"] == False: 176 get_user_data() 177 account_data = USER_DATA["account_data"] 178 else: 179 account_data = USER_DATA["account_data"] 180 181 client_menu = { 182 "1": shopping_menu, 183 "2": get_acc_info, 184 "3": repayment, 185 "4": withdrawal, 186 "5": transfer, 187 "6": statement, 188 "7": logout 189 } 190 print(templates.CLIENT_WIN.format(USER_DATA["account_id"])) 191 exit_flag = False 192 while not exit_flag: 193 client_option = input("Please select your action >>>").strip() 194 if client_option in client_menu: 195 client_menu[client_option](account_data) 196 else: 197 print("Invalid option. please try again.") 198 exit_flag = True 199 200 201 def admin_create(): 202 ''' 203 管理员新创建账户 204 :return: 205 ''' 206 print(" -------------Admin to creat a new account--------------") 207 acc_id = input("New Account ID >>>").strip() 208 acc_psd = input("Initial passward >>>").strip() 209 acc_cc = str(input("New credit card # >>>").strip()) 210 acc_credit = input ("Initial credit >>>").strip() 211 enroll_date = str(input("Enroll date (e.g. 2000-01-01)>>>").strip()) 212 expire_date = str(input("Expired date (e.g. 2005-01-01) >>>").strip()) 213 account_dict = { 214 "id": acc_id, 215 "password": acc_psd, 216 "credit_card": acc_cc, 217 "credit": acc_credit, 218 "balance": 0, 219 "enroll_date": enroll_date, 220 "expire_date": expire_date, 221 "billing_day": 22, 222 "status": "0" # 0 = normal, 1 = locked, 2 = disabled, 8 = admin 223 } 224 acc_file = "%s.json" %acc_id 225 acc_path = os.path.join(settings.DATABASE["database_path"], acc_file) 226 with open(acc_path, "w", encoding="utf-8") as f: 227 json.dump(account_dict,f) 228 229 230 def admin_reactivate(): 231 """ 232 激活 233 :return: 234 """ 235 back_flag = False 236 while not back_flag: 237 acc_id = input("please input the account id you want to reactivate>>>") 238 acc_data = update_acc_info.load_account(acc_id) 239 reconfirm_msg = input("please reconfirm you want to reactivate the account (Y/N) or press [b] for back >>>").strip() 240 if reconfirm_msg == "Y": 241 acc_data["status"] = "0" 242 update_acc_info.dump_account(acc_data) 243 print("The account has been unlocked") 244 elif reconfirm_msg == "b": 245 back_flag = True 246 else: 247 print("Reactivation failed") 248 back_flag = True 249 250 251 def admin_freeze(): 252 ''' 253 冻结 254 :return: 255 ''' 256 back_flag = False 257 while not back_flag: 258 acc_id = input("please input the account id you want to freeze>>>") 259 acc_data = update_acc_info.load_account(acc_id) 260 reconfirm_msg = input("please reconfirm you want to freeze the account (Y/N) or press [b] for back>>>").strip() 261 if reconfirm_msg == "Y": 262 acc_data["status"] = "2" 263 update_acc_info.dump_account(acc_data) 264 elif reconfirm_msg == "b": 265 back_flag = False 266 else: 267 print("Freeze failed") 268 back_flag = True 269 270 271 def admin_credit_update(): 272 ''' 273 更新信用额度 274 :return: 275 ''' 276 back_flag = False 277 while not back_flag: 278 acc_id = input("please input the account id you want to update the credit >>>") 279 acc_data = update_acc_info.load_account(acc_id) 280 new_credit = input("please input the new credit for {}".format(acc_id)).strip() 281 if len(new_credit)> 0 and new_credit.isdigit(): 282 acc_data["credit"] = new_credit 283 update_acc_info.dump_account(acc_data) 284 else: 285 print("Invalid input") 286 back_flag = True 287 288 289 def admin_portal(): 290 ''' 291 管理员入口 292 :return: 293 ''' 294 account_data = auth.login(USER_DATA, ACCESS_LOGGER) 295 admin_menu = { 296 "1": admin_create, 297 "2": admin_reactivate, 298 "3": admin_freeze, 299 "4": admin_credit_update, 300 "5": exit 301 } 302 exit_flag = False 303 while not exit_flag: 304 if account_data["status"] == 8: 305 print(templates.ADMIN_WIN.format(account_data["id"])) 306 admin_option = input("Your action >>>").strip() 307 if admin_option in admin_menu: 308 admin_menu[admin_option]() 309 else: 310 print("Invalid option. please try again.") 311 continue 312 else: 313 exit("Permission denied") 314 315 316 def sys_run(): 317 ''' 318 主程序窗口 319 :return: 320 ''' 321 print(templates.OPEN_WIN) 322 open_input = input('\033[31;1mYour choice >>>\033[0m ') 323 open_dic = { 324 "1": admin_portal, 325 "2": client_portal 326 } 327 if open_input in open_dic: 328 open_dic[open_input]() 329 else: 330 print("Invalid option. please try again.") 331 332 333 sys_run()
#!usr/bin/env python # -*- coding:utf-8 -*- import sys import json from conf import templates from conf import settings from core import update_acc_info from core import main def shopping(acc_data): # 购物 acc_id = acc_data["id"] print(templates.SHOPPING_WIN.format(acc_id)) menu_dict = settings.SHOPPING_MENU while True: for i in sorted(menu_dict): print(i) option1 = input('请选择\033[001m产品分类\033[0m 【b】返回 【任意键】退出').strip() # 001加粗 if option1 in menu_dict: print('{}清单如下:'.format(option1).rjust(25, '-')) for k in menu_dict[option1]: print(k, menu_dict[option1][k]) while True: option2 = input('请选择 \033[001m商品\033[0m 加入购物车【b】返回 【q键】退出 ').strip() if option2 in menu_dict[option1]: option3_num = input('请输入购买数量').strip() if option3_num.isdigit() and int(option3_num) <= menu_dict[option1][option2]['数量']: num = int(option3_num) price = menu_dict[option1][option2]['单价'] cost = num*price balance = acc_data["balance"] if cost <= balance: acc_data["balance"] = balance - cost update_acc_info.dump_account(acc_data) menu_dict[option1][option2]['数量'] -= num print("商品已购,您的最新余额为\033[34m%d\033[0m" % (acc_data["balance"])) break else: print('账户余额不足,请还款') main.client_portal() else: print("抱歉,商品数目不足") continue elif option2 == 'b': break elif option2 == 'q': sys.exit() else: print('错误信息,请重新选择') continue elif option1 == 'b': main.client_portal() else: sys.exit()
#!usr/bin/env python # -*- coding:utf-8 -*- from conf import settings from core import update_acc_info TRANSACTION_TYPE = { 'repay': {'action': 'plus', 'interest': 0}, # 还款 'receive': {'action': "plus", 'interest': 0}, # 接收 'withdraw': {'action': 'minus', 'interest':0.05}, # 提款 'transfer': {'action': 'minus', 'interest':0.05}, # 转出 'pay': {'action': 'minus', 'interest': 0}, # 支付 } def transaction(acc_data, log_obj, tran_type, amount, **other): ''' cover all money transactions listed in settings.TRANSACTION_TYPE :param acc_data: :param log_obj: :param tran_type: :param amount: :param other: :return: ''' amount = float(amount) transaction_type = settings.TRANSACTION_TYPE interest = amount * transaction_type[tran_type]["interest"] if transaction_type[tran_type]["action"] == "plus": new_balance = acc_data["balance"] + amount elif transaction_type[tran_type]["action"] == "minus": new_balance = acc_data["balance"] - amount - interest if new_balance < 0: print('Your current balance is %s, which may not be enough for this transaction' % acc_data["balance"]) acc_data["balance"] = new_balance update_acc_info.dump_account(acc_data) log_obj.info("ID:{}-Action:{}-Amount:{}-Interest:{}".format(acc_data["id"], tran_type, amount, interest)) return acc_data
1 #!usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # function: update any modifies or transaction into json file 4 \ 5 6 import os 7 import json 8 from conf import settings 9 from core import db_handler 10 11 def dump_account(acc_data): 12 ''' 13 存入文件 14 :param acc_data: 15 :return: 16 ''' 17 acc_file = "%s.json" % acc_data["id"] 18 db_file_path = db_handler.db_handler(settings.DATABASE) 19 acc_path = os.path.join(db_file_path, acc_file) 20 #print(acc_path) 21 with open(acc_path,"w+", encoding="utf-8") as f: 22 json.dump(acc_data,f) 23 return True 24 25 26 def load_account(acc_id): 27 ''' 28 读取文件,用于transfer 29 :param acc_id: 30 :return: 31 ''' 32 acc_file = "%s.json" % acc_id 33 db_file_path = db_handler.db_handler(settings.DATABASE) 34 acc_path = os.path.join(db_file_path, acc_file) 35 with open(acc_path, "r+", encoding="utf-8") as f: 36 acc_data = json.load(f) 37 return acc_data
#!usr/bin/env python #-*- coding:utf-8 -*- import json account_dict = { "id": "admin001", "password": "admin1", "credit_card": None, "credit": None, "balance": None, "enroll_date": "2000-01-01", "expire_date": "2999-12-31", "billing_day": 22, "status": "8" # 0 = normal, 1 = locked, 2 = disabled, 8 = admin } account_file = "%s.json" % account_dict["id"] with open(account_file, "w+") as f: json.dump(account_dict,f)
log\access.log
log\transaction.log
示例
sample 1: alex的列子
sample 2:大牛的例子(涉及类)