软件目录:
1、配置文件settings.ini
[root@Surpass conf]# cat settings.ini [DEFAULT] user_dir = /root/wangpeng/pythonproject/ATM/db/user_data goods_path = /root/wangpeng/pythonproject/ATM/db/goods.json log_path = /root/wangpeng/pythonproject/ATM/log/access.log
2、用户视图层
(1)admin.py

#!/usr/bin/env python # -*- coding:utf-8 -*- from prettytable import PrettyTable from core import src from interface import admin_interface # 增加用户 def add_user(): src.register() # 修改用户额度 def change_user_balance(): sign = True while sign: change_user = input('请输入要更改额度的用户:').strip() balance = input('请输入修改后的用户额度:').strip() if not balance.isdigit(): print('请输入一个正整数!') continue flag, msg = admin_interface.change_user_balance_interface(change_user, balance) if flag: print(msg) break else: print(msg) _continue = input('是否继续修改用户额度(y,n):').strip().lower() sign = False if _continue == 'n' else True # 锁定用户 def lock_user(): sign = True while sign: lock_user = input('请输入要冻结的用户:').strip() flag, msg = admin_interface.lock_user_interface(lock_user) if flag: print(msg) break else: print(msg) _continue = input('是否继续冻结用户(y,n):').strip().lower() sign = False if _continue == 'n' else True # 管理员功能字典 admin_func = { '0': ['增加用户', add_user], '1': ['修改用户额度', change_user_balance], '2': ['锁定用户', lock_user], } # 管理员功能主函数 def admin_run(): tb_admin = PrettyTable(field_names=['功能编号', '功能名称']) for k in admin_func: tb_admin.add_row([k, admin_func[k][0]]) print(tb_admin) flag = True while flag: choice = input('请输入功能编号:').strip() if choice in admin_func: admin_func[choice][1]() else: print('请输入正确的功能编号!') _continue = input('是否继续输入功能编号(y,n):').strip().lower() flag = False if _continue == 'n' else True
(2)src.py

#!/usr/bin/env python # -*- coding:utf-8 -*- import sys import time from prettytable import PrettyTable from lib import common from interface import user_interface from interface import bank_interface from interface import shop_interface current_user = { 'username': None, 'login_time': None, } goods_class = { '0': '绝版书籍', '1': '高端电子', '2': '实惠厨具' } def register(): """注册功能""" flag = True while flag: register_name = input('请输入注册的用户名:').strip() register_pwd = input('请输入用户的密码:').strip() reenter_pwd = input('请再次输入密码:').strip() balance = input('请选择信用卡的额度或者选d选择默认额度:') if reenter_pwd == register_pwd: if balance.lower() == 'd': sign, msg = user_interface.register_interface(register_name, register_pwd) elif balance.isdigit(): sign, msg = user_interface.register_interface(register_name, register_pwd, balance) else: print('选择的额度必须为一个数字!') continue tb_register = PrettyTable(field_names=['用户', '注册时间', '注册结果']) tb_register.add_row([register_name, time.strftime('%m-%d %X'), msg]) print(tb_register) if sign: break else: print('注册失败,两次输入密码不一致!') _continue = input('是否继续注册用户(y,n):').strip().lower() flag = False if _continue == 'n' else True def login(): """登录功能""" flag = True while flag: login_name = input('请输入登录名:').strip() login_pwd = input('请输入密码:').strip() sign, msg = user_interface.login_interface(login_name, login_pwd) tb_login = PrettyTable(field_names=['用户', '登录时间', '登录结果']) tb_login.add_row([login_name, time.strftime('%m-%d %X'), msg]) print(tb_login) if sign: current_user['username'] = login_name current_user['login_time'] = time.ctime(time.time()) break _continue = input('是否继续登录(y,n):').strip().lower() flag = False if _continue == 'n' else True @common.check_login(current_user) def check_balance(): """查看额度""" balance = user_interface.check_balance_interface(current_user['username']) tb_balance = PrettyTable(field_names=['用户', '剩余额度']) tb_balance.add_row([current_user['username'], balance]) print(tb_balance) @common.check_login(current_user) def withdraw(): """提现功能""" flag = True user = current_user['username'] while flag: cash_number = input('请输入提现的金额(元):').strip() try: float(cash_number) sign, msg = bank_interface.withdraw_interface(user, cash_number) tb_withdraw = PrettyTable(field_names=['用户', '提现时间', '提现结果']) tb_withdraw.add_row([user, time.strftime('%m-%d %X'), msg]) print(tb_withdraw) except ValueError: print('提现失败,请输入一个数字!') finally: _continue = input('是否继续提现(y,n):').strip().lower() flag = False if _continue == 'n' else True @common.check_login(current_user) def repayment(): """还款功能""" while True: repay_money = input('请输入还款的金额(元):').strip() if not repay_money.isdigit(): print('请输入一个正整数!') continue sign, msg = bank_interface.repay_interface(current_user['username'], repay_money) tb_repay_money = PrettyTable(field_names=['用户', '还款时间', '还款结果']) tb_repay_money.add_row([current_user['username'], time.strftime('%m-%d %X'), msg]) print(tb_repay_money) break @common.check_login(current_user) def transfer(): """转账功能""" flag = True user = current_user['username'] transfer_obj = input('请输入转账的对象:').strip() while flag: transfer_number = input('请输入转账的金额(元):').strip() try: float(transfer_number) sign, msg = bank_interface.transfer_interface(user, transfer_obj, transfer_number) tb_transfer = PrettyTable(['用户', '转账时间', '转账结果']) tb_transfer.add_row([user, time.strftime('%m-%d %X'), msg]) print(tb_transfer) except ValueError: print('转账失败,请输入一个数字!') finally: _continue = input('是否继续进行转账(y,n):').strip().lower() flag = False if _continue == 'n' else True @common.check_login(current_user) def check_flow(): """查看流水""" number = 1 user = current_user.get('username') flow_list = bank_interface.check_flow_interface(user) tb_flow = PrettyTable(field_names=['序号', f'{user}的流水记录']) for item in flow_list: tb_flow.add_row([number, item]) number += 1 print(tb_flow) @common.check_login(current_user) def shopping(): """购物功能""" print('欢迎来到购物商城主页'.center(30, '=')) user = current_user['username'] tb_goods_class = PrettyTable(field_names=['序号', '商品类别']) for k in goods_class: tb_goods_class.add_row([k, goods_class[k]]) while True: print(tb_goods_class) class_choice = input('请选择商品的类别或者按Q退出购物功能:').strip().upper() if class_choice == 'Q': break if class_choice not in goods_class: print('请输入正确的商品类别!') continue else: goods_info = shop_interface.get_goods_info_interface(class_choice) tb_goods_info = PrettyTable(field_names=['商品编号', '商品名称', '商品价格']) for k in goods_info: tb_goods_info.add_row([k, goods_info[k][0], goods_info[k][1]]) while True: print(tb_goods_info) goods_choice = input('请输入商品编号,或按Q返回上一层:').strip() if goods_choice.upper() == 'Q': break if goods_choice not in goods_info: print('请输入正确的商品编号!') continue cmd = input('是否添加该商品(y,n):').strip().lower() if cmd == 'n': continue elif cmd == 'y': sign_1, msg_1 = shop_interface.add_shop_car_interface(user, goods_info[goods_choice][0], goods_info[goods_choice][1]) print(msg_1) break pay_choice = input('是否支付(y,n):').strip().lower() if pay_choice == 'y': msg = shop_interface.shop_settle(user) print(msg) break @common.check_login(current_user) def check_shop_car(): """查看购物车""" user = current_user['username'] shop_car = shop_interface.check_shop_car_interface(user) print(f'{user}的购物车'.center(30, '=')) tb_shop_car = PrettyTable(field_names=['商品名称', '商品数量', '商品单价']) for k in shop_car: tb_shop_car.add_row([k, shop_car[k][0], shop_car[k][1]]) print(shop_car) @common.check_login(current_user) def admin(): """管理员功能""" from core import admin admin.admin_run() def see_latter(): """退出功能""" print('欢迎下次再次使用ATM系统'.center(30, '=')) sys.exit(0) func_dic = { '0': ['注册功能', register], '1': ['登录功能', login], '2': ['查看额度', check_balance], '3': ['提现功能', withdraw], '4': ['还款功能', repayment], '5': ['转账功能', transfer], '6': ['查看流水', check_flow], '7': ['购物功能', shopping], '8': ['查看购物车', check_shop_car], '9': ['管理员功能', admin], '10': ['退出功能', see_latter] } def run(): """主函数""" tb_func = PrettyTable(field_names=['功能编号', '功能名称']) for k in func_dic: tb_func.add_row([k, func_dic[k][0]]) while True: print(tb_func) user_choice = input('请选择功能编号:').strip() if user_choice not in func_dic: print('请输入正确的功能编号!') continue func_dic[user_choice][1]()
3、逻辑接口层
(1)admin_interface.py

#!/usr/bin/env python #-*- coding:utf-8 -*- from db import db_handler # 修改用户的额度接口a def change_user_balance_interface(user,balance): user_dic = db_handler.get_user_data(user) if not user_dic: return False,f'用户{user}不存在!' else: user_dic['balance'] = balance db_handler.set_user_data(user_dic) return True,f'修改用户{user}额度成功,当前额度{balance}元' # 锁定用户接口 def lock_user_interface(lock_user): user_dic = db_handler.get_user_data(lock_user) if not user_dic: return False,f'用户{lock_user}不存在!' else: user_dic['is_locked'] = True db_handler.set_user_data(user_dic) return True,f'用户{lock_user}已锁定!'
(2)bank_interface.py

#!/usr/bin/env python # -*- coding:utf-8 -*- from db import db_handler from lib import common # 查看额度接口 def check_balance_interface(username): user_dic = db_handler.get_user_data(username) return user_dic.get('balance') # 提现请求 def withdraw_interface(username, cash_number): user_dic = db_handler.get_user_data(username) if (float(cash_number) * 1.05) > float(user_dic.get('balance')): # 提现需要加收百分之5的手续费用 return False, f'用户{username}提现失败,账户余额不足!' else: fee = str(float(cash_number) * 0.05) user_dic['balance'] = str(float(user_dic.get('balance')) - float(cash_number) * 1.05) user_dic['flow'].append(f'用户{username}提现成功,提取金额{cash_number}元,收取手续费{fee}元') db_handler.set_user_data(user_dic) common.log_generate('提现模块', f'用户{username}提现成功,提取金额{cash_number}元,收取手续费{fee}元', 20) return True, f'用户{username},提现成功,提取金额{cash_number}元,收取手续费{fee}元!' # 转账请求接口 def transfer_interface(current_user, transfer_obj, transfer_number): current_user_dic = db_handler.get_user_data(current_user) transfer_obj_dic = db_handler.get_user_data(transfer_obj) if not transfer_obj_dic: return False, f'用户{current_user}转账失败,转账对象{transfer_obj}不存在!' else: if float(transfer_number) > float(current_user_dic.get('balance')): return False, f'用户{current_user}转账失败,转账金额{transfer_number}超出账户额度!' else: current_user_dic['balance'] = str(float(current_user_dic.get('balance')) - float(transfer_number)) transfer_obj_dic['balance'] = str(float(transfer_obj_dic.get('balance')) + float(transfer_number)) current_user_dic['flow'].append(f'用户{current_user}转入{transfer_obj}金额{transfer_number}元') transfer_obj_dic['flow'].append(f'用户{transfer_obj}收到{current_user}转账金额{transfer_number}元') db_handler.set_user_data(current_user_dic, transfer_obj_dic) common.log_generate('转账模块', f'用户{current_user}转入{transfer_obj}金额{transfer_number}元', 20) common.log_generate('转账模块', f'用户{transfer_obj}收到{current_user}转账金额{transfer_number}元', 20) return True, f'用户{current_user}转账{transfer_obj}成功,转账金额{transfer_number}元' # 还款接口 def repay_interface(username, repay_money): user_dic = db_handler.get_user_data(username) user_dic['balance'] = str(float(user_dic.get('balance')) + float(repay_money)) user_dic['flow'].append(f'用户{username}还款成功,还款金额{repay_money}元') db_handler.set_user_data(user_dic) common.log_generate('还款模块', f'用户{username}还款成功,还款金额{repay_money}元',20) return True, f'用户{username}还款成功,还款金额{repay_money}元' # 支付接口 def pay(user, cost): user_dic = db_handler.get_user_data(user) if float(cost) > float(user_dic['balance']): return False, f'支付失败,用户{user}余额不足!' else: user_dic['balance'] = str(float(user_dic.get('balance')) - float(cost)) user_dic['flow'].append(f'用户{user}支付成功,一共消费{cost}元!') db_handler.set_user_data(user_dic) common.log_generate('购物模块',f'用户{user}支付成功,一共消费{cost}元!',20) return True,user_dic,f'用户{user}支付成功,一共消费{cost}元!' # 查看消费流水接口 def check_flow_interface(username): user_dic = db_handler.get_user_data(username) return user_dic.get('flow')
(3)shop_interface.py

#!/usr/bin/env python # -*- coding:utf-8 -*- from db import db_handler from interface import bank_interface # 获取商品信息 def get_goods_info_interface(goods_class): goods_info = db_handler.get_goods_data(goods_class) return goods_info # 增加购物车 def add_shop_car_interface(user, goods_name, good_price): user_dic = db_handler.get_user_data(user) if goods_name in user_dic['shop_car']: goods_number = user_dic['shop_car'][goods_name][0] user_dic['shop_car'][goods_name][0] = str(int(goods_number) + 1) else: user_dic['shop_car'][goods_name] = ['1', good_price] db_handler.set_user_data(user_dic) return True, f'用户{user}添加购物车成功' # 商品结算接口 def shop_settle(user): cost = '0' user_dic = db_handler.get_user_data(user) for k in user_dic['shop_car']: goods_number = user_dic['shop_car'][k][0] goods_price = user_dic['shop_car'][k][1] cost = str(int(cost) + int(goods_number) * int(goods_price)) sign, user_dic, msg = bank_interface.pay(user, cost) if sign: user_dic['shop_car'] = {} db_handler.set_user_data(user_dic) return msg # 查看购物车接口 def check_shop_car_interface(user): user_dic = db_handler.get_user_data(user) return user_dic['shop_car']
(4)user_interface.py

#!/usr/bin/env python # -*- coding:utf-8 -*- from db import db_handler from lib import common from interface import bank_interface # 用户注册请求接口 def register_interface(register_name, register_pwd, balance='15000'): if db_handler.get_user_data(register_name): common.log_generate('注册模块', f'注册失败,{register_name}已存在!', 30) return False, f'用户{register_name}已存在!' else: user_dic = { 'username': register_name, 'password': common.password_md5(register_pwd), 'balance': balance, 'flow': [], # 用户记录用户消费流水 'shop_car': {}, # 用于记录购物城 'is_locked': False # 用于记录用户是否被锁定 } db_handler.set_user_data(user_dic) common.log_generate('注册模块', f'用户{register_name}注册成功!', 20) return True, f'用户{register_name}注册成功!' # 用户登录请求接口 def login_interface(login_name, login_pwd): if not db_handler.get_user_data(login_name): return False, f'用户{login_name}不存在,请先注册!' else: user_dic = db_handler.get_user_data(login_name) if user_dic['is_locked'] == True: return False,f'用户{login_name}已被锁定!' if common.password_md5(login_pwd) == user_dic.get('password'): common.log_generate('登录模块', f'用户{login_name}登录成功!', 20) return True, f'用户{login_name}登录成功!' else: common.log_generate('登录模块', f'用户{login_name}登录失败,{login_pwd}错误!', 40) return False, f'用户{login_name}登录失败,{login_pwd}错误!' # 查看用户余额接口 -->调用银行的接口查看用户余额 def check_balance_interface(username): res = bank_interface.check_balance_interface(username) return res
4、数据处理层
db_handler.py

#!/usr/bin/env python # -*- coding:utf-8 -*- import os import json from pathlib import Path from configparser import ConfigParser settings_path = os.path.join( Path(os.path.abspath(__file__)).parent.parent, 'conf', 'settings.ini' ) config = ConfigParser() config.read(r'{}'.format(settings_path)) USER_DATA_DIR = config.get('DEFAULT', 'user_dir') GOODS_DATA_PATH = config.get('DEFAULT', 'goods_path') # 获取用户数据 def get_user_data(username): user_path = os.path.join( USER_DATA_DIR, f'{username}.json' ) if os.path.exists(user_path): with open(user_path, mode='rt', encoding='utf-8') as fr: user_data_dic = json.load(fr) return user_data_dic # 设置用户数据(增加或跟新) def set_user_data(*args): for item in args: username = item.get('username') user_path = os.path.join( USER_DATA_DIR, f'{username}.json' ) with open(user_path, mode='wt', encoding='utf-8') as fw: json.dump(item, fw, indent=4, ensure_ascii=False) fw.write(' ') # 获取商品数据 def get_goods_data(goods_class): with open(GOODS_DATA_PATH, mode='rt', encoding='utf-8') as fr: goods_info_dic = json.load(fr) return goods_info_dic[goods_class]
goods.json

[root@Surpass db]# cat goods.json { "0": { "0": [ "《那些年egon追过的富婆》", "150" ], "1": [ "《别样的父子:egon与alex》", "200" ], "2": [ "《东莞炮王:tank的极限挑战》", "300" ], "3": [ "《风骚画家:tank与egon》", "150" ] }, "1": { "0": [ "Iphone XS", "10000" ], "1": [ "IPad PRO 2019", "4500" ], "2": [ "MacBook PRO", "14000" ], "3": [ "Apple Watch", "6200" ] }, "2": { "0": [ "Range Hoods", "1500" ], "1": [ "Cutting Board", "450" ], "2": [ "Tool", "600" ], "3": [ "Gas Cooker", "800" ] } } [root@Surpass db]# [root@Surpass db]#
egon.json

[root@Surpass user_data]# cat egon.json { "username": "egon", "password": "b553bfd76a443f7c76ac75965911b93c", "balance": "22850.0", "flow": [ "用户egon提现成功,提取金额1000元,收取手续费50.0元", "用户egon转入tank金额3000元", "用户egon转入tank金额4000元", "用户egon还款成功,还款金额10000元", "用户egon收到lxx转账金额400元", "用户egon收到lxx转账金额500元" ], "shop_car": {}, "is_locked": false } [root@Surpass user_data]#
5、公共方法库

#!/usr/bin/env python # -*- coding:utf-8 -*- import hashlib import logging.config from conf import setting func_dic = {} # md5加密 def password_md5(password): salt_1 = password[:3] salt_2 = password[-2:] m = hashlib.md5((salt_1 + password + salt_2).encode('utf-8')) return m.hexdigest() # 日志产生 def log_generate(log_module, log_msg, log_level=10): logging.config.dictConfig(setting.LOGGING_DIC) logger_obj = logging.getLogger(log_module) if log_level == 10: logger_obj.debug(log_msg) elif log_level == 20: logger_obj.info(log_msg) elif log_level == 30: logger_obj.warning(log_msg) elif log_level == 40: logger_obj.error(log_msg) elif log_level == 50: logger_obj.critical(log_msg) # 登录认证装饰器 def check_login(current_user): def wrapper(func): def inner(*args, **kwargs): if not current_user['username']: print(f'请先登录,才能使用{func.__doc__}功能!') else: return func(*args, **kwargs) return inner return wrapper
6、日志文件

access.log [root@Surpass log]# cat access.log [2020-04-03 09:01:43,626]:[MainThread:140127466886976][task_id:注册模块][common.py:26][INFO][用户egon注册成功!] [2020-04-03 09:32:00,738]:[MainThread:140719983122240][task_id:注册模块][common.py:26][INFO][用户tank注册成功!] [2020-04-03 18:27:14,464]:[MainThread:140218694326080][task_id:注册模块][common.py:26][INFO][用户jim注册成功!] [2020-04-03 18:32:39,779]:[MainThread:140116792883008][task_id:登录模块][common.py:26][INFO][用户egon登录成功!] [2020-04-03 18:33:00,061]:[MainThread:140116792883008][task_id:提现模块][common.py:26][INFO][用户egon提现成功,提取金额1000元,收取手续费50.0元] [2020-04-03 18:33:37,443]:[MainThread:140116792883008][task_id:转账模块][common.py:26][INFO][用户egon转入tank金额3000元] [2020-04-03 18:33:37,444]:[MainThread:140116792883008][task_id:转账模块][common.py:26][INFO][用户tank收到egon转账金额3000元] [2020-04-03 18:33:46,053]:[MainThread:140116792883008][task_id:转账模块][common.py:26][INFO][用户egon转入tank金额4000元] [2020-04-03 18:33:46,053]:[MainThread:140116792883008][task_id:转账模块][common.py:26][INFO][用户tank收到egon转账金额4000元] [2020-04-03 18:34:33,314]:[MainThread:140116792883008][task_id:还款模块][common.py:24][DEBUG][用户egon还款成功,还款金额10000元] [2020-04-03 19:18:53,703]:[MainThread:139985108981568][task_id:登录模块][common.py:26][INFO][用户egon登录成功!] [2020-04-03 19:19:48,204]:[MainThread:140507353343808][task_id:登录模块][common.py:26][INFO][用户egon登录成功!] [2020-04-03 21:36:35,775]:[MainThread:139636260968256][task_id:注册模块][common.py:26][INFO][用户lxx注册成功!] [2020-04-03 21:36:56,395]:[MainThread:139636260968256][task_id:登录模块][common.py:30][ERROR][用户lxx登录失败,ddd错误!] [2020-04-03 21:37:10,685]:[MainThread:139636260968256][task_id:登录模块][common.py:26][INFO][用户lxx登录成功!] [2020-04-03 21:37:33,265]:[MainThread:139636260968256][task_id:提现模块][common.py:26][INFO][用户lxx提现成功,提取金额1000元,收取手续费50.0元] [2020-04-03 21:37:56,363]:[MainThread:139636260968256][task_id:转账模块][common.py:26][INFO][用户lxx转入egon金额400元] [2020-04-03 21:37:56,364]:[MainThread:139636260968256][task_id:转账模块][common.py:26][INFO][用户egon收到lxx转账金额400元] [2020-04-03 21:38:01,860]:[MainThread:139636260968256][task_id:转账模块][common.py:26][INFO][用户lxx转入egon金额500元] [2020-04-03 21:38:01,860]:[MainThread:139636260968256][task_id:转账模块][common.py:26][INFO][用户egon收到lxx转账金额500元] [2020-04-03 21:38:21,804]:[MainThread:139636260968256][task_id:还款模块][common.py:26][INFO][用户lxx还款成功,还款金额10000元] [2020-04-03 21:41:07,502]:[MainThread:140061648467776][task_id:登录模块][common.py:26][INFO][用户lxx登录成功!] [2020-04-03 21:41:32,177]:[MainThread:140236342261568][task_id:登录模块][common.py:26][INFO][用户lxx登录成功!] [2020-04-03 21:44:22,891]:[MainThread:140581042657088][task_id:登录模块][common.py:26][INFO][用户lxx登录成功!] [2020-04-03 21:45:05,387]:[MainThread:140581042657088][task_id:购物模块][common.py:26][INFO][用户lxx支付成功,一共消费10950元!] [2020-04-03 21:52:20,014]:[MainThread:140581042657088][task_id:购物模块][common.py:26][INFO][用户lxx支付成功,一共消费1500元!] [2020-04-03 21:59:07,141]:[MainThread:139720622716736][task_id:登录模块][common.py:26][INFO][用户lxx登录成功!] [2020-04-03 21:59:36,576]:[MainThread:139720622716736][task_id:购物模块][common.py:26][INFO][用户lxx支付成功,一共消费14000元!]