• 🐍ATM功能实现项目


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

    1、额度 15000或自定义
    2、实现购物商城,买东西加入 购物车,调用信用卡接口结账
    3、可以提现,手续费5%
    4、支持多账户登录
    5、支持账户间转账
    6、记录每月日常消费流水
    7、提供还款接口
    8、ATM记录操作日志
    9、提供管理接口,包括添加账户、用户额度,冻结账户等。。。
    10、用户认证用装饰器
    示例代码 https://github.com/triaquae/py3_training/tree/master/atm

    简易流程图:https://www.processon.com/view/link/589eb841e4b0999184934329

     二、首先画一个流程图让思路更清晰:

    三、目录结构图:

    四、启动文件

     start.py源代码:

    1 import os, sys
    2 
    3 path = os.path.dirname(__file__)
    4 sys.path.append(path)
    5 from core import src
    6 
    7 if __name__ == '__main__':
    8     src.run()

    五、配置文件相关

    setting.py源代码:

     1 import os
     2 
     3 BASE_PATH = os.path.dirname(os.path.dirname(__file__))  # ATM的路径
     4 BASE_DB = os.path.join(BASE_PATH, 'db')  # db 文件的路径
     5 BASE_LOG = os.path.join(BASE_PATH, 'log')  # 日志路径
     6 
     7 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
     8                   '[%(levelname)s][%(message)s]'  # 其中name为getlogger指定的名字
     9 
    10 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
    11 
    12 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
    13 
    14 # 定义日志输出格式 结束
    15 
    16 # 如果不存在定义的日志目录就创建一个
    17 if not os.path.isdir(BASE_LOG):
    18     os.mkdir(BASE_LOG)
    19 
    20 # log文件的全路径
    21 logfile_path = os.path.join(BASE_LOG, 'log.log')
    22 
    23 # log配置字典
    24 LOGGING_DIC = {
    25     'version': 1,
    26     'disable_existing_loggers': False,
    27     'formatters': {
    28         'standard': {
    29             'format': standard_format
    30         },
    31         'simple': {
    32             'format': simple_format
    33         },
    34     },
    35     'filters': {},
    36     'handlers': {
    37         # 打印到终端的日志
    38         'console': {
    39             'level': 'DEBUG',
    40             'class': 'logging.StreamHandler',  # 打印到屏幕
    41             'formatter': 'simple'
    42         },
    43         # 打印到文件的日志,收集info及以上的日志
    44         'default': {
    45             'level': 'DEBUG',
    46             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
    47             'formatter': 'standard',
    48             'filename': logfile_path,  # 日志文件
    49             'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
    50             'backupCount': 5,
    51             'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
    52         },
    53 
    54     },
    55     'loggers': {
    56         # logging.getLogger(__name__)拿到的logger配置
    57         '': {
    58             'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
    59             'level': 'INFO',
    60             'propagate': True,  # 向上(更高level的logger)传递
    61         },
    62     },
    63 }

    六、核心逻辑

    src.py源代码:

      1 from interface import user, bank, shopping
      2 from lib import common
      3 
      4 user_data = {
      5     'name': None
      6     # 判断用户是否登入
      7 }
      8 
      9 
     10 def logout():
     11     '''
     12     退出.
     13     :return:
     14     '''
     15     user_data['name'] = None
     16 
     17 
     18 def login():
     19     '''
     20     登入.
     21     :return:
     22     '''
     23     print('登录。。。')
     24     if user_data['name']:
     25         print('你已经登入过了')
     26     count = 0
     27     while True:
     28         name = input('请输入用户名>>:').strip()
     29         if name.lower() == 'q': break
     30         password = input('请输入密码>>:').strip()
     31         flag, msg = user.login_interface(name, password)
     32         if flag:
     33             user_data['name'] = name
     34             print(msg)
     35             break
     36         else:
     37             count += 1
     38             if count == 3:
     39                 user.locked_interface(name)
     40                 print('错误次数过多,已锁定')
     41             else:
     42 
     43                 print(msg)
     44 
     45 
     46 def register():
     47     '''
     48     注册.
     49     :return:
     50     '''
     51     print('注册。。。')
     52     if user_data['name']:
     53         print('你已经登入过了')
     54     while True:
     55         name = input('请输入用户名>>:').strip()
     56         if name.lower() == 'q': break
     57         password = input('请输入密码>>:').strip()
     58         password2 = input('再次输入密码>>:').strip()
     59         if password == password2:
     60             flag, msg = user.register_interface(name, password)
     61             if flag:
     62                 print(msg)
     63                 break
     64             else:
     65                 print('用户已存在')
     66         else:
     67             print('两次密码不一致')
     68 
     69 
     70 @common.login_auth
     71 def check_balance():
     72     '''
     73     查看余额.
     74     :return:
     75     '''
     76     print('查看余额。。。')
     77     balance = bank.check_balance_interface(user_data['name'])
     78     print(balance)
     79 
     80 
     81 @common.login_auth
     82 def transfer():
     83     '''
     84     转账.
     85     :return:
     86     '''
     87     print('转账。。。')
     88     while True:
     89         to_name = input('输入转账的用户>>:').strip()
     90         balance = input('输入转账金额>>:').strip()
     91         if balance.isdigit():
     92             balance = int(balance)
     93             flag, msg = bank.transfer_interface(user_data['name'], to_name, balance)
     94             if flag:
     95                 print(msg)
     96                 break
     97             else:
     98                 print(msg)
     99         else:
    100             print('必须输入数字')
    101 
    102 
    103 @common.login_auth
    104 def repay():
    105     '''
    106     还款.
    107     :return:
    108     '''
    109     print('还款。。。')
    110     balance = input('请输入还款金额>>:').strip()
    111     if balance.isdigit():
    112         balance = int(balance)
    113         falg, msg = bank.repay_interface(user_data['name'], balance)
    114         if falg:
    115             print(msg)
    116         else:
    117             print(msg)
    118     else:
    119         print('必须输入数字')
    120 
    121 
    122 @common.login_auth
    123 def withdraw():
    124     '''
    125     取款.
    126     :return:
    127     '''
    128     print('取款。。。')
    129     balance = input('输入取款金额>>:').strip()
    130     if balance.isdigit():
    131         balance = int(balance)
    132         falg, msg = bank.withdraw_interface(user_data['name'], balance)
    133         if falg:
    134             print(msg)
    135         else:
    136             print(msg)
    137     else:
    138         print('必须输入数字')
    139 
    140 
    141 @common.login_auth
    142 def check_record():
    143     '''
    144     查看流水.
    145     :return:
    146     '''
    147     print('查看流水。。。')
    148     bankflow = bank.check_bankflow_interface(user_data['name'])
    149     for flow in bankflow:
    150         print(flow)
    151 
    152 
    153 @common.login_auth
    154 def shop():
    155     '''
    156     1 先循环打印出商品
    157     2 用户输入数字选择商品(判断是否是数字,判断输入的数字是否在范围内)
    158     3 取出商品名,商品价格
    159     4 判断用户余额是否大于商品价格
    160     5 余额大于商品价格时,判断此商品是否在购物车里
    161         5.1 在购物车里,个数加1
    162         5.1 不在购物车里,拼出字典放入({‘good’:{‘price’:10,‘count’:1}})
    163     6 用户余额减掉商品价格
    164     7 花费加上商品价格
    165     8 当输入 q时,购买商品
    166         8.1 消费为0 ,直接退出
    167         8.2 打印购物车
    168         8.3 接受用户输入,是否购买 当输入y,直接调购物接口实现购物
    169     :return:
    170     '''
    171     print('购物。。。')
    172     goods_list = [
    173         ['coffee', 10],
    174         ['chicken', 20],
    175         ['iphone', 8000],
    176         ['macPro', 15000],
    177         ['car', 100000]
    178     ]
    179     money = 0
    180     user_balance = bank.check_balance_interface(user_data['name'])
    181     shopping_cart = {}
    182     while True:
    183         for i, v in enumerate(goods_list):
    184             print(f'{i}: {v}')
    185         choice = input('请输入需要购买商品的编号(数字)(q退出)>>:').strip()
    186         if choice.isdigit():
    187             choice = int(choice)
    188             if choice >= len(goods_list):
    189                 print('商品不存在')
    190                 continue
    191             shop_name = goods_list[choice][0]
    192             shop_price = goods_list[choice][1]
    193             if user_balance >= shop_price:
    194                 if shop_name in shopping_cart:
    195                     shopping_cart[shop_name]['count'] += 1
    196                 else:
    197                     shopping_cart[shop_name] = {'price': shop_price, 'count': 1}
    198                 user_balance -= shop_price
    199                 money += shop_price
    200                 print(f'{shop_name}已加入购物车')
    201             else:
    202                 print('余额不足')
    203                 continue
    204         elif choice.lower() == 'q':
    205             if money == 0:
    206                 break
    207             print(shopping_cart)
    208             user = input('是否购买Y/N>>:').strip()
    209             if user.lower() == 'y':
    210                 falg, msg = shopping.shopping_interface(user_data['name'], money, shopping_cart)
    211                 if falg:
    212                     print(msg)
    213                     break
    214                 else:
    215                     print(msg)
    216                     break
    217             elif user.lower() == 'n':
    218                 print('你什么都没有购买')
    219                 break
    220             else:
    221                 print('无选项')
    222                 continue
    223 
    224         else:
    225             print('输入非法字符')
    226 
    227 
    228 @common.login_auth
    229 def check_shopping_cart():
    230     '''
    231     查看购物车.
    232     :return:
    233     '''
    234     print('查看购物车。。。')
    235     shoppingcart = shopping.check_shoppingcart(user_data['name'])
    236     if shoppingcart:
    237         print(shoppingcart)
    238     else:
    239         print('无商品')
    240 
    241 
    242 func_dic = {
    243     '1': login,
    244     '2': register,
    245     '3': check_balance,
    246     '4': transfer,
    247     '5': repay,
    248     '6': withdraw,
    249     '7': check_record,
    250     '8': shop,
    251     '9': check_shopping_cart,
    252     '10': logout
    253 }
    254 
    255 
    256 def run():
    257     '''
    258     功能选择接口.
    259     :return:
    260     '''
    261     while True:
    262         print('''选择需要的功能:
    263 1、登入
    264 2、注册
    265 3、查看余额
    266 4、转账
    267 5、还款
    268 6、取款
    269 7、查看流水
    270 8、购物
    271 9、查看购买商品
    272 10、退出程序
    273 ''')
    274         choice = input('编号>>:').strip()
    275         if choice in func_dic:
    276             func_dic[choice]()

    七、用户数据

    db_handler.py源代码:

     1 import os
     2 import json
     3 from conf import setting
     4 
     5 
     6 def save(user_dic):
     7     '''
     8     保存用户信息文件.
     9     :param user_dic: 用户信息
    10     :return:
    11     '''
    12     user_path = os.path.join(setting.BASE_DB, '%s.json' % user_dic['name'])
    13     with open(user_path, 'w', encoding='utf-8')as f:
    14         json.dump(user_dic, f)
    15         f.flush()
    16 
    17 
    18 #
    19 def select(name):
    20     """
    21    查询用户文件.
    22     :param name: str --> 用户名
    23     :return: None, user_dic
    24     """
    25     user_path = os.path.join(setting.BASE_DB, '%s.json' % name)
    26     if os.path.exists(user_path):
    27         with open(user_path, 'r', encoding='utf-8')as f:
    28             user_dic = json.load(f)
    29             return user_dic
    30     else:
    31         return None

    八、银行接口

    bank.py源代码:

      1 from db import db_handler
      2 from core import src
      3 from lib import common
      4 
      5 bank_logger = common.get_logger('bank')
      6 
      7 
      8 def check_balance_interface(name):
      9     '''
     10     查询余额接口.
     11     :param name:账户名
     12     :return:balance
     13     '''
     14     user_dic = db_handler.select(name)
     15     balance = user_dic['balance']
     16     return balance
     17 
     18 
     19 def transfer_interface(from_name, to_name, balance):
     20     '''
     21     转账接口.
     22     :param from_name:转账用户
     23     :param to_name: 收款用户
     24     :param balance: 转账金额
     25     :return:True,False
     26     '''
     27     if from_name == to_name:
     28         return False, '不能给自己转账'
     29     to_dic = db_handler.select(to_name)
     30     if to_dic:
     31         from_dic = db_handler.select(from_name)
     32         if from_dic['balance'] >= balance:
     33             to_dic['balance'] += balance
     34             from_dic['balance'] -= balance
     35             from_dic['bankflow'].append('你向%s转账%s元' % (to_name, balance))
     36             to_dic['bankflow'].append('你收到%s的转账%s元' % (from_name, balance))
     37             bank_logger.info('%s向%s转账%s元' % (from_name, to_name, balance))
     38             db_handler.save(from_dic)
     39             db_handler.save(to_dic)
     40             return True, '转账成功'
     41         else:
     42             return False, '余额不足'
     43     else:
     44         return False, '用户不存在'
     45 
     46 
     47 def repay_interface(name, balance):
     48     '''
     49     还款接口.
     50     :param name: 还款用户
     51     :param balance: 还款金额
     52     :return:True,False
     53     '''
     54     user_dic = db_handler.select(name)
     55     if user_dic['balance'] >= balance:
     56         user_dic['balance'] -= balance
     57         user_dic['bankflow'].append('还款%s' % balance)
     58         bank_logger.info('%s还款了%s元' % (name, balance))
     59         db_handler.save(user_dic)
     60         return True, '还款成功'
     61     else:
     62         return False, '余额不足以还款'
     63 
     64 
     65 def withdraw_interface(name, balance):
     66     '''
     67     取款接口.
     68     :param name: 取款用户
     69     :param balance: 取款金额
     70     :return:True,False
     71     '''
     72     user_dic = db_handler.select(name)
     73     if user_dic['balance'] >= balance * 1.05:  # 0.5%的手续费
     74         user_dic['balance'] -= balance * 1.05
     75         user_dic['bankflow'].append('取款%s,手续费%s' % (balance, balance * 0.05))
     76         bank_logger.info('你取款了%s元,手续费%s元' % (balance, balance * 0.05))
     77         db_handler.save(user_dic)
     78         return True, '取款成功,取出金额%s' % balance
     79     else:
     80         return False, '余额不足'
     81 
     82 
     83 def consume_interface(name, money):
     84     '''
     85     消费接口.
     86     :param name: 消费用户
     87     :param money: 消费金额
     88     :return:True,False
     89     '''
     90     user_dic = db_handler.select(name)
     91     if user_dic['balance'] >= money:
     92         user_dic['balance'] -= money
     93         db_handler.save(user_dic)
     94         return True, '扣款成功'
     95     else:
     96         return False, '余额不足'
     97 
     98 
     99 def check_bankflow_interface(name):
    100     '''
    101     银行流水.
    102     :param name: 账户名
    103     :return:user_bankflow
    104     '''
    105     user_dic = db_handler.select(name)
    106     user_bankflow = user_dic['bankflow']
    107     return user_bankflow

    九、购物接口

    shopping.p源代码:

     1 from db import db_handler
     2 from interface import bank
     3 
     4 
     5 def shopping_interface(name, money, shoppingcart):
     6     '''
     7     购物接口.
     8     :param name:用户名
     9     :param money: 消费金额
    10     :param shoppingcart: 购物车清单
    11     :return:True,False
    12     '''
    13     flag, msg = bank.consume_interface(name, money)
    14     if flag:
    15         user_dic = db_handler.select(name)
    16         user_dic['shoppingcart'] = shoppingcart
    17         db_handler.save(user_dic)
    18         return True, '购买成功'
    19     else:
    20         return False, '余额不足'
    21 
    22 
    23 def check_shoppingcart(name):
    24     '''
    25     查看购物车接口.
    26     :param name: 用户名
    27     :return:user_dic['shoppingcart']
    28     '''
    29     user_dic = db_handler.select(name)
    30 
    31     return user_dic['shoppingcart']

    十、用户信息接口

    user.py源代码:

     1 from db import db_handler
     2 from lib import common
     3 
     4 user_logger = common.get_logger('user')
     5 
     6 
     7 def login_interface(name, password):
     8     '''
     9     登入接口.
    10     :param name:用户名
    11     :param password: 用户密码
    12     :return:True,False
    13     '''
    14     user_dic = db_handler.select(name)
    15     if user_dic:  # {'name': 'song', 'password': '123'}
    16         if password == user_dic['password'] and not user_dic['locked']:
    17             user_logger.info('用户%s登入了账户' % name)
    18             return True, '登入成功'
    19         else:
    20             return False, '用户名密码错误或被锁定'
    21     else:
    22         return False, '用户不存在'
    23 
    24 
    25 def register_interface(name, password, balance=15000):
    26     '''
    27     注册接口.
    28     :param name:用户名
    29     :param password: 密码
    30     :param balance: 确认密码
    31     :return:True,False
    32     '''
    33     user_dic = db_handler.select(name)
    34     if user_dic:
    35         return False, '用户已存在'
    36     else:
    37         user_dic = {'name': name, 'password': password, 'balance': balance,
    38                     'locked': False, 'bankflow': [], 'shoppingcart': {}}
    39         db_handler.save(user_dic)
    40         user_logger.info('用户%s注册成功' % name)
    41         return True, '注册成功'
    42 
    43 
    44 def locked_interface(name):
    45     '''
    46     锁定接口.
    47     :param name:用户名
    48     :return:
    49     '''
    50     user_dic = db_handler.select(name)
    51     if user_dic:
    52         user_dic['locked'] = True
    53         db_handler.save(user_dic)
    54 
    55 
    56 def un_locked_interface(name):
    57     '''
    58     解锁用户.
    59     :param name:用户名
    60     :return:
    61     '''
    62     user_dic = db_handler.select(name)
    63     if user_dic:
    64         user_dic['locked'] = False
    65         db_handler.save(user_dic)

    十一、模块工具

    common.py源代码:

     1 from core import src
     2 import logging.config
     3 from conf import setting
     4 
     5 
     6 def login_auth(func):
     7     '''
     8     装饰器
     9     :param func: 函数名
    10     :return: wrapper
    11     '''
    12 
    13     def wrapper(*args, **kwargs):
    14         if not src.user_data['name']:
    15             src.login()
    16         else:
    17             return func(*args, **kwargs)
    18 
    19     return wrapper
    20 
    21 
    22 def get_logger(name):
    23     '''
    24     盗用日志字典.
    25     :param name:日志名字
    26     :return:
    27     '''
    28     logging.config.dictConfig(setting.LOGGING_DIC)  # 使用这个日志字典
    29     logger = logging.getLogger('name')
    30     return logger

    十二、功能演示:

    1、注册:

     2、登入:

     3、查看余额:

     4、转账:

     log文件记录的日志:

     5、还款:

     6、取款:

     7、查看流水:

    查看song的流水:

     8、购物:

     

     

     

     9、查看购物车:

     10、退出登入(退出后需要重新登入)

    感谢观看!记得双击么么哒!

     
  • 相关阅读:
    1004 Counting Leaves
    1003 Emergency (25分)
    1002 A+B for Polynomials (25分)
    1001 A+B Format
    Weekly Contest 139
    491. Increasing Subsequences
    488. Zuma Game
    servlet总结
    firefox插件Firebug的使用教程
    KMP---POJ 3461 Oulipo
  • 原文地址:https://www.cnblogs.com/songhaixing/p/11844081.html
Copyright © 2020-2023  润新知