前言:眼看基础知识要学完了。还是把之前丢掉的作业,拿回来重新做吧。再不做,担心后面跟不上进度了。光懂基础知识,开发不了软件,这就有点尴尬了。先找个案例抄一遍。搞清楚逻辑结构再说:.....................
一、程序需求
模拟实现一个ATM + 购物商城程序:
1.额度 15000或自定义
2.实现购物商城,买东西加入 购物车,调用信用卡接口结账
3.可以提现,手续费5%
4.每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息(没写)
5.支持多账户登录
6.支持账户间转账
7.记录每月日常消费流水
8.提供还款接口
9.ATM记录操作日志
10.提供管理接口,包括添加账户、用户额度,冻结账户等。。。
11.用户认证用装饰器
二、程序结构:
├── ATM #ATM主程目录 │ ├── __init__.py │ ├── bin #ATM 执行文件 目录 │ │ ├── __init__.py │ │ ├── atm.py #ATM 执行程序 │ │ ├── manage.py #信用卡管理 │ ├── conf #配置文件 │ │ ├── __init__.py │ │ └── Settings.py #配置参数 │ ├── core #主要程序逻辑都 在这个目录 里 │ │ ├── __init__.py │ │ ├── accounts.py #用于从文件里加载和存储账户数据 │ │ ├── auth.py #用户认证模块及主要功能函数 │ │ ├── db_handler.py #数据库连接引擎 │ │ ├── logger.py #日志记录模块 │ │ ├── main.py #主逻辑交互程序 │ │ ├── transaction.py #记账还钱取钱与账户金额相关的操作,冻结或者锁定用户 │ ├── db #用户数据存储的地方 │ │ ├── __init__.py │ │ ├── account_sample.py #生成一个初始的账户数据 ,把这个数据 存成一个 以这个账户id为文件名的文件,放在accounts目录 就行了,程序自己去会这里找 │ │ └── accounts #存各个用户的账户数据 ,一个用户一个文件 │ │ └── 123.json #新创建的用户账户示例文件 │ │ └── 1234.json #一个用户账户示例文件 │ │ └── 123456.json #一个用户账户示例文件 │ │ └── 6230001.json #管理用户账户示例文件 │ └── log #日志目录 │ ├── access.log #用户访问和操作的相关日志 │ └── login_in.log #登陆日志 └── shopping_mall #电子商城程序,需单独实现,主要实现购物的功能。 │ └── __init__.py │ └── product.txt #存放商品的txt文件 │ └── shopping_list.txt #存放购物清单的txt.文件 │ └── shopping_mall.py #购物商城程序 ├── README 目录
三、简要说明
1.程序从/bin/atm.py开始执行if __name__ == '__main__':
main.run()
2.程序转到/core/main.py下的run()函数,登陆时调用/core/auth的acc_login()进行登陆验证:用到了/core/auth下的acc_auth2()方法进行验证(此时传入的参数时用户输入的账户和密码)
acc_auth2中有调用了/core/db_handler下的db_handler()方法(参数是输入的账户名)在db_handler中只是进行判断是什么引擎,return file_db_handle(数据库引擎)解析文件,返回文件执行加载输入的用户的账户的所有数据
接下来判断是否为管理者账户,或者是否被冻结,若都不是,则判断输入的密码是否与数据库中的密码一样,在判断到期时间是否过期
所有都通过的话就返回这个账户的数据,之前已经创建了一个空字典,里面有是否验证:用户数据:用户账户:,判断是否被验证过,然后把用户数据临时的传递到里面,执行主循环函数
可以选择进入到购物商城,或者信用卡操作或者退出
1)购物商城
调用/shopping_mall/shopping_mall.py文件执行,主循环函数,选择你是商家还是用户,
①如果选择商家,商家有增加商品修改商品的功能
②如果选择用户,用户则有购物,刷信用卡消费的功能,当退出时打印消费清单
2)信用卡操作
调用/core/main.py下interactive(用户的所有数据)调用主循环函数,可以打印账户信息、还款、取款、转账、账单、退出等操作
①账户信息
②还款
③取款
④转账
⑤账单
⑥退出
3)若在账户登陆的时候进行输入的时管理员账户调用/bin/manage.py则可以对用户进行管理,解冻 用户、冻结用户、申领新卡
①添加账户
②冻结账户
③解冻账户
④退出
1 #!/usr/bin/python3 2 # -*- coding:utf-8 -*- 3 #__author:Administrator 4 #date:2018/7/14 5 import os,sys 6 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 7 8 sys.path.append(BASE_DIR) 9 10 from core import main 11 12 13 14 if __name__ == '__main__': 15 main.run()
1 #!/usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 ''' 4 Administrator 5 2018/8/13 6 ''' 7 import os,sys 8 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 9 #print(base_dir) 10 sys.path.append(BASE_DIR) 11 12 from core import main 13 14 15 if __name__ == '__main__': 16 main.goto_manage()
1 #!/usr/bin/python3 2 # -*- coding:utf-8 -*- 3 #__author:Administrator 4 #date:2018/7/14 5 6 #参数配置文件 7 import os,sys,logging 8 9 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#/Atm 10 11 DATABASE = { 12 'engine': 'file_storage', 13 'name': 'account', 14 'path': "%s/db" % BASE_DIR#../Atm 15 } 16 17 LOG_LEVEL = logging.INFO #记录等级 18 LOG_TYPES = { 19 'transaction': 'transaction.log', 20 'access': 'access.log' 21 } 22 23 #发生交易的配置类型 24 TRANSACTION_TYPE = { 25 'repay':{'action':'plus','interest':0},#还款 26 'withdraw':{'action':'minus','interest':0.05},#取现是降低可用余额 27 'transfer':{'action':'minus','interest':0.05},#转账是降低可用余额 28 'consume':{'action':'minus','interest':0}, #消费 29 }
1 #!/usr/bin/python3 2 # -*- coding:utf-8 -*- 3 #__author:Administrator 4 #date:2018/8/12 5 import os,sys 6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__name__))) 7 sys.path.append(BASE_DIR) 8 from core import db_handler 9 from conf import setting 10 from core import logger 11 import json,time 12 13 14 def load_current_balance(account_id): 15 db_path = db_handler.db_handler(setting.DATABASE) # 返回的是数据文件路径 16 account_file = "%s/%s.json" % (db_path, account_id) # 取到数据文件的绝对地址 17 with open(account_file, "r") as f: 18 account_data = json.load(f) 19 return account_data 20 21 def dump_account(account_data): 22 db_path = db_handler.db_handler(setting.DATABASE) # 返回的是数据文件路径 23 account_file = "%s/%s.json" % (db_path, account_data["id"]) # 取到数据文件的绝对地址 24 with open(account_file,"w") as f: 25 json.dump(account_data,f) 26 return True
1 #!/usr/bin/python3 2 # -*- coding:utf-8 -*- 3 #__author:Administrator 4 #date:2018/7/14 5 import os,sys 6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__name__))) 7 sys.path.append(BASE_DIR) 8 from core import db_handler 9 from conf import setting 10 from core import logger 11 import json,time,functools 12 13 14 #做一个登陆装饰器 15 def login_required(func): 16 @functools.wraps(func) 17 def wrapper(*args,**kwargs): 18 if args[0].get('is_authenticated'): 19 return func(*args,**kwargs) 20 else: 21 exit("用户认证失败") 22 return wrapper 23 24 25 #第二步,做一个用户认证功能 26 #初始化信息,一旦认证成功,就把数据传给这个字典 27 28 #输入账户id 和密码 29 def acc_auth(account,password): 30 db_path=db_handler.db_handler(setting.DATABASE)#返回的是数据文件路径 31 account_file="%s/%s.json"%(db_path,account)#取到数据文件的绝对地址 32 #print(account_file) #打印一下地址 33 if os.path.isfile(account_file): 34 with open(account_file,"r") as f: 35 account_data=json.load(f) 36 if account_data["password"]==password: 37 exp_time_stamp=time.mktime(time.strptime(account_data["expir_date"],'%Y-%m-%d')) 38 if time.time()>exp_time_stamp: 39 print("