Python购物流程结合ATM接口实现
来源:互联网 发布:joo yeon seo韩国 编辑:程序博客网 时间:2024/06/02 03:33
简介
ATM购物作业要求:
- 额度15000¥或自定义
- 实现购物商城,买东西加入购物车,调用信用卡接口结账
- 可以提现,手续费5%
- 每月22号出账单,每月10号为还款日,过期未还,按欠款总额的万分之5,每日计息
- 支持多账户登录
- 支持账户间转账
- 记录每月日常消费流水记录
- 提供还款接口
- ATM记录操作日志
- 提供管理接口,包括添加账户、用户额度、冻结账户等
程序要求:
分级目录,包含以下文件夹:
bin可执行文件
- atm.py start启动进入
- shopping.py 购物程序
- 要求每个程序块不超过10行config 配置文件
-user_db数据库
-log_format日志格式化modules/core/lib核心文件(不依赖其他文件,可通用的.py)
-提供的接口文件src连接文件(所有的业务逻辑代码)
-代码逻辑的实现模块log日志输出保存文件夹
- db数据库保存文件夹
文件目录
在ATM总文件夹下,建立bin、config、db、lib、src文件夹,如下图:
如何在不同文件夹下调用其他文件的py程序呢?
利用如下代码增加路径,并且位置有讲究:
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(_file_))))#增加当前绝对路径
放错位置的sys.path.append:
调整sys.path.append上下位置后,可顺利执行:
还包括了“F:\My_PyCharm_Code”路径
bin文件
admin.py
只用于管理员的登录管理程序:
1、创建账户
2、删除账户
3、冻结账户
4、查询账户
5、添加管理员账户
#_*_coding:utf-8_*___author__ = 'Alex_XT'import osimport syspath_dir = sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))#增加当前绝对路径for item in sys.path: print(item)from src import admin as src_adminif __name__ == "__main__": src_admin.run()
client.py
只用于普通账户的
1、账户信息
2、还款
3、取款
4、转账
5、账单
#_*_coding:utf-8_*___author__ = 'Alex_XT'import sysimport ossys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))from src import client as src_clientif __name__ == "__main__": src_client.run()
crontab.py
#_*_coding:utf-8_*___author__ = 'Alex_XT'from src import crontab as src_crontabif __name__ == "__main__": src_crontab.run()
config文件
settings.py
这里存放了管理员的数据库db路径和普通用户成员的数据库路径:
#_*_coding:utf-8_*___author__ = 'Alex_XT'import osBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))ADMIN_DIR_FOLDER = os.path.join(BASE_DIR,'db','admin')USER_DIR_FOLDER = os.path.join(BASE_DIR,'db','userinfo')
探讨os模块的作用:
如果少写一个os.path.dirname的情况:
就是所在py文件路径
#_*_coding:utf-8_*___author__ = 'Alex_XT'import osBASE_DIR = os.path.dirname(os.path.abspath(__file__))# USER_DIR_FOLDER = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR,"db","admin")))print(BASE_DIR)
如果加上os.path.dirname的情况,会将上一级路径添上:
#_*_coding:utf-8_*___author__ = 'Alex_XT'import osBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# USER_DIR_FOLDER = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR,"db","admin")))print(BASE_DIR)
如果加上os.path.join的情况,会将路径相拼接:
#_*_coding:utf-8_*___author__ = 'Alex_XT'import osBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))USER_DIR_FOLDER = os.path.join(BASE_DIR,"db","admin")print(USER_DIR_FOLDER)
os.path.dirname的情况:
与以上os.path.join的区别
os.path.exists用于判断路径是否存在:
if not os.path.exists(os.path.join(settings.ADMIN_DIR_FOLDER,username)):print("用户名不存在")
避免“FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。”的错误!
os.walk用于读取路径文件夹和文件:
它是遍历文件夹下所有的文件:
其中
- root表示string,代表目录的路径;
- sub_folders表示list,包含了当前dirpath路径下所有的子目录名字(不包含目录路径);
- files表示list,包含了当前dirpath路径下所有的非目录子文件的名字(不包含目录路径);
print("有以下管理员:") for root, sub_folders, files in os.walk(settings.ADMIN_DIR_FOLDER): print(files)
注意,sub_folders和 files均不包含路径信息,如需完整路径,可使用os.path.join(root, sub_folders)
# image directories for name in files: images.append(os.path.join(root, name)) # get 10 sub-folder names for name in sub_folders: temp.append(os.path.join(root, name))
os.listdir()用于读取仅当前路径下的文件名:
os.listdir()函数得到的是仅当前路径下的文件名,不包括子目录中的文件,所以需要使用递归的方法得到全部文件名。
# -*- coding: utf-8 -*-import osdef listdir(path, list_name): for file in os.listdir(path): file_path = os.path.join(path, file) if os.path.isdir(file_path): listdir(file_path, list_name) elif os.path.splitext(file_path)[1]=='.jpeg': list_name.append(file_path)
本例:
print("有以下账户:") for sub_folders in os.listdir(settings.USER_DIR_FOLDER): print(sub_folders)
lib文件
commons.py
用于密文的设置,md5加密:
#_*_coding:utf-8_*___author__ = 'Alex_XT'import hashlibdef md5(arg): """ md5加密 :param arg: :return: """ obj = hashlib.md5() obj.update(bytes(arg,encoding='utf-8'))#转为字节 return obj.hexdigest()def check_paypasswd(CURRENT_USER_INFO,paypasswd): if md5(paypasswd) == CURRENT_USER_INFO['pay_passwd']: return True else: print("支付密码错误!") return False
密文的读取与判断:
user_dict = json.load(open(os.path.join(settings.ADMIN_DIR_FOLDER,username),'r'))if username == user_dict['username'] and commons.md5(password)==user_dict['password']: CURRENT_USER_INFO['is_authenticated']=True CURRENT_USER_INFO['current_user'] = username return True
src文件
backend文件logger.py
# _*_coding:utf-8_*___author__ = 'Alex_XT'import loggingimport osfrom config import settingsdef get_logger(card_num, struct_time): if struct_time.tm_mday < 23: file_name = "%s_%s_%d" % (struct_time.tm_year, struct_time.tm_mon, 22)#2017_9_22 else: file_name = "%s_%s_%d" % (struct_time.tm_year, struct_time.tm_mon + 1, 22)#2017_10_22 file_handler = logging.FileHandler( os.path.join(settings.USER_DIR_FOLDER, card_num, 'record', file_name), encoding='utf-8'#用于中文编码输出 ) fmt = logging.Formatter(fmt="%(asctime)s: %(name)s: %(message)s") file_handler.setFormatter(fmt) logger1 = logging.Logger('user_logger', level=logging.INFO) logger1.addHandler(file_handler) return logger1
admin.py
# _*_coding:utf-8_*___author__ = 'Alex_XT'import osimport jsonfrom lib import commonsfrom config import settingsCURRENT_USER_INFO = {'is_authenticated': False, 'current_user': None}def init(): """ 初始化管理员信息 :return: """ dic = {'username': 'Alex', 'password': commons.md5('123')} # 以dic['username']名字命名文件 json.dump(dic, open(os.path.join(settings.ADMIN_DIR_FOLDER, dic['username']), 'w', encoding='utf-8'))def create_user(): """ 创建账户 :return: """ card_num = input("请输入新卡号:").strip() # card_num = "6222040209028810" # 创建目录:在card_num下创建 # 'record' # "basic_info.json" if not os.path.exists(os.path.join(settings.USER_DIR_FOLDER, card_num, 'record')): os.makedirs(os.path.join(settings.USER_DIR_FOLDER, card_num, 'record')) else: print("该账户已存在!继续执行,信息会被覆盖!!!") base_info = {'username': input("username:"), # 'Tim', 'card': card_num, 'password': commons.md5(input("password:")), # '123' 'pay_passwd': commons.md5(input("pay_passwd:")), # '123' "credit": 15000, # 信用卡额度 "balance": 15000, # 本月可用额度 "saving": 0, # 储蓄金额 "enroll_date": "2016-01-01", "expire_date": "2021-01-01", 'status': 0, # 0 = normal,1 = locked, 2 = disabled "debt": [], # 欠款记录,如: # [{'date':"2015-04-10","total_debt":80000,"balance_debt":5000},{'date':"2015-05-10","total_debt":80000,"balance_debt":5000}] } json.dump(base_info, open(os.path.join(settings.USER_DIR_FOLDER, card_num, "basic_info.json"), 'w')) print("创建成功!")def remove_user(): """ 移除用户 :return: """ passdef locked_user(): """ 冻结账户 :return: """ passdef search(): """ 搜索用户 :return: """ search_obj = input("1、管理员信息\n2、普通用户信息\n信息查询序号>>:") if search_obj == "1": print("有以下管理员:") for root, sub_folders, files in os.walk(settings.ADMIN_DIR_FOLDER): print(files) info_obj = input("要查询的名字:") if not os.path.exists(os.path.join(settings.ADMIN_DIR_FOLDER,info_obj)): print("管理员名字写错了!") else: dic = json.load(open(os.path.join(settings.ADMIN_DIR_FOLDER,info_obj),'r')) print(dic) else: print("有以下账户:") for sub_folders in os.listdir(settings.USER_DIR_FOLDER): print(sub_folders) info_obj = input("要查询的账户:") if not os.path.exists(os.path.join(settings.USER_DIR_FOLDER,info_obj)): print("账户号写错了!") else: basic_info = json.load(open(os.path.join(settings.USER_DIR_FOLDER,info_obj,"basic_info.json"),'r')) print(basic_info)def add_admin(): dic = {"username": input("新增管理员名字:"), "password": commons.md5(input("管理员密码:"))} if not os.path.exists(os.path.join(settings.ADMIN_DIR_FOLDER, dic['username'])): print("该管理员账户可用!") json.dump(dic, open(os.path.join(settings.ADMIN_DIR_FOLDER, dic['username']), 'w', encoding='utf-8')) else: print("该管理员已存在!请重新添加!")def main(): menu = """ 1、创建账户 2、删除账户 3、冻结账户 4、查询账户 5、添加管理员账户 """ print(menu) menu_dic = { '1': create_user, '2': remove_user, '3': locked_user, '4': search, '5': add_admin, } while True: user_option = input("请选择菜单序号>>:").strip() if user_option in menu_dic: menu_dic[user_option]() else: print("没有该选项!")def login(): """ 用户登录 :return: """ while True: username = input("请输入用户名:") password = input("请输入密码:") if not os.path.exists(os.path.join(settings.ADMIN_DIR_FOLDER, username)): print("用户名不存在") else: user_dict = json.load(open(os.path.join(settings.ADMIN_DIR_FOLDER, username), 'r')) if username == user_dict['username'] and commons.md5(password) == user_dict['password']: CURRENT_USER_INFO['is_authenticated'] = True CURRENT_USER_INFO['current_user'] = username return True else: print("密码错误!")def run(): init() ret = login() if ret: main()
client.py
# _*_coding:utf-8_*___author__ = 'Alex_XT'import osimport timeimport jsonfrom lib import commonsfrom config import settingsfrom src.backend import loggerCURRENT_USER_INFO = {}def dump_current_user_info(): json.dump(CURRENT_USER_INFO, open(os.path.join(settings.USER_DIR_FOLDER, CURRENT_USER_INFO['card'], "basic_info.json"), 'w'))def write_record(message): """ 账户记录 :param message: :return: """ struct_time = time.localtime() logger_obj = logger.get_logger(CURRENT_USER_INFO['card'], struct_time) logger_obj.info(message)def account_info(): """ 账户信息 :return: """ print(CURRENT_USER_INFO)def repay(): """ 还款 :return: """ passdef withdraw(): """ 提现 提现时,优先从自己余额中拿,如果余额不足,则使用信用卡(额度限制),提现需要手续费5% :return: """ num = float(input("请输入提现金额>>:")) if CURRENT_USER_INFO['saving'] >= num: CURRENT_USER_INFO['saving'] -= num write_record('%s - 储蓄账户:%d ' % ('提现', num)) dump_current_user_info() else: temp = num - CURRENT_USER_INFO['saving'] if CURRENT_USER_INFO['balance'] > (temp + temp * 0.05): CURRENT_USER_INFO['balance'] -= temp CURRENT_USER_INFO['balance'] -= temp * 0.05 write_record('%s - 储蓄账户:%f 信用卡账户:%f 手续费:%f' % ('提现', CURRENT_USER_INFO['saving'], temp, temp * 0.05)) else: print("账户余额不足,无法完成体现!")def transfer(): """ 转账 :return: """ passdef print_bil(): passdef go_shopping(): Product_List = [("Air Conditioner",50000),("Mac", 12000),("Apple", 5800), ("Bike", 800), ("Python", 80), ("NoteBook", 10)] # 使用了元组 Current_List = [] while True: print("---index product price---") for index, item in enumerate(Product_List): print("{}{}{}{}{}{}$".format(" " * 3, index, " " * 10, item[0], " " * 9, item[1])) print("\033[31;1m 按q退出购物\033[0m") choose_item = input("Choose index: ") if choose_item.isdigit(): choose_item = int(choose_item) if (choose_item < len(Product_List)) and (choose_item >= 0): Current_pro = Product_List[choose_item] if Current_pro[1] < CURRENT_USER_INFO['saving']: CURRENT_USER_INFO['saving'] -= Current_pro[1] Current_List.append(Current_pro) print(" Your Current List:%s Saving is: %s Balance is: \033[31;1m %s \033[0m" % ( Current_List, CURRENT_USER_INFO['saving'], CURRENT_USER_INFO['balance'])) write_record('%s - 储蓄账户:%f ' % ('消费', Current_pro[1])) dump_current_user_info() elif Current_pro[1] < CURRENT_USER_INFO['balance']: print("\033[43;1m Your saving money is not enough!!! %s\033[0m" % CURRENT_USER_INFO['saving']) Current_List.append(Current_pro) print(" Your Current List:%s Saving is: %s Balance is: \033[31;1m %s \033[0m" % ( Current_List, CURRENT_USER_INFO['saving'], CURRENT_USER_INFO['balance'])) choose_pay = input("请选择付款方式:\n1、储蓄余额+信用卡;\n2、只信用卡;") if choose_pay == "1": paypasswd = input("你选择了另外支付用信用卡消费,请输入支付密码:") temp = Current_pro[1] - CURRENT_USER_INFO['saving'] if commons.check_paypasswd(CURRENT_USER_INFO,paypasswd) and CURRENT_USER_INFO['balance'] > (temp): CURRENT_USER_INFO['balance'] -= temp message = '%s - 储蓄账户:%f - 信用卡支付:%f' % ('消费', CURRENT_USER_INFO['saving'], temp) write_record(message) CURRENT_USER_INFO['saving'] = 0 dump_current_user_info() print(" Your Current List:%s Saving is: %s Balance is: \033[31;1m %s \033[0m" % ( Current_List, CURRENT_USER_INFO['saving'], CURRENT_USER_INFO['balance'])) print(message) elif choose_pay == "2": paypasswd = input("你只选择了信用卡消费,请输入支付密码:") if commons.check_paypasswd(CURRENT_USER_INFO,paypasswd) and CURRENT_USER_INFO['balance'] > (Current_pro[1]): CURRENT_USER_INFO['balance'] -= Current_pro[1] message = '%s - 信用卡支付:%f' % ('消费', Current_pro[1]) write_record(message) dump_current_user_info() print(" Your Current List:%s Saving is: %s Balance is: \033[31;1m %s \033[0m" % ( Current_List, CURRENT_USER_INFO['saving'], CURRENT_USER_INFO['balance'])) print(message) else: print("余额不足,请退出!!!") else: print("\033[41;1m Invalid index! Continue... \033[0m") continue elif choose_item == "q": print("-------Your List-------") for item in Current_List: print(item[0], "--->>", item[1]) # exit("Final saving is: \033[31;1m %s \033[0m ,final balance is: %s" % ( # CURRENT_USER_INFO['saving'], CURRENT_USER_INFO['balance'])) print("Final saving is: \033[31;1m %s \033[0m ,final balance is: %s" % ( CURRENT_USER_INFO['saving'], CURRENT_USER_INFO['balance'])) break else: print("\033[41;1m Wrong Command! Continue...\033[0m") continuedef main(): menu = ''' 1、账户信息 2、还款 3、取款/提现 4、转账 5、账单 6、购物 ''' menu_dic = { '1': account_info, '2': repay, '3': withdraw, '4': transfer, '5': print_bil, '6': go_shopping, } while True: print(menu) user_option = input("选择菜单序号>>:").strip() if user_option in menu_dic: menu_dic[user_option]() else: print("该选项不存在!")def init(basic_info): CURRENT_USER_INFO.update(basic_info)def login(): """ 登录 :return: """ while True: card_num = input("卡号:") # "6222040209028810" if not os.path.exists(os.path.join(settings.USER_DIR_FOLDER, card_num)): print("卡号不存在!") else: password = input("请输入密码:") basic_info = json.load(open(os.path.join(settings.USER_DIR_FOLDER, card_num, "basic_info.json"), 'r')) if basic_info['password'] == commons.md5(password): init(basic_info) print("登录成功!") return True else: print("密码错误!")def run(): ret = login() if ret: main()
crontab.py
#_*_coding:utf-8_*___author__ = 'Alex_XT'import osimport jsonimport timefrom config import settingsfrom src.backend import loggerdef main(): card_list = os.listdir(settings.USER_DIR_FOLDER) for card in card_list: basic_info = json.load(open(os.path.join(settings.USER_DIR_FOLDER,card,'basic_info.json'))) struct_time = time.localtime() #循环账单列表,为每月的欠款计息,并写入到当月账单中 for item in basic_info['debt']: interest = item['total_debt']*0.0005 if basic_info['saving']>=interest: basic_info['saving']-=interest else: temp = interest-basic_info['saving'] basic_info['balance']-=temp logger_obj = logger.get_logger(card,struct_time) logger_obj.info("欠款利息 - %f - 备注:未还款日期%s;共欠款%f,未还款%f" % (interest, item['date'], item['total_debt'], item['balance_debt'])) json.dump( basic_info, open(os.path.join(settings.USER_DIR_FOLDER, basic_info['card'], "basic_info.json"), 'w') ) # 如果当前等于10号(9号之前) # 当前余额为负值,则将值添加到账单列表中,开始计息,同时,本月可用额度恢复。 if struct_time.tm_mday == 11 and basic_info['credit']>basic_info['balance']: date = time.struct_time("%Y-%m-%d") dic = {"date":date, "total_debt":basic_info['credit']-basic_info['balance'], "balance_debt":basic_info['credit']-basic_info['balance'], } basic_info['debt'].append(dic) #恢复可用额度 basic_info['balance']=basic_info['credit'] json.dump( basic_info, open(os.path.join(settings.USER_DIR_FOLDER,basic_info['card'],"basic_info.json"),'w') )def run(): main()
实现效果
管理员
普通用户
登录
提现
购物
付款
退出
流水账信息
代码下载
代码下载链接地址
参考
【1】python实现购物车程序 - 快递小可的博客 - CSDN博客
http://blog.csdn.net/sxingming/article/details/52334488
【2】Python获取指定文件夹下的文件名 - CSDN博客
http://blog.csdn.net/lsq2902101015/article/details/51305825
- Python购物流程结合ATM接口实现
- 购物车实现流程
- 购物车实现流程
- 使用Python的Django框架结合jQuery实现AJAX购物车页面
- 购物菜单选择、购物结算、ATM取款
- python实现购物车程序
- 购物流程
- asp.net购物车实现-------结合session方式
- asp.net购物车实现-------结合数据库的方式
- atm(选做)——实现信用卡程序 python
- python实现简单的购物车
- python练习题:实现购物车功能
- Python实现简单的购物过程
- Python Django实现简单购物车功能
- 结合IComparer接口实现对ListBox排序
- jsonp结合百度接口-实现搜索功能
- zookeeper结合dubbo实现分布式接口调用
- 微信卡券接口 - 系统流程实现
- spring boot整合redis
- Nodejs+Vuejs实现无限分类关系
- SEO新手必学:充分了解搜索引擎盈利模式
- 51单片机的中断系统(六)
- Use LCD Keyboard Shieid to show color sensor's data which received [1.2]
- Python购物流程结合ATM接口实现
- linux centos7 下 mysql5.6安装
- transient关键字
- JZOJ5372. 【NOIP2017提高A组模拟9.17】猫 链表+贪心+堆优化
- 汉诺塔问题
- javascript原型链详细解析(二)
- shiro配置问题
- 关于通过curl函数请求微信接口的总结
- 仿射变换中交比调合比概念