[py]python之信用卡ATM

Posted 毛台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[py]python之信用卡ATM相关的知识,希望对你有一定的参考价值。

python之信用卡ATM

参考: http://www.cnblogs.com/wushank/p/5248916.html
他的博客写的很ok

需求介绍

模拟实现一个ATM + 购物商城程序

  • 额度 15000或自定义
  • 实现购物商城,买东西加入 购物车,调用信用卡接口结账
  • 可以提现,手续费5%
  • 每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
  • 支持多账户登录
  • 支持账户间转账
  • 记录每月日常消费流水
  • 提供还款接口
  • ATM记录操作日志
  • 提供管理接口,包括添加账户、用户额度,冻结账户等。

因对本次作业的MVC结构没有思路,故研究分析了王松牛人的作业,现整理如下:

程序简要说明

一、主程序day5_credit_card.py开始

   1、生成today今天的日期和星期数weekoftoday
   2、定义currusers:实例化modules下的users.py中的类Users
   3、初始化对账单report.create_statement_main()
       (1)、从database目录下的文件creditcard中读取信用卡列表
       (2)、循环列表调用 create_card_statement
       (3)、create_card_statement函数说明
            3.1 获取当前日期currday和today
            3.2 如果当天是22号出帐日:
              3.2.1 赋值startday,endday,startdate,enddate,statement_key出帐起始结束时间
              3.2.2 获取卡号对应的消费流水列表dbapi.load_bill_report(cardno, startdate, enddate)
              3.2.3 statement_dict的信息追加到信用卡帐单信息中。
   4、循环菜单
       (1)、判断用户是否登录,并输出相应用户信息
              未登录输出template.index_default_menu.format("", today, common.numtochr(weekoftoday))
              否则输出template.index_logined_menu.format("欢迎您: {0}".format(curruser.name), today,common.numtochr(weekoftoday))
       (2)、输出用户选择菜单
       (3)、输入5,则退出菜单
       (4)、输入1,首先加载当年用户信息curruser.db_load(),然后调用doshopping(curruser)
       (5)、输入2,首先加载当年用户信息curruser.db_load(),然后调用user_login(curruser, today, weekoftoday)
       (6)、输入3,调用card_center(curruser)信用卡中心
       (7)、输入4,调用manager(curruser)后台管理
   5、菜单1:doshopping商城函数
       (1)、实例化商城,调用shopping.Shopping()
       (2)、循环开始,输出商品菜单shoppobj.welcome_menu
       (3)、输入编号选择并赋值shop_cassify_id,并进行输入验证判断
       (4)、输入值为4,进行购物车商品显示shopping.Shopping.print_goods_list(shoppobj.shopping_cart)
              并显示common.show_message("当前购物车共有 {0} 件商品,合计 {1} 元)
       (5)、输入值为5,shoppobj.payfor_shopcart(userobj),无错误,输出支付成功
       (6)、输入值为1-3,则调用shoppobj.get_goods_list_by_typeid(),显示商品分列表
       (7)、第二层循环开始,并显示指定商品分类下的所有商品列表(Shopping类静态方法)
              shopping.Shopping.print_goods_list(goods_list)
       (8)、选择商品编号goods_id,加入购物车,并对输入进行判断
            8.1 如果输入为q,返回上一层
            8.2 调用商品加入购物车函数shoppobj.add_shopping_card(goods_id)
            8.3 如果返回正确,则显示购物车所有商品信息shopping.Shopping.print_goods_list(shoppobj.shopping_cart),并输出common.show_message("已将商品加入购物车!", "INFORMATION")
               第三层循环开始,显示“继续购物(y) or 返回上一级(q)”,
            8.4 如果返回失败,则输出common.show_message("添加购物车失败,请检查输入商品编号是否正确!", "ERROR"),并continue
   6、菜单2:user_login(curruser, today, weekoftoday)用户登录
       (1)、循环开始
       (2)、判断用户是否登录成功userobj.islogin,
            2.1 如果已经登录,则显示个人中心菜单 template.index_user_center.format(userobj.name, today, common.numtochr(weekoftoday)) 
            2.2 输出选择功能菜单,选择6,返回上级菜单
            2.3 如果选择1-5,则通过反射来执行,从 template 模块查找各按键对应的模块
                func_dict = template.user_center_func
            2.4 根据输出的数字,赋值相应的模块名称,modulepy = __import__(func_dict[_choose]["module"])
            2.5 如果选择的是1,2,5,则赋值modulesobj 、classobj、func
   7、菜单3:card_center(curruser)信用卡中心
       (1)、判断用户是否登录
            1.1 已登录,则重新load一下数据userobj.db_load(),并获取到绑定的信息卡信息cardno = userobj.bindcard
            1.2 获得信用卡对象card = CreditCard(cardno)
            1.3 如果未登录,则进行循环,让用户输入信用卡和密码进行认证
       (2)、显示登录输出菜单index_ATM,循环开始:
       (3)、输入common.input_msg("请选择功能: ", ("1", "2", "3", "4", "5"))
       (4)、如果输入是5,就返回上一层循环
       (5)、如果输入是1,则查看信用卡信息
       (6)、如果输入是2,则进行提现菜单
            6.1 如果card.frozenstatus状态是1,则提示“卡已冻结,请联系客服”
            6.2 否则提示“信用卡提现将收取 {0}% 的手续费!”
            6.3 循环开始,提示"请输入要提现的金额(q返回):"
            6.4 输入正确的话,提示输入信用卡密码进行确认
            6.5 执行提现函数card.fetch_money(float(cost), cardpasswd),并根据返回结果进行输出相应信息
       (7)、如果输入是3,则进入转帐菜单
            7.1 如果card.frozenstatus状态是1,则提示“卡已冻结,请联系客服”
            7.2 否则提示“信用卡转帐将收取 {0}% 的手续费!”
            7.3 循环开始,提示"请输入要转账的卡号(q返回)"
            7.4 对卡号是数字,则生成一个trans_cardobj = CreditCard(trans_cardno)
            7.5 进行卡号判断存在的话,提示是转账的金额,
            7.6 如果金额正确并输入信用卡密码进行确认
            7.5 执行转帐函数card.translate_money(float(trans_cost), cardpasswd, trans_cardobj) ,并根据返回结果进行输出相应信息  
       (8)、如果输入是4,则进入还款菜单
            8.1 调用card.recreate_statement()函数,更新一下对账单信息
            8.2 循环开始,获取对账单所有列表interest_list = card.load_statement_list()
            8.3 获取还未还款的记录并显示message_info = report.print_statement_list(card.cardno, interest_list)
            8.4 如果有要还款的记录,则显示具体帐单信息
            8.5 请选择还款的16位账单号,然后进行判断,
            8.6 输出正确,则显示指定单号的相应对账单信息report.print_statement_detail
            8.7 输入还款金额,并更新已还款金额 = 现在还的金额 + 已经还的金额
            8.8 需要还款数 = 消费总费用 + 利息 ,并判断是否已还清,如果还清则设置interest_list[i][pay_serno]["isfinished"] = 1
            8.9 如果未还清,则显示“您尚未全部还款,请在还款日前尽快还款!”
            8.10 将还款后的信息写入数据库更新dbapi.write_statement_list(card.cardno, interest_list)
            8.11 显示是否继续还款。
   8、菜单4:主菜单后台管理模块manager(userobj):
       (1)、用户是否登录,是否是角色是否是admin
       (2)、是admin,进入循环,显示template.index_admin
       (3)、选择菜单,输入1时,进入创建新用户调用User类中的init_user_info()函数
       (4)、选择菜单,输入2时,进入删除用户菜单调用get_users()函数
            4.1 get_users() 显示用户的信息,用户新建、删除、解锁用户时显示用户基本信息
            4.2 输入操作的用户名
            4.3 创建一个用户实例_deluser = Users(),并赋值_deluser.username = username
            4.4 _deluser.load_user_info()判断,如果用户名存在,load用户信息成功,显示用户信息,返回用户
            4.5 用户不存在,返回失败
            4.6 调用_user.del_user(),并显示删除用户成功
       (5)、选择菜单,输入3时,进行锁定用户菜单调用get_users()函数,方式同上
       (6)、选择菜单,输入4时,进入发行信用卡菜单
            6.1 调用newcard = fill_card_info()函数,填充信用卡资料信息,返回一个信用卡对象
            6.2 循环开始,输入卡号,并判断卡号是否存在,不存在退出循环
            6.3 在依次输入密码,额度等信息,并返回一个信用卡对象
       (7)、选择菜单,输入5时,进入冻结信用卡
            7.1 输入要操作卡号
            7.2 card = CreditCard(cardno),实例化信用卡
            7.3 判断信用卡是否存在card.card_is_exists
            7.4 存在则输入卡信息,并在次确定是否冻结
            7.5 card.frozenstatus = 1设置卡的标志位,card.update_card()更新信用卡文件
       (8)、选择菜单,输入0时,返回上层菜单

二、包conf说明:

   1、errorcode.py介绍:
       定义系统错误代码表:NO_ERROR,USER_NOT_EXISTS,CARD_NOT_BINDED,BALANCE_NOT_ENOUGHT,CARD_OWNER_ERROR,CARD_PASS_ERROR
   2、settings.py介绍:定义一系列变量值
       2.1 定义程序文件主目录BASE_DIR,并加入环境变量
       2.2 定义数据库信息DATABASE
       2.3 定义日志文件存放路径LOG_PATH
       2.4 定义账单报表文件路径REPORT_PATH
       2.5 定义用户登录失败最大次数ERROR_MAX_COUNT
       2.6 定义日息费率EXPIRE_DAY_RATE
       2.7 定义转账、提现手续费FETCH_MONEY_RATE
       2.8 定义信用额度CREDIT_TOTAL
       2.9 定义每月账单日期STATEMENT_DAY
   3、template.py介绍:该模块用来定义系统的菜单模板
       3.1 主程序中的主菜单index_default_menu
       3.2 主程序中的用户登录后的显示菜单index_logined_menu
       3.3 主程序中的用户中心菜单index_user_center
       3.4 用户中心按键对应功能模块user_center_func
       3.5 购物模块的主菜单, menu 菜单在shopping模块中内部构造shopping_index_menu 
       3.6 账单报表显示模板report_bill
       3.7 购物历史记录显示模板shopping_history
       3.8 后台管理模板index_admin
       3.9 ATM 管理模块index_ATM
       3.10 显示用户基本信息模板user_info
       3.11 显示信用卡基本信息模板card_info
       3.12 信用卡对账单列表模板report_statement_list
       3.13 信用卡对账单详细模板report_statement_detail

三、包database介绍:

   1、init_db.py介绍:
       1.1 定义商品列表_shopping_list
       1.2 定义用户列表_user_list
       1.3 定义信用卡列表_creditcard_list
       1.4 函数init_db_shoppingmark() 初始化购物商城数据表 shoppingmark.db
       1.5 函数init_db_users() 初始化用户数据表 users.db
       1.6 函数init_db_creditcard() 初始化信用卡数据表 creditcard.db
       1.7 执行init_database(),通过反射初始化数据表分别调用以上三个函数

四、包dbhelper介绍:

   1、dbapi.py介绍:
       1.1 函数append_db_json(contant, filename),将信息以 json 格式写入数据表文件(追加)
       1.2 函数write_db_json(contant, filename),将信息以 json 格式写入数据表文件(覆盖)
       1.3 函数load_data_from_db(tabename),从指定的数据表中获取所有数据,通过 json 方式将数据返回
       1.4 函数load_bill_report(cardno, startdate, enddate),从信用卡对账单中获取指定卡的对账信息数据, 获取某一个时间段内的数据
       1.5 函数load_shop_history(user, startdate, enddate),查找报表记录中的指定用户的购物历史记录,将结果存入到列表中
       1.6 函数load_statement_list(cardno),从对账单中获取记录
       1.7 函数write_statement_list(cardno, db_list),将对账单记录写入对账单文件,更新

五、包modules介绍:

1、users.py介绍之类Users:
   1、定义私有变量:__database 值为database下的user.db
   2、定义用户的静态变量
   3、定义动态方法db_load(self.dict_user = dbapi.load_data_from_db(self.__database)),即调用dbapi模块中的load_data_from_db方法来展示用户信息
   4、定义login函数,输入用户名和密码
       (1)、调用user_exists,判断用户是否存在,不存在则使用common.show_message进行异常颜色输出。
       (2)、如存在则调用 用户登录模块_user_login ,首先对输入的密码参数进行md5计算_password = common.encrypt(password),调用common模块中的encrypt函数,并进行用户信息的判断的赋值
       (3)、判断是否用户被锁定
       (4)、判断用户是否登录成功,成功则break退出,失败则输出异常信息
       (5)、连续三次登录失败,则设置用户锁定标识为1,并update_user更新到user.db
       (6)、重置trycount 重置次数
   5、update_user即为将dict_user用户列表信息进行回写文件
   6、定义用户存在函数user_exists、创建函数create_user、删除函数del_user、锁定函数unlock_user
   7、创建并init_user_info初始化用户信息,输入各种信息后,调用 create_user来生成用户
   8、定义静态方法user_auth,用于用户登录验证装饰器
   9、定义bind_card函数判断卡绑定
   10、注销用户函数logout,将系统属性置空
   11、个人中心 - 修改密码函数modify_password
   12、修改用户信息modify_user_info
       (1)、首先输出当前的用户信息
       (2)、输入新的用户信息
       (3)、输入新的信用卡信息,并创建一个新的卡对象,调用CreditCard模块:cardobj = CreditCard
       (4)、判断信用卡是否存在
       (5)、输入其他信息,并update_user回写文件
   13、根据用户名获取用户信息load_user_info

2、shopping.py之类Shopping:
   1、定义私有变量:__welcome_title 菜单标题、__database 数据库文件、__shop_report_file购物报表
   2、定义__init__: 特别定义方法
         (1)、获取数据表数据self._get_shop_market()
         (2)、购物商城欢迎菜单self._construct_title_menu() 
   3、_get_shop_market方法:加载购物商品信息dbapi.load_data_from_db(shoppingmarket.db)
   4、_construct_title_menu方法:输出购物商城菜单
       self.welcome_menu = self.__welcome_title.format(menu="".join(_menu))
   5、get_goods_list_by_typeid方法:根据用户选择的商品分类编号,获取该分类下所有商品
   6、定义静态方法print_goods_list:列表中的商品信息输出到屏幕,商品列表或购物车商品列表
         (1)、输出商品信息标题
         (2)、循环输出商品具体信息
   7、定义方法add_shopping_card(self, goodsid):根据商品编号加入购物车
         (1)、定义变量_goods_tuple ,即具体的商品列表
         (2)、开始查找输入的商品编号,并加入购物车列表中,并计算金额
         (3)、成功后break
         (4)、返回return 成功与否
   8、定义payfor_shopcart结算方法,并调用@Users.user_auth认证模块作装饰器
       购物车结算模块,功能包括:购物车付款、购物记录写入文件
         (1)、判断用户是否绑定信用卡,如无,则返回错误,有,则继续、
         (2)、实例化信用卡类cardobj = CreditCard(userobj.bindcard)
         (3)、判断信用卡余额是否大于购买金额,如果不够,输出额度不够,否则继续
         (4)、调用common.create_serialno(),生成一个流水号
         (5)、调用卡的支付模块进行支付cardobj.card_pay(self.shopping_cost, 1, serno)
                    支付扣款 
                    记录消费流水对账单,将发生了费用还没有还款的账单信息写入文件 report_bill 中
                    更新信用卡可透支余额信息到数据库 creditcard.db
         (6)、记录购物流水shopping_record,并写入报表记录文件shopping_history
         (7)、购物结算完成后将对象的购物车清空shopping_cart.clear(), 购物车商品总价清0 ,待下次购物
         (8)、返回错误代码

3、creditcard.py之类CreditCard:
   1、指定数据表__database的表creditcard
   2、定义信用卡额度,信用卡透支余额,信用卡日息,提现手续费率,信用卡状态等变量
   3、定义_load_card_info函数,用户输入的卡号获取信用卡信息
   4、定义card_is_exists函数,判断输入的信用卡是否存在
   5、定义card_pay(self, cost, paytype, sereialno)函数,信用卡支付,从信用卡可透支余额中扣费
        (1)、根据传入的paytype的值,定义payfor的名称,例:1:消费、2:转账、3:提现、4:手续费
        (2)、支付扣款self.credit_balance -= cost
        (3)、定义_tmp_bill_record,记录消费流水对账单
        (4)、将消费流水对账单写回到文件report_bill
        (5)、更新信用卡可透支余额信息到数据库 creditcard.db
   6、定义新发行信用卡create_card函数,根据输入的卡号密码等信息并更新到creditcard.db
   7、定义信用卡更新update_card函数,根据输入的卡号密码等信息并更新到creditcard.db
   8、定义转账、提现时验证操作_pay_check函数,转账、提现时验证操作,判断卡的余额与支付密码是否正确。并   返回错误类型码
   9、定义提现函数fetch_money(self, count, passwd)
        (1)、根据传入的取现金额,计算取现+手续费总额
        (2)、调用_pay_check函数,根据返回值进行操作。
        (3)、如果返回值是errorcode.NO_ERROR,则调用card_pay函数将取现金额和手续费计帐,并回写文件
        (4)、并返回errorcode.NO_ERROR
   10、定义信用卡转账函数translate_money(self, trans_count, passwd, trans_cardobj)
        (1)、根据传入的转帐金额,计算转帐+手续费总额
        (2)、调用_pay_check函数,根据返回值进行操作。
        (3)、如果返回值是errorcode.NO_ERROR,则调用card_pay函数将转帐金额和手续费计帐,并回写文件
        (4)、并给对方卡充值,trans_cardobj.credit_balance += trans_count,并调用trans_cardobj.update_card()写入数据库文件
        (4)、并返回errorcode.NO_ERROR
   11、定义对账单列表数据函数load_statement_list,调用dbapi.load_statement_list(self.cardno)
   12、定义recreate_statement函数,实现今天的日期将当前卡的对账单重新生成,主要对过了还款日的账单重新生    成利息信息
        (1)、获取当前日期today
        (2)、获取卡的对账单信息card_statement = dbapi.load_statement_list(self.cardno)
        (3)、如果有记录,进行循环读取,并判断isfinished字段是否是1,是则加记录加到临时列表tmp_list
        (4)、未还款,则获取pdate还款时期,并判断是否过期
        (5)、如果过期则计算利息:record[k]["interest"] = v["total"] * settings.EXPIRE_DAY_RATE * day_delta
        (6)、将过期或非过期的记录都加到临时列表tmp_list
        (7)、将更新过的列表写入文件,替换原有信息dbapi.write_statement_list(self.cardno, tmp_list)

4、common.py介绍:
   1、函数verification_code(),用来生成一个4位的验证码,并返回验证码
   2、函数encrypt(string),用来字符串加密
   3、函数write_log(content),用来写错误日志
   4、函数get_chinese_num(uchar),用来计算汉字的个数
   5、函数show_message(msg, msgtype)根据msgtype类型,对print函数进行封装,根据不同类型显示不同颜色
   6、函数create_serialno(),用来生成一个消费、转账、提款时的流水号,不重复
   7、函数numtochr(num_of_weekday),将数字星期转换为中文数字
   8、函数input_msg(message, limit_value=tuple()),判断input输入的信息是否为空的公共检测函数,为空继续输入,不为空返回输入的信息
   9、函数input_date(msg, default_date),对输入的日期进行判断是否正确 yyyy-mm-dd or yyyy-m-d

5、report.py介绍: 账单生成模块
   1、导入calendar,timedelta等模块
   2、函数get_date(),用来用户输入一个时间段,如果显示报表是要提供开始、结束日期,返回开始,结束时间
       2.1 调用common.input_date来生成一个开始日期startdate
       2.2 调用common.input_date来生成一个结束日期enddate
       2.3 返回一个时间的字典
   3、函数print_shopping_history(userobj),个人中心 - 购物历史记录打印模块
   4、函数print_bill_history(userobj) ,个人中心-账单明细 打印模块
   5、函数create_card_statement(cardno),生成信用卡对账单
   6、函数create_statement_main(),卡对账单初始化模块,从卡数据库文件中加载所有卡号,对所有卡调用生成对账单模块
   7、函数print_statement_list(cardno, list_info),将卡号对应的未还款记录显示出来
   8、函数print_statement_detail(cardno, serino, details),还款模块 - 用户选择还款的单号后,显示详细的还款对账单及流水信息

ATM 模拟程序说明

系统主程序为根目录下的:day5_credit_card.py

1. 系统功能模块

Day5_ATM 模拟程序是在python3.0 环境下开发

2. 系统目录结构:

程序采用分层的方式编写,包括数据库访问层、数据库层(数据文件)、业务逻辑层(module 层),业务处理层(主程序)

3.应用知识点:
  • a) 字典、列表、元组的操作
  • b) 文件的读写操作
  • c) 函数的应用
  • d) 类的使用
  • e) 装饰器、反射

代码如下:

1、主程序credit_card.py:

#!/usr/bin/env python
# -*- encoding:utf-8 -*-

import os,sys

from datetime import date, datetime
from conf import template, errorcode
from conf import settings
from modules import shopping, common
from dbhelper import dbapi
from modules.users import Users
from modules.creditcard import CreditCard
from modules import report


def doshopping(userobj):
    """
    购物商城模块,进行购物部分的所有处理
    :param userobj:  一个用户对象,如果用户未登录,在支付模块会通过装饰器来登录
    :return:
    """
    # 实例化商城
    shoppobj = shopping.Shopping()
    # 选择商品类型
    exitflag = False
    while not exitflag:
        # 开始菜单
        print(shoppobj.welcome_menu)
        shop_cassify_id = input("请选择商品分类编号[1-3]: ").strip().lower()
        if not shop_cassify_id: continue
        if shop_cassify_id == "0":
            exitflag = True
            continue
        if int(shop_cassify_id) not in range(1, 6):
            common.show_message("请选择正确的商品类型编号!", "ERROR")

            continue
        elif shop_cassify_id == "4":
            # 查看购物车
            shopping.Shopping.print_goods_list(shoppobj.shopping_cart)
            common.show_message("当前购物车共有 {0} 件商品,合计 {1} 元 !".format(len(shoppobj.shopping_cart),
                                                                    shoppobj.shopping_cost), "INFORMATION")
            continue
        elif shop_cassify_id == "5":
            # 购物结算
            dealresult = shoppobj.payfor_shopcart(userobj)
            if dealresult == errorcode.NO_ERROR:
                common.show_message("支付完成!", "INFORMATION")

        else:
            # 获取用户选择的商品类型编号
            shoppobj.goods_classify_id = shop_cassify_id
            # 获得商品类型编号对应的商品列表
            goods_list = shoppobj.get_goods_list_by_typeid()

            if not goods_list:
                common.show_message("未找到商品信息!", "NOTICE")

                continue

            # 开始选择商品,添加到购物车
            choose_goods_flag = True
            while choose_goods_flag:
                # 显示指定商品分类下的所有商品列表(Shopping类静态方法)
                shopping.Shopping.print_goods_list(goods_list)
                goods_id = input("选择商品编号,加入购物车(q返回上一级): ").strip().lower()
                if not goods_id: continue
                # 返回上一级
                if goods_id == "q":
                    choose_goods_flag = False
                    continue
                else:
                    # 将选择商品加入购物车
                    result = shoppobj.add_shopping_card(goods_id)
                    if result:
                        # 添加成功,显示购物车所有商品信息
                        shopping.Shopping.print_goods_list(shoppobj.shopping_cart)
                        common.show_message("已将商品加入购物车!", "INFORMATION")

                        # 是否继续添加
                        nextflag = False
                        while not nextflag:
                            donext = input("继续购物(y) or 返回上一级(q):").strip().lower()
                            if donext == "y":
                                break
                            elif donext == "q":
                                choose_goods_flag = False
                                break
                            else:
                                continue
                    else:
                        # 添加购物车失败
                        common.show_message("添加购物车失败,请检查输入商品编号是否正确!", "ERROR")

                        continue


def user_login(userobj, today, weekoftoday):
    """
    主菜单的2号菜单登录系统模块
    :param userobj: 当前用户对象
    :param today: 菜单显示的日期
    :param weekoftoday: 菜单显示的星期
    :return:
    """
    quitflag = False
    while not quitflag:
        if userobj.islogin:
            # 如果用户已经登录,菜单功能2为个人中心,调用另一个菜单模板 index_user_center
            print(template.index_user_center.format(userobj.name, today, common.numtochr(weekoftoday)))
            _chooseflag = False
            while not _chooseflag:
                _choose = input("选择功能:")
                if _choose not in ("1", "2", "3", "4", "5", "6"):
                    common.show_message("选择正确的功能编号!", "ERROR")
                    continue
                else:
                    _chooseflag = True

            # 返回上级菜单
            if _choose == "6":
                quitflag = True
            else:
                # 根据用户按键开始处理,从 template 模块查找各按键对应的模块,通过反射来执行
                func_dict = template.user_center_func
                modulepy = __import__(func_dict[_choose]["module"])
                # 1,2,5号键为users类方法,
                if _choose in (\'1\', \'2\', \'5\'):
                    modulesobj = getattr(modulepy, "users")
                    classobj = getattr(modulesobj, "Users")
                    func = getattr(classobj, func_dict[_choose]["func"])

                else:
                    # 3,4为 report 模块的方法
                    modulesobj = getattr(modulepy, "report")
                    func = getattr(modulesobj, func_dict[_choose]["func"])

                func(userobj)
        else:
            # 用户未登录,调用 Users类的登录模块
            userobj.login()
            quitflag = True


def card_center(userobj):
    if userobj.islogin:
        # 重新load一下数据
        userobj.db_load()
        cardno = userobj.bindcard
        # 获得信用卡对象
        card = CreditCard(cardno)
    else:
        # 未登录信用卡
        input_flag = False
        while not input_flag:
            cardno = input("请输入信用卡卡号: ").strip().lower()
            if cardno.isnumeric():
                card = CreditCard(cardno)
                if card.card_is_exists:
                    pwd = input("请输入密码:")
                    if common.encrypt(pwd) == card.password:
                        common.show_message("登录成功", "NOTICE")
                        input_flag = True
                        continue
                else:
                    common.show_message("卡号不存在,请重新输入!", "ERROR")
                    continue
            else:
                common.show_message("卡号无效!", "ERROR")
                continue

    show_template = template.index_ATM
    quitflag = False
    while not quitflag:
        print(show_template.format(cardno=card.cardno))
        _choose = common.input_msg("请选择功能: ", ("1", "2", "3", "4", "5"))
        # 返回
        if _choose == "5":
            quitflag = True
            continue

        # 查看信用卡信息
        if _choose == "1":
            common.show_message(template.card_info.format(cardno=card.cardno,
                                                          owner=card.owner,
                                                          total=card.credit_total,
                                                          balance=card.credit_balance,
                                                          status="正常" if card.frozenstatus == 0 else "冻结"
                                                          ), "NOTICE")
        # 提现
        if _choose == "2":
            if card.frozenstatus == 1:
                common.show_message("卡已冻结,请联系客服!", "ERROR")
            else:
                common.show_message("信用卡提现将收取 {0}% 的手续费!".format(settings.FETCH_MONEY_RATE * 100), "NOTICE")
                quitflag = False
                while not quitflag:
                    cost = common.input_msg("请输入要提现的金额(q返回):")
                    if cost.isnumeric():
                        cardpasswd = common.input_msg("请输入信用卡密码:")
                        # 执行提现操作
                        exe_result = card.fetch_money(float(cost), cardpasswd)
                        if exe_result == errorcode.NO_ERROR:
                            common.show_message("已完成提现!", "NOTICE")
                        if exe_result == errorcode.BALANCE_NOT_ENOUGHT:
                            common.show_message("信用卡可透支余额不足!", "ERROR")
                        if exe_result == errorcode.CARD_PASS_ERROR:
                            common.show_message("信用卡密码错误!", "ERROR")
                    elif cost == "q":
                        quitflag = True
                        continue
                    else:
                        common.show_message("输入错误!", "ERROR")
        # 转账
        if _choose == "3":
            if card.frozenstatus == 1:
                common.show_message("此卡已冻结,请联系客服!", "ERROR")
            else:
                common.show_message("信用卡转账将收取 {0}% 的手续费!".format(settings.FETCH_MONEY_RATE * 100), "NOTICE")
                quitflag = False
                while not quitflag:
                    trans_cardno = common.input_msg("请输入要转账的卡号(q返回):")
                    if trans_cardno.isnumeric():
                        # 生成一个卡对象, 验证卡号是否存在
                        trans_cardobj = CreditCard(trans_cardno)

                        # 卡号不存在返回主菜单
                        if not trans_cardobj.card_is_exists:
                            common.show_message("卡号不存在,请确认!", "ERROR")
                            quitflag = True
                            continue
                        else:
                            # 卡号存在
                            trans_cost = common.input_msg("请输入要转账的金额: ")

                            # 如果输入的均为数字
                            if trans_cost.isnumeric():
                                comfirm = common.input_msg("确定要给卡号 {0} 转入人民币 {1} 元吗(y/n)?".format(trans_cardobj.cardno,
                                                                                                  trans_cost),
                                                           ("y", "n"))
                                if comfirm == "y":
                                    cardpasswd = common.input_msg("请输入信用卡密码:")

                                    # 执行转账操作
                                    exe_result = card.translate_money(float(trans_cost), cardpasswd, trans_cardobj)

                                    if exe_result == errorcode.NO_ERROR:
                                        common.show_message("转账完成!", "NOTICE")
                                    if exe_result == errorcode.BALANCE_NOT_ENOUGHT:
                                        common.show_message("信用卡可透支余额不足!", "ERROR")
                                    if exe_result == errorcode.CARD_PASS_ERROR:
                                        common.show_message("信用卡密码错误!", "ERROR")
                            else:
                                common.show_message("输入错误!", "ERROR")

                    elif trans_cardno == "q":
                        quitflag = True
                        continue
                    else:
                        common.show_message("输入错误!", "ERROR")

        # 还款
        if _choose == "4":
            # 更新一下对账单信息
            card.recreate_statement()

            quitflag = False
            while not quitflag:
                # 获取对账单所有列表
                interest_list = card.load_statement_list()
                # 获取还未还款的记录并显示
                message_info = report.print_statement_list(card.cardno, interest_list)

                # 如果有要还款的记录
                if len(message_info) > 0:
                    common.show_message(message_info, "NOTICE")
                    # 输入要还款的单号
                    serino_list = list()
                    for order in interest_list:
                        serino_list.append(list(order.keys())[0])
                    serino_list.append("q")
                    pay_serno = common.input_msg("请选择还款的16位账单号(q退出):", tuple(serino_list))

                    if pay_serno == "q":
                        quitflag = True
                        continue
                    else:
                        for i in range(len(interest_list)):
                            for k, details in interest_list[i].items():
                                if k == pay_serno:
                                    # 显示指定单号的相信对账单信息
                                    common.show_message(report.print_statement_detail(card.cardno,
                                                                                      pay_serno,
                                                                                      details),
                                                        "NOTICE")
                                    pay_fee = common.input_msg("请输入还款金额:")
                                    if pay_fee.isnumeric():
                                        # 更新已还款金额 = 现在还的金额 + 已经还的金额
                                        total_payed = details["payed"] + float(pay_fee)
                                        interest_list[i][pay_serno]["payed"] = total_payed

                                        # 全还了吗?需要还款数 = 消费总费用 + 利息
                                        need_pay = details["total"] + details["interest"]
                                        if total_payed >= need_pay:
                                            # 还款数大于等于需要还款数,则更新已还款字段信息
                                            interest_list[i][pay_serno]["isfinished"] = 1
                                        else:
                                            # 没全部还款
                                            common.show_message("您尚未全部还款,请在还款日前尽快还款!", "NOTICE")
                                        # 将还款后的信息写入数据库更新
                                        dbapi.write_statement_list(card.cardno, interest_list)

                                        # 还款成功
                                        common.show_message("还款成功", "NOTICE")
                                        # 是否继续
                                        iscontinue = common.input_msg("继续还款吗(y/n)?", ("y", "n"))
                                        if iscontinue == "n":
                                            quitflag = True

                                    else:
                                        common.show_message("输入数据不正确,请重新输入!", "ERROR")
                else:
                    common.show_message("无账单信息!", "NOTICE")
                    quitflag = True


def get_users():
    """
    显示用户的信息,用户新建、删除、解锁用户时显示用户基本信息
    :return:
    """
    username = common.input_msg("请输入用户名:")
    # 创建一个用户实例
    _deluser = Users()
    _deluser.username = username
    # 如果用户名存在,load用户信息成功
    if _deluser.load_user_info():
        # 先显示一下用户的信息
        common.show_message(template.user_info.format(username=_deluser.username,
                                                      name=_deluser.name,
                                                      mobile=_deluser.mobile,
                                                      role=_deluser.role,
                                                      isdel="否" if _deluser.isdel == 0 else "是",
                                                      islocked="否" if _deluser.islocked == 0 else "是",
                                                      bindcard=_deluser.bindcard)
                            , "NOTICE")
        return _deluser
    else:
        common.show_message("用户名不存在!", "ERROR")
        return False


def fill_card_info():
    """
    填充信用卡资料信息
    :return: 返回一个信用卡对象
    """
    retry_flag = False
    while not retry_flag:
        cardno = common.input_msg("请输入卡号:")
        cardobj = CreditCard(cardno)
        if cardobj.card_is_exists:
            common.show_message("卡号已存在,请重新输入卡号", "ERROR")
            continue
        else:
            retry_flag = True
            continue

    cardobj.password = common.input_msg("请输入密码:")
    cardobj.credit_total = common.input_msg("信用额度(default:{0}):".format(cardobj.credit_total))
    cardobj.credit_balance = cardobj.credit_total
    cardobj.owner = common.input_msg("所有者:")
    return cardobj


def manager(userobj):
    """
    主菜单后台管理模块
    :param userobj: 当前登录用户对象
    :return:
    """
    if userobj.islogin:
        if userobj.role == "admin":
            quit_flag = False
            while not quit_flag:
                _show_template = template.index_admin
                print(_show_template.format(username=userobj.name))
                _choose = input("选择操作功能: ").strip().lower()
                # 创建新用户
                if _choose == "1":
                    _newuser = Users()
                    # 调用初始化用户函数创建新用户
                    _newuser.init_user_info()
                # 删除用户
                if _choose == "2":
                    _user = get_users()
                    if _user:
                        confirm = common.input_msg("确定要删除此用户吗(y/n)?", ("y", "n"))
                        if confirm == "y":
                            _user.del_user()
                            common.show_message("用户删除成功!", "NOTICE")
                # 解锁用户
                if _choose == "3":
                    _user = get_users()
                    if _user:
                        confirm = common.input_msg("确认解锁吗(y/n)?", ("y", "n"))
                        if confirm == "y":
                            _user.unlock_user()
                            common.show_message("用户解锁成功!", "NOTICE")
                # 发行信用卡
                if _choose == "4":
                    newcard = fill_card_info()
                    newcard.create_card()
                    common.show_message("发卡成功!", "NOTICE")

                # 冻结信用卡
                if _choose == "5":
                    cardno = common.input_msg("输入卡号:")
                    card = CreditCard(cardno)
                    if not card.card_is_exists:
                        common.show_message("卡号不存在", "ERROR")
                    else:
                        # 调用模板显示卡信息
                        common.show_message(template.card_info.format(cardno=card.cardno,
                                                                      owner=card.owner,
                                                                      total=card.credit_total,
                                                                      balance=card.credit_balance,
                                                                      status="正常" if card.frozenstatus == 0 else "冻结"
                                                                      ), "INFORMATION")
                        confirm = common.input_msg("确认要冻结此卡吗(y/n)?", ("y", "n"))
                        if confirm == "y":
                            card.frozenstatus = 1
                            card.update_card()
                            common.show_message("此卡已冻结!", "NOTICE")
                # 退出
                if _choose == "0":
                    quit_flag = True
        else:
            # 不是 admin 角色无权限
            common.show_message("权限不够!", "ERROR")
    else:
        common.show_message("请先登录系统!", "NOTICE")
        userobj.login()


if __name__ == "__main__":
    today = datetime.now().strftime("%Y-%m-%d")
    weekoftoday = date.weekday(datetime.now())
    curruser = Users()

    # 初始化对账单
    report.create_statement_main()

    # --------    开始主程序   -------------------
    exitflag = False
    while not exitflag:
        # 如果用户登录了,显示登录的界面; 未登录显示未登录的界面
        if not curruser.islogin:
            print(template.index_default_menu.format("", today, common.numtochr(weekoftoday)))
        else:
            print(template.index_logined_menu.format("欢迎您: {0}".format(curruser.name), today,
                                                     common.numtochr(weekoftoday)))

        choose = common.input_msg("选择功能编号[1-5]: ", ("1", "2", "3", "4", "5")).strip()
        if choose == "5":
            exitflag = True
            continue

        # 1 购物商城
        if choose == "1":
            curruser.db_load()
            doshopping(curruser)

        # 2 用户登录
        if choose == "2":
            curruser.db_load()
            user_login(curruser, today, weekoftoday)

        # 3 信用卡管理
        if choose == "3":
            card_center(curruser)

        # 4 后台管理
        if choose == "4":
            manager(curruser)

2、配置文件包conf下代码:

2.1 参数配置文件settings.py:

#!/usr/bin/env python

import os,sys

# 程序文件主目录
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 添加环境变量
sys.path.append(BASE_DIR)

# 数据库信息
DATABASE = dict(engineer="file", dbpath=os.path.join(BASE_DIR, "database"), tables={"users": "users",
                                                                                    "shopping": "shoppingmark",
                                                                                    "creditcard": "creditcard"
                                                                                    })

# 日志文件存放路径
LOG_PATH = os.path.join(BASE_DIR, "logs")
# 账单报表文件路径
REPORT_PATH = os.path.join(BASE_DIR, "report")
# 用户登录失败最大次数
ERROR_MAX_COUNT = 3
# 日息费率
EXPIRE_DAY_RATE = 0.0005
# 转账、提现手续费
FETCH_MONEY_RATE = 0.05
# 信用额度
CREDIT_TOTAL = 10000
# 每月账单日期(默认每月22日为账单日)
STATEMENT_DAY = 6

2.2 界面显示模板文件templates.py:

#!/usr/bin/env python
"""
该模块用来定义系统的菜单模板
"""
# 主程序中的主菜单

index_default_menu = \'\'\'
-------------------------------------------------------------------------
                             ATM 模拟程序

{0}                                        今天 {1}   星期{2}
-------------------------------------------------------------------------
【1】进入商城 【2】登录系统 【3】信用卡中心 【4】后台管理 【5】退出系统
\'\'\'

# 主程序中的用户登录后的显示菜单

index_logined_menu = \'\'\'
-------------------------------------------------------------------------
                             ATM 模拟程序

{0}                                        今天 {1}   星期{2}
-------------------------------------------------------------------------
【1】进入商城 【2】用户中心 【3】信用卡中心 【4】后台管理 【5】退出系统
\'\'\'

# 主程序中的用户中心菜单

index_user_center = \'\'\'
-------------------------------------------------------------------------
                                用户中心

当前用户:{0}                                   今天 {1}   星期{2}
-------------------------------------------------------------------------
【1】修改密码 【2】修改资料 【3】我的账单 【4】购物记录 【5】注销 【6】返回

\'\'\'

# 用户中心按键对应功能模块
user_center_func = {
    "1": {"module": "modules.users", "func": "modify_password"},
    "2": {"module": "modules.users", "func": "modify_user_info"},
    "3": {"module": "modules.report", "func": "print_bill_history"},
    "4": {"module": "modules.report", "func": "print_shopping_history"},
    "5": {"module": "modules.users", "func": "logout"}
}

# 购物模块的主菜单, menu 菜单在shopping模块中内部构造

shopping_index_menu = \'\'\'
    ==================================================================================
    =                                                                                =
    =                                 信用卡购物商城                                  =
    =                                                                                =
    ==================================================================================

    {menu}
    \'\'\'

# 账单报表显示模板
report_bill = \'\'\'
------------------------------------------------------------------------------
                                 用户中心 - 账单明细

卡号:{cardno}                           账单时间:{startdate} 至 {enddate}
------------------------------------------------------------------------------
     交易时间        交易类型        交易金额           流水号
{billdetail}

\'\'\'

# 购物历史记录显示模板
shopping_history = \'\'\'
------------------------------------------------------------------------------
                                  用户中心 - 购物明细

用户:{username}                           购物时间:{startdate} 至 {enddate}
------------------------------------------------------------------------------
\'\'\'

# 后台管理模板
index_admin = \'\'\'
------------------------------------------------------------------------------
                               后台管理

用户:{username}
------------------------------------------------------------------------------
【1】创建用户               【2】删除用户         【3】解锁用户
【4】发行信用卡             【5】冻结信用卡       【0】退出后台管理
\'\'\'

# ATM 管理模块
index_ATM = \'\'\'
------------------------------------------------------------------------------
                               信用卡管理中心

卡号:{cardno}
------------------------------------------------------------------------------
【1】我的信用卡    【2】提现    【3】转账     【4】还款    【5】返回
\'\'\'

# 显示用户基本信息模板
user_info = \'\'\'
------------------------------------------------------------------------------
                               用户基本信息

用 户 名:{username}        姓    名:{name}               手    机:{mobile}
用户权限:{role}            是否锁定:{islocked}           是否删除:{isdel}
信用卡号:{bindcard}
------------------------------------------------------------------------------
\'\'\'

# 显示信用卡基本信息模板
card_info = \'\'\'
-----------------------------------------------------------------------------------
                               信用卡基本信息

卡号:{cardno}   所有人:{owner}  信用额度:{total}  剩余额度:{balance} 状态:{status}
-----------------------------------------------------------------------------------
\'\'\'
report_statement_list = \'\'\'
----------------------------------------------------------------------------------
                                信用卡对账单列表
卡号:{cardno}
----------------------------------------------------------------------------------
    账单号            还款日        应还款        已还款
{show_msg}
\'\'\'

report_statement_detail = \'\'\'
---------------------------------------------------------------------------------------
                               信用卡对账单

卡号:{cardno}                                          账单编号:{serino}
---------------------------------------------------------------------------------------
  账单日            账单日期范围              还款日       应还款     已还款     利息
{billdate}    {sdate} 至 {edate}     {pdate}    {total}     {payed}     {interest}
---------------------------------------------------------------------------------------
账单明细:
     交易时间        交易类型        交易金额           流水号
{details}
\'\'\'

2.3 错误代码文件errorcode.py:

#!/usr/bin/env python
"""
系统错误代码表
"""
NO_ERROR = 99999               # 系统正常返回
USER_NOT_EXISTS = 10000        # 用户名不存在
CARD_NOT_BINDED = 10001        # 用户未绑定信用卡
BALANCE_NOT_ENOUGHT = 10002    # 信用卡余额不足
CARD_OWNER_ERROR = 10003       # 绑定卡时输入的卡号与卡的所有人不一致
CARD_PASS_ERROR = 10004        # 信用卡密码错误

3、数据库database下代码:

3.1 初始化数据模块init_db.py:

#!/usr/bin/env python
import json,os,sys

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

from conf import settings
from modules import common

# 初始化数据表
_shopping_list = {
    "1": {"typename": "食品生鲜", "product": (
        {"no": "0001", "name": "进口牛奶 欧德堡(Oldenburger)1L*12", "price": 95},
        {"no": "0002", "name": "乐虎氨基酸维生素功能饮料250ML*24罐", "price": 120},
        {"no": "0003", "name": "意大利进口 Ferrero Rocher费列罗巧克力(盒)", "price": 205},
        {"no": "0004", "name": "品湖韵阳澄湖大闸蟹礼券1388型 8只", "price": 458},
        {"no": "0005", "name": "三胖蛋 正宗内蒙原味大瓜子218g*6桶/礼", "price": 168},
        {"no": "0006", "name": "臻味山珍礼盒 吉年纳福1600g干菌山珍大礼包", "price": 256}
    )},
    "2": {"typename": "数码产品", "product": (
        {"no": "1001", "name": "佳能(Canon) EOS 6D 单反机身(不含镜头) 家庭套餐", "price": 9326},
        {"no": "1002", "name": "360安全路由P1 3mm纤薄设计 大户型智能无线路由器", "price": 89},
        {"no": "1003", "name": "小米 4c 高配版 全网通 白色 移动联通电信", "price": 1499},
        {"no": "1004", "name": "华为(HUAWEI)荣耀手环zero 经典黑短", "price": 399},
        {"no": "1005", "name": "步步高(BBK)家教机S2 香槟金 32G ", "price": 3468},
        {"no": "1006", "name": "Apple MacBook Air 13.3英寸笔记本电脑", "price": 6988}
    )},
    "3": {"typename": "男装女装", "product": (
        {"no": "2001", "name": "伊莲娜2016新款连衣裙英伦格子针织连衣裙假两件裙加厚", "price": 163},
        {"no": "2002", "name": "Maxchic玛汐2016春时尚分割修身圆领修身长袖连衣裙", "price": 235},
        {"no": "2003", "name": "2015新冬款加厚加绒牛仔裤女保暖小脚裤大码弹力铅笔裤", "price": 169},
        {"no": "2004", "name": "秋冬新款青年男士休闲连帽羽绒服男韩版修身短款外套", "price": 319},
        {"no": "2005", "name": "AAPE秋冬季新款 时尚潮牌猿人头袖英文字母印花男士休闲", "price": 298},
        {"no": "2006", "name": "2015秋冬新款加绒保暖套头卫衣 15541707 BC17灰花灰", "price": 159}
    )}
}

_user_list = {
    "test": {"password": "12345", "name": "测试", "mobile": "13511111111", "islocked": 0, "bindcard": "1001012345",
             "role": "user", "isdel": 0},
    "super": {"password": "12345", "name": "Admin", "mobile": "15257157418", "islocked": 0, "bindcard": "1001010002",
              "role": "admin", "isdel": 0}
}

_creditcard_list = {
    "1001012345": {"password": "12345", "credit_total": 10000, "credit_balance": 10000,
                   "owner": "test", "frozenstatus": 0},
    "1001010002": {"password": "12345", "credit_total": 10000, "credit_balance": 10000,
                   "owner": "super", "frozenstatus": 0}
}


# 初始化购物商城数据表 shopping_list.db
def init_db_shoppingmark():
    _db_file = os.path.join(settings.DATABASE[\'dbpath\'], "shoppingmark.db")
    with open(_db_file, "w+") as f:
        f.write(json.dumps(_shopping_list))


# 初始化用户数据表 user_list.db
def init_db_users():
    _db_file = os.path.join(settings.DATABASE[\'dbpath\'], "users.db")
    with open(_db_file, "w+") as fu:
        for k, v in _user_list.items():
            # 获得用户设置的密码
            tmppassword = _user_list[k][\'password\']
            # 对密码进行加密
            encrypassword = common.encrypt(tmppassword)
            # 修改明文密码
            _user_list[k][\'password\'] = encrypassword
        fu.write(json.dumps(_user_list))


# 初始化信用卡数据表 creditcard.db
def init_db_creditcard():
    _db_file = os.path.join(settings.DATABASE[\'dbpath\'], "creditcard.db")
    with open(_db_file, "w+") as fc:
        for k, v in _creditcard_list.items():
            tmppassword = _creditcard_list[k][\'password\']
            encrypassword = common.encrypt(tmppassword)
            _creditcard_list[k][\'password\'] = encrypassword
        fc.write(json.dumps(_creditcard_list))


# 初始化数据表
def init_database():
    tables = list(settings.DATABASE[\'tables\'].values())  # 数据表名称列表
    database = settings.DATABASE[\'dbpath\']  # 数据表存放路径
    for _table in tables:
        # 如果表不存在
        if not os.path.exists(os.path.join(database, "{0}.db".format(_table))):
            print("Table {0}.db create successfull".format(_table))
            # 通过反射初始化数据表

            if hasattr(sys.modules[__name__], "init_db_{0}".format(_table)):
                init_func = getattr(sys.modules[__name__], "init_db_{0}".format(_table))
                init_func()
            else:
                common.write_error_log("init table {0} failed,no function init_db_{0} found".format(_table))


if __name__ == "__main__":
    init_database()

执行init_db脚本可生成json格式的users.db、shoppingmark.db和creditcard.db

内容如下:

3.2 数据文件:

- users
{"test": {"isdel": 0, "name": "\\u6d4b\\u8bd5", "password": "8ad8dd76a16dca9ffcfc970a807a6378", "islocked": 0, "role": "user", "bindcard": "1001012345", "mobile": "13511111111"}, "super": {"isdel": 0, "name": "Admin", "password": "8ad8dd76a16dca9ffcfc970a807a6378", "islocked": 0, "role": "admin", "bindcard": "1001010002", "mobile": "15257157418"}}

- shoppingmarket
{"2": {"product": [{"no": "1001", "name": "\\u4f73\\u80fd\\uff08Canon\\uff09 EOS 6D \\u5355\\u53cd\\u673a\\u8eab\\uff08\\u4e0d\\u542b\\u955c\\u5934\\uff09 \\u5bb6\\u5ead\\u5957\\u9910", "price": 9326}, {"no": "1002", "name": "360\\u5b89\\u5168\\u8def\\u7531P1 3mm\\u7ea4\\u8584\\u8bbe\\u8ba1 \\u5927\\u6237\\u578b\\u667a\\u80fd\\u65e0\\u7ebf\\u8def\\u7531\\u5668", "price": 89}, {"no": "1003", "name": "\\u5c0f\\u7c73 4c \\u9ad8\\u914d\\u7248 \\u5168\\u7f51\\u901a \\u767d\\u8272 \\u79fb\\u52a8\\u8054\\u901a\\u7535\\u4fe1", "price": 1499}, {"no": "1004", "name": "\\u534e\\u4e3a\\uff08HUAWEI\\uff09\\u8363\\u8000\\u624b\\u73afzero \\u7ecf\\u5178\\u9ed1\\u77ed", "price": 399}, {"no": "1005", "name": "\\u6b65\\u6b65\\u9ad8\\uff08BBK\\uff09\\u5bb6\\u6559\\u673aS2 \\u9999\\u69df\\u91d1 32G ", "price": 3468}, {"no": "1006", "name": "Apple MacBook Air 13.3\\u82f1\\u5bf8\\u7b14\\u8bb0\\u672c\\u7535\\u8111", "price": 6988}], "typename": "\\u6570\\u7801\\u4ea7\\u54c1"}, "1": {"product": [{"no": "0001", "name": "\\u8fdb\\u53e3\\u725b\\u5976 \\u6b27\\u5fb7\\u5821(Oldenburger)1L*12", "price": 95}, {"no": "0002", "name": "\\u4e50\\u864e\\u6c28\\u57fa\\u9178\\u7ef4\\u751f\\u7d20\\u529f\\u80fd\\u996e\\u6599250ML*24\\u7f50", "price": 120}, {"no": "0003", "name": "\\u610f\\u5927\\u5229\\u8fdb\\u53e3 Ferrero Rocher\\u8d39\\u5217\\u7f57\\u5de7\\u514b\\u529b(\\u76d2)", "price": 205}, {"no": "0004", "name": "\\u54c1\\u6e56\\u97f5\\u9633\\u6f84\\u6e56\\u5927\\u95f8\\u87f9\\u793c\\u52381388\\u578b 8\\u53ea", "price": 458}, {"no": "0005", "name": "\\u4e09\\u80d6\\u86cb \\u6b63\\u5b97\\u5185\\u8499\\u539f\\u5473\\u5927\\u74dc\\u5b50218g*6\\u6876/\\u793c", "price": 168}, {"no": "0006", "name": "\\u81fb\\u5473\\u5c71\\u73cd\\u793c\\u76d2 \\u5409\\u5e74\\u7eb3\\u798f1600g\\u5e72\\u83cc\\u5c71\\u73cd\\u5927\\u793c\\u5305", "price": 256}], "typename": "\\u98df\\u54c1\\u751f\\u9c9c"}, "3": {"product": [{"no": "2001", "name": "\\u4f0a\\u83b2\\u5a1c2016\\u65b0\\u6b3e\\u8fde\\u8863\\u88d9\\u82f1\\u4f26\\u683c\\u5b50\\u9488\\u7ec7\\u8fde\\u8863\\u88d9\\u5047\\u4e24\\u4ef6\\u88d9\\u52a0\\u539a", "price": 163}, {"no": "2002", "name": "Maxchic\\u739b\\u6c502016\\u6625\\u65f6\\u5c1a\\u5206\\u5272\\u4fee\\u8eab\\u5706\\u9886\\u4fee\\u8eab\\u957f\\u8896\\u8fde\\u8863\\u88d9", "price": 235}, {"no": "2003", "name": "2015\\u65b0\\u51ac\\u6b3e\\u52a0\\u539a\\u52a0\\u7ed2\\u725b\\u4ed4\\u88e4\\u5973\\u4fdd\\u6696\\u5c0f\\u811a\\u88e4\\u5927\\u7801\\u5f39\\u529b\\u94c5\\u7b14\\u88e4", "price": 169}, {"no": "2004", "name": "\\u79cb\\u51ac\\u65b0\\u6b3e\\u9752\\u5e74\\u7537\\u58eb\\u4f11\\u95f2\\u8fde\\u5e3d\\u7fbd\\u7ed2\\u670d\\u7537\\u97e9\\u7248\\u4fee\\u8eab\\u77ed\\u6b3e\\u5916\\u5957", "price": 319}, {"no": "2005", "name": "AAPE\\u79cb\\u51ac\\u5b63\\u65b0\\u6b3e \\u65f6\\u5c1a\\u6f6e\\u724c\\u733f\\u4eba\\u5934\\u8896\\u82f1\\u6587\\u5b57\\u6bcd\\u5370\\u82b1\\u7537\\u58eb\\u4f11\\u95f2", "price": 298}, {"no": "2006", "name": "2015\\u79cb\\u51ac\\u65b0\\u6b3e\\u52a0\\u7ed2\\u4fdd\\u6696\\u5957\\u5934\\u536b\\u8863 15541707 BC17\\u7070\\u82b1\\u7070", "price": 159}], "typename": "\\u7537\\u88c5\\u5973\\u88c5"}}

- creditcard
{"1001010002": {"credit_total": 10000, "owner": "super", "password": "8ad8dd76a16dca9ffcfc970a807a6378", "frozenstatus": 0, "credit_balance": 275}, "1001012345": {"credit_total": 10000, "owner": "test", "password": "8ad8dd76a16dca9ffcfc970a807a6378", "frozenstatus": 0, "credit_balance": 9537}}

4、数据访问层dbhelper下的dbapi.py:

数据访问层模块,读写数据

#!/usr/bin/env python
"""
__author: super
数据库访问层:
1 提供从数据文件、报表文件中读取数据的接口
2 将数据写入到数据文件的接口
"""
import os,json
from conf import settings
from modules.common import write_error_log,write_log


def append_db_json(contant, filename):
    """
    将信息以 json 格式写入数据表文件(追加)
    :param contant: 要写入的 json 格式内容
    :param filename: 要写入的数据表文件名
    :return: 无返回
    """
    try:
        with open(filename, \'a+\') as fa:
            fa.write(json.dumps(contant))
            fa.write("\\n")
    except Exception as e:
        write_error_log(e)


def write_db_json(contant, filename):
    """
    将信息以 json 格式写入数据表文件(覆盖)
    :param contant: 写入的json数据内容
    :param filename: 要写入的文件名
    :return: 无返回结果
    """
    try:
        with open(filename, \'w+\') as fw:
            fw.write(json.dumps(contant))
    except Exception as e:
        write_error_log(e)


def load_data_from_db(tabename):
    """
    从指定的数据表中获取所有数据,通过 json 方式将数据返回
    :param tabename: 数据文件名
    :return: 返回所有结果
    """
    try:
        with open(tabename, \'r+\') as f:
            return json.load(f)
    except Exception as e:
        write_error_log(e)


def load_bill_report(cardno, startdate, enddate):
    """
    从信用卡对账单中获取指定卡的对账信息数据, 获取某一个时间段内的数据
    :param enddate: 查询记录的结束日期
    :param startdate: 查询记录的开始日期
    :param cardno: 信用卡卡号
    :return: 信用卡对账单数据 ,返回结果为 list 数据类型
    """
    r_file = os.path.join(settings.REPORT_PATH, "report_bill")
    result = []
    try:
        with open(r_file, "r+") as f:
            for line in f:
                _record = json.loads(line)
                if _record["cardno"] == cardno:
                    if startdate <= _record["starttime"] <= enddate:
                        result.append(_record)
        return result
    except Exception as e:
        write_error_log(e)


def load_shop_history(user, startdate, enddate):
    """
    查找报表记录中的指定用户的购物历史记录,将结果存入到列表中
    :param user:  用户名
    :param startdate: 开始日期
    :param enddate: 结束日期
    :return: 结果 dict_list
    """
    _file = os.path.join(settings.REPORT_PATH, "shopping_history")
    result = list()
    try:
        with open(_file, "r") as f:
            for line in f:
                _record = json.loads(line)
                # 如果找到指定用户记录
                if list(_record.keys())[0] == user:
                    if list(_record.values())[0]["time"] >= startdate <= enddate:
                        result.append(_record)
        return result
    except Exception as e:
        write_error_log("dbapi > load_shop_history > {0}".format(e))


def load_statement_list(cardno):
    """
    从对账单中获取记录,
    :param cardno: 对账单文件
    :return: 返回一个列表
    """
    file = os.path.join(settings.REPORT_PATH, "statement_{0}".format(cardno))
    result_list =

以上是关于[py]python之信用卡ATM的主要内容,如果未能解决你的问题,请参考以下文章

python之ATM

Python实战之ATM+购物车

python基础之ATM-1

模拟实现ATM+购物商城的程序

6_python之路之atm购物

python第二十二天-----在做作业当中............