Python 基础 - Day 5 Assignment - ATM

作业需求及初步思路

 需求 思路 
1自定义信用卡额度 e.g 15000  见下数据存储模式
 2 实现购物商城,买东西加入购物车,调用信用卡结构结账 改下购物车的扣款接口 
3可以提现,手续费5%  【提现】注意有利息,同时打印日志 
4支持多账户登陆(admin, client)

【信用卡中心】for client

【管理员中心】for admin

5 支持账户间转账 【转账】打印日志 
 6记录每月日常消费流水 【消费流水】transaction.log; 呈现购物车消费,提现,转账,还款的日志 
 7提供还款结构 【还款】 
 8ATM记录操作日志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()
bin\atm.py

 

#!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}
                         }
                 }
conf\settings
#!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                             |
|                                                                                              |
|                                                                                              |
|----------------------------------------------------------------------------------------------|
'''
conf\templates
 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()
core\auth
 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
core\billdate
 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')
core\db_handler
 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("")
core\logger
  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()
core\main
#!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()
core\shopping
#!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
core\transaction
 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
update_acc_info
#!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)
database\test_accounts_dump

log\access.log

log\transaction.log

 

示例

sample 1:  alex的列子

sample 2:大牛的例子(涉及类)

转载于:https://www.cnblogs.com/lg100lg100/p/7527057.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值