前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python-ATM加购物车

python-ATM加购物车

作者头像
py3study
发布2020-01-19 16:25:47
1K0
发布2020-01-19 16:25:47
举报
文章被收录于专栏:python3
代码语言:javascript
复制
模拟实现一个ATM + 购物商城程序
    1.额度 15000或自定义                                        
    4.支持多账户登录                                            
    5.支持账户间转账                                           
    9.提供管理接口,包括添加账户、用户额度,冻结账户等。。。          
    10.用户认证用装饰器                                          
    3.可以提现,手续费5%                                        
    2.实现购物商城,买东西加入 购物车,调用信用卡接口结账            
    6.记录每月日常消费流水                                       
    7.提供还款接口                                              
    8.ATM记录操作日志                                           
    包含随时返回:b   和随时退出:q

ps:使用面向过程的思想去实现
代码语言:javascript
复制
画的贼烂,框架如上图
代码语言:javascript
复制
ATM+购物车
    |-------conf 配置加接口
    |        |------interface.py  接口配置
    |        |------settings.py   路径加日志配置
    |
    |-------core 核心  用户与超管
    |        |------admin.py  超管功能
    |        |------atm.py    ATM功能
    |        |------shopping.py  购物功能
    |
    |-------db  数据库
    |        |------userdb  用户文件 json格式
    |        |------dbhandler.py  数据层操作
    |
    |-------lib  公共库
    |        |------common.py  用户认证加日志功能
    |
    |-------log 日志文件夹
    |        |------operation.log  操作日志
    |        |------trading.log    交易日志
    |-------start.py  程序启动文件
代码语言:javascript
复制
#coding:utf-8
from db import dbhandler
from lib import common

logger1=common.get_logger("操作日志")

logger2=common.get_logger('交易日志')

def add_user(name,pwd='123',lines=15000):
    '''添加账户接口'''
    user_dict={'name':name,'password':pwd,'lines':lines,'balance':lines,'buy':[],'lock':False}
    state,msg=dbhandler.query(name)
    if state:
        return False,'用户已存在'
    else:
        dbhandler.save(user_dict)
        logger1.info('%s用户创建成功' % name)
        return True, '%s用户创建成功,密码为%s' % (name,pwd)

def trans_interface(my_name,trans_name,money):
    '''转账接口'''
    state_my,msg_my=dbhandler.query(my_name)
    state_tra,msg_tra=dbhandler.query(trans_name)
    if state_tra:
        if int(money) < int(msg_my['balance']):
            msg_my['balance']=int(msg_my['balance'])-int(money)
            msg_tra['balance']=int(msg_tra['balance'])+int(money)
            dbhandler.save(msg_my)
            dbhandler.save(msg_tra)
            logger2.info('%s转账给%s%s元成功'%(my_name,trans_name,money))
            return True,'%s转账给%s%s元成功'%(my_name,trans_name,money)
        else:
            return False,'转账失败,余额不足'
    else:
        return False,'转账用户不存在'

def withdrawal_interface(name,money):
    '''提现接口'''
    state,msg=dbhandler.query(name)
    poundage=int(money)*5/100
    if msg['balance'] < (int(money)+poundage):
        return False,'提现失败,余额不足'
    else:
        msg['balance']=msg['balance'] - int(money) - poundage
        dbhandler.save(msg)
        logger2.info('%s提现%s元成功,手续费为%s元'%(name,money,poundage))
        return True,'%s提现%s元成功,手续费为%s元'%(name,money,poundage)

def repay_interface(name,money):
    '''还款接口'''
    state,msg=dbhandler.query(name)
    if state:
        msg['balance']=msg['balance']+int(money)
        dbhandler.save(msg)
        logger2.info('%s还款%s元成功,余额为%s'%(name,money,msg['balance']))
        return True,'%s还款%s元成功,余额为%s'%(name,money,msg['balance'])

def check_balance(name):
    '''查看余额接口'''
    state,user_dict=dbhandler.query(name)
    res=user_dict['balance']
    return res

def shopping_interface(name,cost,shopping_dict):
    '''购物支付接口'''
    state,user_dict=dbhandler.query(name)
    if user_dict['balance'] > cost:
        user_dict['balance']-=cost
        user_dict['buy'].append(shopping_dict)
        dbhandler.save(user_dict)
        logger2.info('%s购买成功,消费了%s元'%(name,cost))
        return True,'购买成功,消费了%s元'%cost
    else:
        return False,'余额不足,购买失败'

def check_shop_car(name):
    '''查看购物记录即可'''
    state,user_dict=dbhandler.query(name)
    res=user_dict['buy']
    return res

interface.py

代码语言:javascript
复制
# coding:utf-8
# ============================路径配置加日志配置项(日志配置模板)=========================================
import os

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

USER_DB = os.path.join(BASE_DIR, 'db', 'userdb')

standard_format = '[%(asctime)s][task_id:%(name)s]' \
                  '[%(levelname)s]< %(message)s >'  # 其中name为getlogger指定的名字

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

id_simple_format = '[%(asctime)s][%(levelname)s] %(message)s'

# log文件的路径
OPE_LOG_PATH = os.path.join(BASE_DIR, 'log', 'operation.log')  # 操作日志路径
TRA_LOG_PATH = os.path.join(BASE_DIR, 'log', 'trading.log')  # 交易日志路径

# log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': id_simple_format
        },
    },
    'filters': {},
    'handlers': {
        # 打印到终端的日志,使用的格式为 simple_format
        'ch': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日志,使用的格式为 standard_format
        'default1': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': OPE_LOG_PATH,  # 日志文件
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
        'default2': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': TRA_LOG_PATH,  # 日志文件
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    'loggers': {
        '操作日志': {
            'handlers': ['ch', 'default1'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': False,
        },
        '交易日志': {
            'handlers': ['ch', 'default2'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': False,
        },
    },
}
代码语言:javascript
复制
# coding:utf-8
from conf import interface
from db import dbhandler
from lib import common

tag = True


def adduser():
    '''添加用户'''
    while True:
        name = input('请输入账户名:').strip()
        if not name: continue
        name1 = input('请确认账户名:').strip()
        if name != name1:
            print('两次输入不一致!')
            continue
        state, msg = interface.add_user(name1)
        if state:
            print(msg)
            break
        else:
            print(msg)


def set_lines():
    '''设置额度'''
    while True:
        name = input('请输入账户名:').strip()
        if not name: continue
        name1 = input('请确认账户名:').strip()
        if name != name1:
            print('两次输入不一致!')
            continue
        lines = input('请输入信用额度:').strip()
        if lines.isdigit():
            state, msg = interface.dbhandler.query(name1)
            if state:
                msg['lines'] = lines
                dbhandler.save(msg)
                interface.logger1.info('%s设置%s成功,信用额度为%s!!' % ('admin', name1, lines))
                print('%s设置%s成功,信用额度为%s!!' % ('admin', name1, lines))
            else:
                print(msg)
        else:
            print('额度请输入数字')
            break


def freeze():
    '''冻结功能'''
    name = input('请输入冻结账户名:').strip()
    name1 = input('请确认冻结账户名:').strip()
    if name != name1:
        print('两次输入不一致!')
        return
    state, msg = dbhandler.query(name1)
    if state:
        msg['lock'] = True
        dbhandler.save(msg)
        interface.logger1.info('%s冻结%s成功' % ('admin', name1))
        print('%s冻结%s成功' % (common.user_state['name'], name1))
    else:
        print(msg)


def unfreeze():
    '''解冻功能'''
    name = input('请输入冻结账户名:').strip()
    name1 = input('请确认冻结账户名:').strip()
    if name != name1:
        print('两次输入不一致!')
        return
    state, msg = dbhandler.query(name1)
    if state:
        msg['lock'] = False
        dbhandler.save(msg)
        interface.logger1.info('%s解冻%s成功' % ('admin', name1))
        print('%s解冻%s成功' % ('admin', name1))
    else:
        print(msg)


def check_log():
    '''查看操作日志功能'''
    dbhandler.query_log('admin')


def menu():
    view = '''
        1.添加账户
        2.设置用户额度
        3.冻结账户
        4.解冻账户
        5.查看操作日志
        q.退出
    '''
    print(view)


@common.login_auth(auth='admin')
def main():
    view_dict = {
        '1': adduser,
        '2': set_lines,
        '3': freeze,
        '4': unfreeze,
        '5': check_log
    }
    global tag
    while tag:
        print('管理员'.center(60, '-'))
        menu()
        choice = input('请选择:').strip()
        if choice == 'q':
            tag = False
            break
        if not choice or choice not in view_dict: continue
        view_dict[choice]()

admin.py

代码语言:javascript
复制
# coding:utf-8
from core import admin
from conf import interface
from db import dbhandler
from lib import common


def registered():
    '''注册功能'''
    if common.user_state['name']:
        print('已登录,无法注册')
        return
    while True:
        print('注册'.center(40, '-'))
        name = input('请输入账户名:').strip()
        if not name: continue
        pwd1 = input('请输入密码:').strip()
        if not pwd1: continue
        pwd2 = input('请确认密码:').strip()
        if pwd1 != pwd2:
            print('两次输入密码不一致!')
            break
        if len(pwd2) < 3:
            print('密码强度太低')
            continue
        state, msg = interface.add_user(name, pwd2)
        if state:
            print(msg)
            break
        else:
            print(msg)


def check_balance():
    '''查看余额'''
    balance = interface.check_balance(common.user_state['name'])
    print('%s当前余额为%s元!!!' % (common.user_state['name'], balance))


def transfer():
    '''转账'''
    while True:
        print('转账'.center(40, '-'))
        name = input('请输入要转账的账户名:').strip()
        name1 = input('请确认账户名:').strip()
        if name != name1:
            print('账户名不一致')
            continue
        money = input('请输入转账金额:'.strip())
        if money.isdigit():
            state, msg = interface.trans_interface(common.user_state['name'], name1, money)
            if state:
                print(msg)
                break
            else:
                print(msg)
                break
        else:
            print('金额请输入数字!')
            continue


def repay():
    '''还款'''
    state, msg = dbhandler.query(common.user_state['name'])
    arrears = msg['lines'] - msg['balance']
    print('您的欠款为%s元!!!' % (arrears))
    repay_wage = input('请输入您要还款的金额: ').strip()
    if not repay_wage.isdigit():
        print('请输入数字!')
        return
    else:
        state, msg = interface.repay_interface(common.user_state['name'], repay_wage)
        print(msg)


def withdrawal():
    '''提现'''
    while True:
        print('提现'.center(40, '-'))
        money = input('请输入要提现的金额:').strip()
        if not money.isdigit(): continue
        message = input('提现将要收取%5手续费,是否继续(y/n):').strip()
        if message not in ['y', 'n']: continue
        if message == 'y':
            state, msg = interface.withdrawal_interface(common.user_state['name'], money)
            if state:
                print(msg)
                break
            else:
                print(msg)
        else:
            break


def check_log():
    '''查看操作日志'''
    dbhandler.query_log(common.user_state['name'])


def view():
    view_dict = '''
        1.查询余额
        2.转账
        3.还款
        4.提现
        5.查询日志
        b.返回上一层
        q.退出
    '''
    print(view_dict)


@common.login_auth(auth='user')
def main():
    view_dict = {
        '1': check_balance,
        '2': transfer,
        '3': repay,
        '4': withdrawal,
        '5': check_log
    }
    while admin.tag:
        print('ATM操作界面'.center(60, '-'))
        view()
        choice = input('请选择:').strip()
        if choice == 'q':
            admin.tag = False
            break
        if choice == 'b': break
        if choice not in view_dict: continue
        view_dict[choice]()

atm.py

代码语言:javascript
复制
# coding:utf-8
from lib import common
from core import admin
from conf import interface

shopping_dict = {}  # 购物车

def product():
    '''购物功能'''
    product_list = [
        ['华为P20', 5488],
        ['笔记本', 5599],
        ['Nike运动鞋', 669],
        ['十三香小龙虾', 165],
        ['山地车', 399],
        ['天梭表', 3699],
        ['某宝t恤', 69],
        ['三只松鼠', 59],
        ['重庆小面', 18],
    ]
    cost = 0  # 初始总花费为0
    user_balance = interface.check_balance(common.user_state['name'])  # 调接口查询余额
    global shopping_dict
    while admin.tag:
        print('商品列表'.center(50, '-'))
        for k, v in enumerate(product_list):  # 将商品列表 加上索引打印出来
            print(k, '', v)
        print('q : 退出/购买 ')
        choice = input('\n请选择购买商品:').strip()
        if choice.isdigit():  # 判断输入是否为数字
            choice = int(choice)
            if choice >= len(product_list): continue  # 输入的数字大于索引则重新开始
            product_name = product_list[choice][0]  # 拿到商品名
            product_price = product_list[choice][1]  # 拿到商品价格
            if user_balance >= product_price:  # 判断余额是否大于商品价格
                if product_name in shopping_dict:  # 判断商品是否已在购物车里
                    shopping_dict[product_name]['数量'] += 1  # 有则购物车的对应商品数量加1
                else:
                    shopping_dict[product_name] = {'价格': product_price, '数量': 1}  # 购物车添加新字典
                user_balance -= product_price  # 余额减去商品价格
                cost += product_price  # 花费加上商品价格
                print('%s加入购物车成功' % [product_name, product_price])
            else:
                print('余额不足')
        elif choice == 'q':
            if cost == 0: break
            for k, v in shopping_dict.items():
                print(k, '', v)
            buy = input('是否确认购买(y/n),需支付%s元:' % cost).strip()
            if buy == 'y':  # 确认支付时调支付接口
                state, msg = interface.shopping_interface(common.user_state['name'], cost, shopping_dict)
                if state:
                    print(msg)
                    break
                else:
                    print(msg)
                    break
            else:
                print('无任何商品购买')
                shopping_dict = {}
                break
        else:
            print('输入错误')
            continue


def shop_car():
    '''查看购物车功能'''
    for k, v in shopping_dict.items():
        print(k, '', v)


def check_shop():
    '''查看消费记录功能'''
    shop_dic = interface.check_shop_car(common.user_state['name'])
    for i in shop_dic:
        print(i)


def view():
    view_dict = '''
        1.商品列表
        2.购物车
        3.查看消费记录
        b.返回上一层
        q.退出
    '''
    print(view_dict)


@common.login_auth(auth='user')
def main():
    view_dict = {
        '1': product,
        '2': shop_car,
        '3': check_shop,
    }
    while admin.tag:
        print('购物界面'.center(60, '-'))
        view()
        choice = input('请选择:').strip()
        if choice == 'q':
            admin.tag = False
            break
        if choice == 'b': break
        if choice not in view_dict: continue
        view_dict[choice]()

shopping.py

代码语言:javascript
复制
#coding:utf-8
import json,os
from conf import settings

def save(user_dic):
    '''数据写入'''
    name=user_dic['name']
    with open(settings.USER_DB+r'\%s.json'%name,'wt') as f:
        json.dump(user_dic,f)
        f.flush()


def query(name):
    '''查询用户信息'''
    db_path=settings.USER_DB+r'\%s.json'%name
    if os.path.isfile(db_path):
        with open(db_path,'rt') as f:
            res=json.load(f)
        return True,res
    else:
        return False, '用户不存在'


def query_log(name):
    '''查询日志功能'''
    with open(settings.OPE_LOG_PATH,'rt',encoding='utf-8') as f:
        for names in f.readlines():
            if name in names:
                print(names)
    with open(settings.TRA_LOG_PATH,'rt',encoding='utf-8') as f1:
        for names in f1.readlines():
            if name in names:
                print(names)

dbhandler.py

代码语言:javascript
复制
#:coding:utf-8
user_state = {'name': None}
from conf import settings
import logging.config
from db import dbhandler


def login_user():
    '''认证'''
    count = 0
    while True:
        name = input('请输入用户名:').strip()
        pwd = input('请输入密码:').strip()
        state, msg = dbhandler.query(name)
        if count == 3:
            print('您已被锁定')
            msg['lock'] = True
            dbhandler.save(msg)
            break
        if state:  # 查询状态
            if pwd == msg['password'] and not msg['lock']:
                user_state['name'] = name
                print('%s登录成功' % name)
                break
            elif msg['lock'] == True:
                print('您已被锁定')
                break
            else:
                count += 1
                print('密码错误%s次' % count)
        else:
            print(msg)
            break


def login_admin():
    '''管理员认证'''
    admin_dict = {'name': 'admin', 'password': '123', 'lock': False}
    name = input('请输入管理员账户:').strip()
    pwd = input('请输入密码:').strip()
    if name != admin_dict['name'] or pwd != admin_dict['password']:
        print('账号或密码错误')
    else:
        print('登录成功')
        user_state['name'] = name


def login_auth(auth='module'):
    def outter(func):
        '''装饰器'''

        def warppers(*args, **kwargs):
            if auth == 'user':
                if user_state['name'] == None:
                    login_user()
                if user_state['name']:
                    func(*args, **kwargs)
            if auth == 'admin':
                if user_state['name'] == None:
                    login_admin()
                if user_state['name'] == 'admin':
                    func(*args, **kwargs)
                else:
                    print('没有管理员权限!')
                    return

        return warppers

    return outter


def get_logger(name):
    '''日志模块'''
    logging.config.dictConfig(settings.LOGGING_DIC)
    logger = logging.getLogger(name)
    return logger

common.py

代码语言:javascript
复制
# coding:utf-8
# ================================start.py=======================================
import sys, os

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

from core import atm, shopping, admin


def menu():
    view = '''
        1.注册
        2.ATM     
        3.购物     
        4.管理员   
        q.退出
    '''
    print(view)


if __name__ == '__main__':
    view_dict = {
        '1': atm.registered,
        '2': atm.main,
        '3': shopping.main,
        '4': admin.main
    }
    while admin.tag:
        print('总界面'.center(60, '-'))
        menu()
        choice = input('请选择:').strip()
        if choice == 'q': break
        if not choice or choice not in view_dict: continue
        view_dict[choice]()

花了点时间将之前的面向过程编程作业重写了次,完成后感觉还是写的不够好。时间原因就先这样。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/03/07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档