• 作业:ATM


    作业题目: 模拟实现一个ATM + 购物商城程序
    1、额度 15000或自定义 2、实现购物商城,买东西加入 购物车,调用信用卡接口结账 3、可以提现,手续费5% 4、支持多账户登录 5、支持账户间转账 6、记录每月日常消费流水 7、提供还款接口 8、ATM记录操作日志 9、提供管理接口,包括添加账户、用户额度,冻结账户等。。。 10、用户认证用装饰器
    流程图:


    代码目录结构图:

    atm
    │ ATM.pdf
    │ main_server.py --  程序入口
    │ README
    │ __init__.py


    ├─config
    │ │ setting.py ---- 配置文件
    │ │ __init__.py
    │ │
    │ └─__pycache__
    │ setting.cpython-36.pyc
    │ __init__.cpython-36.pyc

    ├─core
    │ │ admin.py -- 后台管理
    │ │ ATM_operation.py --- ATM操作
    │ │ auth.py --- 账户验证
    │ │ db_handler.py --- 文件操作
    │ │ loggers.py --- 日志
    │ │ main.py ---主程序入口
    │ │ make.py ---  交易中心
    │ │ shopping.py --- 购物商城
    │ │ __init__.py
    │ │
    │ └─__pycache__
    │ admin.cpython-36.pyc
    │ ATM_operation.cpython-36.pyc
    │ auth.cpython-36.pyc
    │ db_handler.cpython-36.pyc
    │ loggers.cpython-36.pyc
    │ main.cpython-36.pyc
    │ make.cpython-36.pyc
    │ shopping.cpython-36.pyc
    │ __init__.cpython-36.pyc



    ├─db
    │ │ __init__.py
    │ │
    │ └─accounts --- 账户文件
    │ 12.json
    │ 123.json
    │ 1234.json
    │ 14.json
    │ admin.json
    │ __init__.py

    ├─log
    │ │ access.log --- 普通用户操作日志
    │ │ admin.log --- 管理员操作日志
    │ │ shopping.log ---- 消费日志
    │ │ transaction.log ---- 交易日志
    │ │ __init__.py
    │ │
    │ └─__pycache__
    │ __init__.cpython-36.pyc

    └─shopp
    │ __init__.py

    └─__pycache__
    __init__.cpython-36.pyc

    main_server.py --  程序入口

    1 import os,sys
    2 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    3 sys.path.append(BASE_DIR)
    4 if __name__ == '__main__':
    5     from core import main
    6     main.entrance()

    main.py ---主程序入口

     1 from .auth import authentication
     2 from .loggers import logger_log
     3 from.ATM_operation import with_draw
     4 from .ATM_operation import transfer
     5 from .ATM_operation import pay_back
     6 from .ATM_operation import view_account_info
     7 from .shopping import shoppings
     8 from .admin import admin_load
     9 from .db_handler import load_account
    10 from .db_handler import save_db
    11 
    12 access_logger = logger_log('access')
    13 transaction_logger = logger_log('transaction')
    14 
    15 
    16 info = [
    17         ('查看账户信息',view_account_info),
    18         ('转账',transfer),
    19         ('还款',pay_back),
    20         ('取现',with_draw),
    21         ('购物商城',shoppings),
    22         ('后台管理',admin_load)
    23     ]
    24 
    25 def conroller(use_boj):
    26     '功能分发器'
    27     while True:
    28         for i,v in enumerate(info):
    29             print(i,v[0])
    30         choice = input('请输入您的选择:').strip()
    31         if not choice:continue
    32         if choice.isdigit():
    33             choice = int(choice)
    34             if choice < len(info) and choice >= 0:
    35                 info[choice][1](use_boj,transaction_logger=transaction_logger,access_logger=access_logger)
    36 def entrance():
    37     '程序入口'
    38     user_obj = {
    39         'is_authentication':False,
    40         'data':None
    41     }
    42     retry_count = 0
    43     while user_obj['is_authentication'] is not True:
    44         account = input('请输入账号:').strip()
    45         password = input('请输入密码:').strip()
    46         auth_data = authentication(account,password)
    47         if  auth_data:
    48             user_obj['is_authentication'] = True
    49             user_obj['data'] = auth_data
    50             print('欢迎登陆'.center(50,'*'))
    51             access_logger.info('%s已登陆'%user_obj['data']['id'])
    52             conroller(user_obj)
    53         else:
    54             print('账号密码错误!')
    55         retry_count += 1
    56         if retry_count == 3:
    57             msg = '用户%s已登陆3失败'%account
    58             access_logger.error(msg)
    59 
    60             break
    View Code

    auth.py  --- 账户验证

     1 from .db_handler import load_account
     2 
     3 def authentication(account,password):
     4     '验证账户'
     5     account_data = load_account(account)
     6     # print(account_data)
     7     if account_data['status'] == 0:
     8         account_data = account_data['data']
     9         if password == account_data['password']:
    10             # print(account_data)
    11             return account_data
    12         else:
    13             return None
    14     else:
    15         return '账户已被锁定!'
    16 def auth(fun):
    17     def wrapper(*args,**kwargs):
    18         if args[0].get('is_authentication'):
    19             return fun(*args,**kwargs)
    20         else:
    21             print('用户不能登陆!')
    22     return wrapper
    View Code

     db_handler.py --- 文件操作

     1 import json,os
     2 from config import setting
     3 
     4 def load_account(account):
     5     '读取文件'
     6     account_file = os.path.join(setting.BASE_DB,'%s.json'%account)
     7     # print(account_file)
     8     if os.path.isfile(account_file):
     9         f = open(account_file)
    10         data = json.load(f)
    11         f.close()
    12         return {'status':0,'data':data}
    13     else:
    14         return {'status':-1,'error':'文件不存在'}
    15 
    16 def save_db(account_data):
    17     '保存文件'
    18     account_file = os.path.join(setting.BASE_DB,'%s.json'%account_data)
    19     print(account_file)
    20     if os.path.isfile(account_file):
    21         f = open('%s.new'%account_file,'w')
    22         data = json.dump(account_data,f)
    23         f.close()
    24         os.remove(account_file)
    25         os.rename('%s.new'%account_file,account_file)
    26         return {'status':0,'data':data}
    27     else:
    28         return {'status':-1,'error':'文件不存在'}
    View Code

    ATM_operation.py --- ATM操作

     1 from .loggers import logger_log
     2 from .make import make_transfer
     3 from .auth import auth
     4 
     5 def view_account_info(account_data,*args,**kwargs):
     6     '查询账户信息'
     7     # print(account_data)
     8     trans_logger = kwargs.get('transaction_logger')
     9     print('账户个人信息'.center(50,'*'))
    10     for k,v in account_data['data'].items():
    11         if k not in ('password'):
    12             print('%15s:%s'%(k,v))
    13     print('END'.center(50,'*'))
    14     trans_logger.info('%s查询了账户信息'%account_data['data']['id'])
    15 @auth
    16 def transfer(account_data,*args,**kwargs):
    17     '账户转账'
    18     trans_logger = kwargs.get('transaction_logger')
    19     print('账户余额'.center(50,'*'))
    20     print('credit:%s
    '
    21           'blance:%s'%(account_data['data']['credit'],account_data['data']['balance']))
    22     flag_exit = False
    23     while not flag_exit:
    24         receiving_account = input('请输入接收账号或按B返回:').strip()
    25         transfer_amount = input('请输入转账金额按B返回:').strip()
    26         if len(transfer_amount) > 0 and transfer_amount.isdigit():
    27             transfer_amount = int(transfer_amount)
    28             if (account_data['data']['balance'] / 2) >= transfer_amount:
    29                 transaction_result = make_transfer(trans_logger,account_data,'transfer',transfer_amount,
    30                                                    receiving_account=receiving_account)
    31                 if transaction_result['status'] == 0:
    32                     print('成功转账%s元,余额还有%s'%(transfer_amount,account_data['data']['balance']))
    33                 else:
    34                     print(transaction_result)
    35             else:
    36                 print('余额不足,可转账%s元'%int(account_data['data']['balance']/2))
    37         if receiving_account == 'b'.lower():
    38             flag_exit = True
    39 @auth
    40 def with_draw(account_data,*args,**kwargs):
    41     '取现'
    42     trans_logger = kwargs.get('transaction_logger')
    43     print('账户余额'.center(50,'*'))
    44     print('credit:%s
    '
    45           'blance:%s'%(account_data['data']['credit'],account_data['data']['balance']))
    46     flag_exit = False
    47     while not flag_exit:
    48         withdraw_amount = input('请输入提现的金额或按按B返回:').strip()
    49         if len(withdraw_amount) > 0 and withdraw_amount.isdigit():
    50             withdraw_amount = int(withdraw_amount)
    51             if (account_data['data']['balance'] / 2) >= withdraw_amount:
    52                 transaction_result = make_transfer(trans_logger,account_data,'withdraw',withdraw_amount)
    53                 if transaction_result['status'] == 0:
    54                     print('成功提现%s元,余额还有%s'%(withdraw_amount,account_data['data']['balance']))
    55                 else:
    56                     print(transaction_result)
    57             else:
    58                 print('余额不足,可提取%s元'%int(account_data['data']['balance']/2))
    59         if withdraw_amount == 'b'.lower():
    60             flag_exit = True
    61 @auth
    62 def pay_back(account_data,*args,**kwargs):
    63     '还款'
    64     trans_logger = kwargs.get('transaction_logger')
    65     print('账户余额'.center(50, '*'))
    66     print('credit:%s
    '
    67           'blance:%s' % (account_data['data']['credit'], account_data['data']['balance']))
    68     flag_exit = False
    69     while not flag_exit:
    70         payback_amount = input('请输入还款的金额按B返回:').strip()
    71         if len(payback_amount) > 0 and payback_amount.isdigit():
    72             payback_amount = int(payback_amount)
    73             transaction_result = make_transfer(trans_logger, account_data, 'repay', payback_amount)
    74             if transaction_result['status'] == 0:
    75                 print('成功还款%s元,当前余额还有%s' % (payback_amount, account_data['data']['balance']))
    76             else:
    77                 print(transaction_result)
    78         else:
    79             print('输入错误,请重新输入!')
    80         if payback_amount == 'b'.lower():
    81             flag_exit = True
    View Code

    make.py ---  交易中心

     1 from config import setting
     2 from .db_handler import save_db
     3 from .db_handler import load_account
     4 
     5 
     6 def make_transfer(logger,user_obj,trans_type,amount,**kwargs):
     7     '交易中心,进行账户间的加减'
     8     amount = float(amount)
     9     if trans_type in setting.TRANSACTION_TYPE:
    10         interest = amount * setting.TRANSACTION_TYPE[trans_type]['interest']
    11         old_balance = user_obj['data']['balance']
    12         if setting.TRANSACTION_TYPE[trans_type]['action'] == 'transfer':
    13             re_account = load_account(kwargs.get('receiving_account'))
    14             re_account_data = re_account['data']['balance']
    15             re_account_data_balance = amount + re_account_data + interest
    16             new_balance = old_balance - amount - interest
    17             re_account['data']['balance'] = re_account_data_balance
    18             user_obj['data']['balance'] = new_balance
    19             save_db(re_account['data'])
    20             save_db(user_obj['data'])
    21         elif setting.TRANSACTION_TYPE[trans_type]['action'] == 'plus':
    22             new_balance = amount + old_balance + interest
    23         elif setting.TRANSACTION_TYPE[trans_type]['action'] == 'minus':
    24             new_balance = old_balance - amount - interest
    25             if new_balance < 0:
    26                 print('对不起,您的信用额度%s对当前的交易是不够的-%s,你当前的信用额度是%s元'%(user_obj['credit'],(amount+interest)
    27                                                             ,old_balance))
    28                 return {'status':-1,'error':'交易失败,余额不足'}
    29         user_obj['data']['balance'] = new_balance
    30         save_db(user_obj['data'])
    31 
    32         logger.info('account:%s action:%s amount:%s interest:%s balance:%s'%
    33                     (user_obj['data']['id'],trans_type,amount,interest,new_balance))
    34         return {'status':0,'msg':'交易成功'}
    35     else:
    36         print('对不起,%s交易类型不支持'%trans_type)
    37         return {'status':1,'error':'交易失败,不支持的类型%s'%trans_type}
    View Code

    loggers.py --- 日志

     1 from config import setting
     2 import logging
     3 import os
     4 from logging import handlers
     5 def logger_log(log_type):
     6     log = logging.getLogger(log_type)
     7     log.setLevel(setting.LOG_LEVE)
     8 
     9     file_log = os.path.join(setting.LOG_PATH,setting.LOG_TYPE[log_type])
    10     fh = handlers.TimedRotatingFileHandler(file_log,when='D',interval=3,encoding='utf-8')
    11     log.addHandler(fh)
    12 
    13     file = setting.LOG_FORMATTER
    14     fh.setFormatter(file)
    15     return log
    View Code

     shopping.py --- 购物商城

     1 from  .make import make_transfer
     2 from .db_handler import save_db
     3 from .loggers import logger_log
     4 from.auth import auth
     5 
     6 
     7 shopping_logger = logger_log('shopping')
     8 def shoppings(account_data,*args,**kwargs):
     9     trans_logger = kwargs.get('transaction_logger')
    10     exit_flag = False
    11     goods = [
    12         ["电脑",1999],
    13         ["鼠标",10],
    14         ["游艇", 20],
    15         ["美女",  998],
    16     ]
    17 
    18     shopping_list = {}
    19     while not exit_flag:
    20         print('-----------商品列表-------')
    21         for i, v in enumerate(goods):
    22             print(i, v)
    23 
    24         choice = input('请输入商品的编号|q退出|y结账:').strip()
    25 
    26         if choice.isdigit():
    27             choice = int(choice)
    28             if choice >= 0 and choice < len(goods):
    29                 product = goods[choice]
    30 
    31                 if product[0] in shopping_list:
    32                     shopping_list[product[0]][1] += 1
    33                 else:
    34                     shopping_list[ product[0] ] =[ product[1],1]
    35                     print('%s已成功加入购物车'%product[0])
    36 
    37         elif choice == 'y'.lower():
    38             print('购物车'.center(50,'*'))
    39             id_cat = 1
    40             total = 0
    41             print('id	商品	数量	单价	总价')
    42             for key in shopping_list:
    43                 print('%s	%s	%s	%s	%s'%(id_cat,
    44                       key,
    45                       shopping_list[key][1],
    46                       shopping_list[key][0],
    47                       shopping_list[key][1]*shopping_list[key][0]))
    48                 id_cat += 1
    49                 total += shopping_list[key][1]*shopping_list[key][0]
    50                 buckles_money(account_data, total)
    51         elif choice == 'q'.lower():
    52             break
    53 @auth
    54 def buckles_money(account_data,total,*args,**kwargs):
    55     settle_acount = input('是否买单|y是|q退出:').strip()
    56     if settle_acount == 'y':
    57         shopping_data = float(total)
    58         print('账户余额'.center(50, '*'))
    59         print('credit:%s
    '
    60               'blance:%s' % (account_data['data']['credit'], account_data['data']['balance']))
    61         old_balance = account_data['data']['balance']
    62         if shopping_data <= old_balance:
    63             new_balance = old_balance - shopping_data
    64             print('已购买成功,您总共花了%s元,现在余额是%s元'%(shopping_data,new_balance))
    65             exit()
    66         else:
    67             print('余额不足,您现在的余额是%s元'%new_balance)
    68         account_data['data']['balance'] = new_balance
    69         save_db(account_data['data'])
    70         shopping_logger.info('account:%s consume:%s  balance:%s' %
    71                          (account_data['data']['id'], shopping_data, new_balance))
    72     elif settle_acount == 'q':
    73             exit()
    View Code

    setting.py ---- 配置文件

     1 import  os,sys
     2 import logging
     3 
     4 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
     5 
     6 BASE_DB = "%sdb\accounts"%BASE_DIR
     7 
     8 
     9 LOG_LEVE = logging.INFO
    10 
    11 LOG_TYPE = {
    12     'access':'access.log',
    13     'transaction':'transaction.log',
    14     'shopping':'shopping.log',
    15     'admin':'admin.log'
    16 }
    17 
    18 LOG_FORMATTER =logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    19 LOG_PATH = os.path.join(BASE_DIR,'log')
    20 
    21 TRANSACTION_TYPE = {
    22     'repay':{'action':'plus', 'interest':0},
    23     'withdraw':{'action':'minus', 'interest':0.05},
    24     'transfer':{'action':'transfer', 'interest':0.05},
    25 }
    View Code

    admin.py -- 后台管理

      1 from config import setting
      2 import os
      3 import json
      4 from .db_handler import save_db
      5 from .loggers import logger_log
      6 
      7 admin_logger = logger_log('admin')
      8 
      9 def add_account(account):
     10     '增加账户'
     11     dic = {
     12         'id':None,
     13         'password':None,
     14         "credit":None,
     15         "balance": None,
     16         "enroll_date":None,
     17         "expire_date": None,
     18         "pay_day": None,
     19         "status": 0
     20     }
     21     account_file = os.path.join(setting.BASE_DB, '%s.json' %account)
     22     print(account_file)
     23     if os.path.isfile(account_file):
     24         print('账户已存在!')
     25     else:
     26         add_id = input('id:').strip()
     27         if add_id.isdigit():
     28             add_id = int(add_id)
     29         add_passwd = input('passwd:').strip()
     30         add_credit = input('credit:').strip()
     31         if add_credit.isdigit():
     32             add_credit = int(add_credit)
     33         balance = input('balance:').strip()
     34         if balance.isdigit():
     35             balance = int(balance)
     36         enroll_date = input('enroll_date:').strip()
     37         expire_date = input('expire_date:').strip()
     38         pay_day = input('pay_day:').strip()
     39         if pay_day.isdigit():
     40             pay_day = int(pay_day)
     41         dic['id'] = add_id
     42         dic['password'] = add_passwd
     43         dic['credit'] = add_credit
     44         dic['balance'] = balance
     45         dic['enroll_date'] = enroll_date
     46         dic['expire_date'] = expire_date
     47         dic['pay_day'] = pay_day
     48         f = open(os.path.join(setting.BASE_DB,'%s.json'%dic['id']),'w')
     49         json.dump(dic,f)
     50         f.close()
     51         print('账户已添加成功!')
     52         admin_logger.info('账户:%s已成功添加,信用额为%s元'%(dic['id'],dic['credit']))
     53 
     54 
     55 def modify_line(account):
     56     '修改信用额度'
     57     account_file = os.listdir(setting.BASE_DB)
     58     modify_file = input('请输入要修改的账号:').strip()
     59     modify_file = '%s.json'%modify_file
     60     for i,v in enumerate(account_file):
     61         if modify_file == v:
     62             f = open(os.path.join(setting.BASE_DB,v),'r')
     63             data = json.load(f)
     64             f.close()
     65             print('当前额度%s元'%data['credit'])
     66             modifyline = input('请输入修改的额度:').strip()
     67             if modifyline.isdigit():
     68                 modifyline = int(modifyline)
     69             data['credit'] = modifyline
     70             save_db(data)
     71             print('已成功修改%s额度,目前信用额度为%s元'%(modify_file,data['credit']))
     72             admin_logger.info('已成功修改账户:%s额度,目前信用额度为%s元'%(modify_file,data['credit']))
     73 
     74 def unfreeze_account(account):
     75     '账户解锁'
     76     unfreeze_file = os.listdir(setting.BASE_DB)
     77     unfreeze = input('请输入要修改的账号:').strip()
     78     unfreeze = '%s.json'%unfreeze
     79     for i,v in enumerate(unfreeze_file):
     80         if unfreeze == v:
     81             f = open(os.path.join(setting.BASE_DB,v),'r')
     82             data = json.load(f)
     83             f.close()
     84             unfreeze_acc = input('是否解冻账号:').strip()
     85             if unfreeze_acc == 'y'.lower():
     86                 data['status'] = 0
     87                 print('账户:%s已解冻'%unfreeze)
     88             else:
     89                 print('输入错误!')
     90             save_db(data)
     91             admin_logger.info('账户:%s已解冻'%unfreeze)
     92 admin_msg = [
     93     ('账户添加',add_account),
     94     ('修改额度',modify_line),
     95     ('解冻账户',unfreeze_account)
     96 ]
     97 def admin_load(account,*args,**kwargs):
     98     admin_id = account['data']['id']
     99     if admin_id == 8888:
    100         for i, v in enumerate(admin_msg):
    101             print(i, v[0])
    102         choice = input('请选择|q退出:').strip()
    103         if choice.isdigit():
    104             choice = int(choice)
    105             if choice < len(admin_msg) and choice >= 0:
    106                 admin_msg[choice][1](account)
    107         elif choice == 'q'.lower():
    108               exit()
    109     else:
    110         print('不是管理员!')
    111         exit()
    View Code

    账户文件

     1 import json
     2 acc_dic = {
     3     'id': 1234,
     4     'password': 'abc',
     5     'credit': 15000,
     6     'balance': 15000,
     7     'enroll_date': '2016-01-02',
     8     'expire_date': '2021-01-01',
     9     'pay_day': 22,
    10     'status': 0 # 0 = normal, 1 = locked, 2 = disabled
    11 }
    12 
    13 print(json.dumps(acc_dic))
    View Code
  • 相关阅读:
    javascript创建类的6种方式
    c#匿名类型
    flex中在basewidget中不能使用图表组件问题
    Xamarin 后台持续定位与提示
    Net 并行知识学习
    占位
    axis 入门【原】
    Oracle存储过程procedure in、out、in out 模式参数【不发布,纯转】
    poi读取写入excel【未完,待续】
    poi读取写入word【未完,待续】
  • 原文地址:https://www.cnblogs.com/yjiu1990/p/9096566.html
Copyright © 2020-2023  润新知