【python练习】ATM&购物商城程序

程序功能

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

1、额度 15000或自定义
2、实现购物商城,买东西加入 购物车,调用信用卡接口结账
3、可以提现,手续费5%
4、支持多账户登录
5、支持账户间转账
6、记录每月日常消费流水
7、提供还款接口
8、ATM记录操作日志
9、提供管理接口,包括添加账户、用户额度,冻结账户等

程序结构:

atm/
├── README
├── atm #ATM主程目录
│   ├── init.py
│   ├── bin #ATM 执行文件 目录
│   │   ├── init.py
│   │   ├── atm.py  #ATM 执行程序
│   │   └── manage.py #ATM 管理端
│   ├── conf #配置文件
│   │   ├── init.py
│   │   └── settings.py
│   ├── core #主要程序逻辑都
│   │   ├── init.py
│   │   ├── db_handler.py   #数据的存储和加载
│   │   ├── logger.py       #日志记录模块
│   │   ├── login.py   #登陆模块
│   │   ├── main.py         #主逻辑交互程序
│   │   └── transaction.py  #记账\还钱\取钱等所有的与账户金额相关的操作
│   ├── db #用户数据存储的地方
│   │   ├── init.py
│   │   └── accounts #存各个用户的账户数据 ,一个用户一个文件
│   │       ├── guanyu.json #用户账户示例文件
│   │       ├── liubei.json #用户账户示例文件
│   │       └── zhangfei.json #用户账户示例文件
│   ├── interface #提供为其他应用的接口
│   │   ├── init.py
│   │   └── pay_interface #支付接口
│   └── logs #日志目录
│       ├── init.py
│       ├── access.log #用户访问和操作的相关日志
│       └── transactions.log #所有的交易日志
└── shopping_mall #购物车程序
    ├── data #用户数据存储的地方
    │       ├── guanyu #用户账户示例文件
    │       ├── liubei #用户账户示例文件
    │       └── zhangfei #用户账户示例文件
    └── shopping.py #购物车主程序

测试账号

atm:
    1. 账号:liubei    密码:liubei123
    2. 账号:guanyu    密码:gy123
    3. 账号:zhangfei  密码:zf123
购物商城程序:
    1. 账号:liubei    密码:liubei123

  


 

atm/atm/bin/atm.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys

BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(BASE_PATH)
sys.path.append(BASE_PATH)

from core import main

if __name__ == '__main__':
    main.run()
atm/atm/bin/manage.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys

BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(BASE_PATH)
sys.path.append(BASE_PATH)

from core import main

if __name__ == '__main__':
    main.root()

atm/atm/config/setting.py
import os
import sys
import logging

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

DATABASE = {
    'engine': 'file_storage',
    'name': 'accounts',
    'path': '%s\\db' % BASE_PATH
}

LOG_LEVEL = logging.INFO
LOG_TYPES = {
    'transaction': 'transaction.log',
    'access': 'access.log'
}

TRANSACTION_TYPE = {
    'repay': {'action': 'plus', 'interest': 0},
    'withdraw': {'action': 'minus', 'interest': 0.05},
    'transfer': {'action': 'minus', 'interest': 0.05},
    'consume': {'action': 'minus', 'interest': 0},
}

atm/atm/core/db_handle.py
import json
import os
from conf import settings


def db_save(acc_data):
    path = '%s\\account\\%s.json' % (settings.DATABASE['path'], acc_data['account'])
    with open(path, 'w') as f:
        f.write(json.dumps(acc_data))
    return 1


def db_read(account):
    path = '%s\\account\\%s.json' % (settings.DATABASE['path'], account)
    if os.path.isfile(path):
        with open(path, 'r') as f:
            data = json.loads(f.read())
        return data
    else:
        return 0
atm/atm/core/logger.py
import logging
from conf import settings

def logger(log_type):
    # 创建Logger
    logger = logging.getLogger(log_type)
    logger.setLevel(logging.INFO)
    # 创建handler
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)

    path = '%s\\logs\\%s' % (settings.BASE_PATH,settings.LOG_TYPES[log_type])
    fh = logging.FileHandler(path)
    fh.setLevel(logging.INFO)
    # 定义formatter
    formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s  %(message)s')
    # 绑定formatter
    ch.setFormatter(formatter)
    fh.setFormatter(formatter)
    # 添加handle对象
    # logger.addHandler(ch)
    logger.addHandler(fh)

    return logger
atm/atm/core/login.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import json
from core import logger

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


def authentication(func):
    '''
    用户认证程序
    :return:登陆成功返回True
    '''
    def inner(data):
        acc = ''
        auth_list = []  # 用于存放每次输入的用户名
        user_data = {}
        auth_flag = False

        print('- - - Login - - -')
        while auth_list.count(acc) < 3 and auth_flag == False:  # 当相同的用户名登陆失败3次,跳出循环
            # acc = 'liubei'
            # pwd = 'lb123'

            acc = input('Account:').strip()
            pwd = input('Password:').strip()

            path = '%s\\db\\account\\%s.json' % (BASE_PATH, acc)  # 用户信息存放路径
            if os.path.isfile(path):  # 用户名是否存在
                with open(path) as f:
                    acc_data = json.loads(f.read())  # 读取信息
                if acc_data['lock state']:  # 用户是否被锁定
                    if acc_data['password'] == pwd:
                        print('Login success !')
                        auth_flag = True

                        user_data['account_id'] = acc
                        user_data['is_authenticated'] = auth_flag
                        user_data['account_data'] = acc_data
                        user_data['tem_data'] = data

                        logger.logger('access').info('Login %s' % acc)

                        func(user_data)
                    else:
                        auth_list.append(acc)
                        logger.logger('access').info('Login %s - Password Error' % acc)
                        print('The password is error,you have %s times' % (3 - auth_list.count(acc)))
                else:
                    logger.logger('access').info('Login %s - Lock' % acc)
                    print('Your account has locked.')
                    exit()
            else:
                auth_list.append(acc)
                print('The account is not exist...you have %s times' % (3 - auth_list.count(acc)))

        if auth_list.count(acc) == 3:  # 已存在的用户登陆失败三次,锁定,写入文件
            if os.path.isfile(path):
                with open(path, 'w')as f:
                    acc_data['lock state'] = False
                    f.write(json.dumps(acc_data))
    return inner
atm/atm/core/main.py
# Author:q1.ang

from core import login
from core import transaction
from core import logger
from core import db_handle


transaction_logger = logger.logger('transaction')

user_data = {
    'account_id': None,
    'is_authenticated': False,
    'account_data': None,
    'exit_flag': False
}


def withdraw():
    '''
    提现功能
    :return:
    '''
    while True:
        print('''
    - - - - 提现 - - - -
    信用卡额度:%s
    可用金额: %s
    ''' % (user_data['account_data']['limit'], user_data['account_data']['balance']))

        money = input("    \033[0;32m输入提现金额(手续费%5)('q'退出):\033[0m").strip()
        if money == 'q':
            break
        else:
            money = - int(money) * 1.05
        tem = transaction.transaction(user_data['account_data'], money, 'withdraw')
        if tem == 1:  # 提现成功
            print('    \033[0;35m... 提现成功,手续费(%s):%s \033[0m'%('%5',abs(money)/1.05*0.05))
            transaction_logger.info(
                'Account %s - Withdraw %s - Balance %s' % (
                    user_data['account_data']['account'], abs(money),
                    user_data['account_data']['balance']))
        elif tem == 0:  # 提现失败
            print('    \033[0;31m余额不足 ... 提现失败 ...\033[0m')
            transaction_logger.info(
                'Account %s - Withdraw %s - Balance %s - Fail(balance not enough)' % (
                    user_data['account_data']['account'], abs(money),
                    user_data['account_data']['balance']))
        else:
            print('    \033[0;31m遇到了一些错误 ... 提现失败,请重试 ...\033[0m')
            transaction_logger.error(
                'Account %s - Withdraw %s - Balance %s - Fail' % (
                    user_data['account_data']['account'], abs(money),
                    user_data['account_data']['balance']))


def repayment():
    '''
    还款功能
    :return:
    '''
    while True:
        print('''
    - - - - 还款 - - - -
    信用卡额度:%s
    可用金额: %s
        ''' % (user_data['account_data']['limit'], user_data['account_data']['balance']))

        money = input("    \033[0;32m输入还款金额('q'退出):\033[0m").strip()
        if money == 'q':
            break
        else:
            money = int(money)

        tem = transaction.transaction(user_data['account_data'], money, 'repayment')
        if tem == 1:
            print('    \033[0;35m... 还款成功 \033[0m')
            transaction_logger.info(
                'Account %s - Repayment %s - Balance %s' % (
                    user_data['account_data']['account'], money,
                    user_data['account_data']['balance']))
        elif tem == 0:
            print('    \033[0;31m... 还款成功 ... 超出还款额度,退还:%s \033[0m' % (money - user_data['account_data']['repayment_money']))
            transaction_logger.info(
                'Account %s - Repayment %s - Return %s - Balance %s' % (
                    user_data['account_data']['account'], money,
                    money - user_data['account_data']['repayment_money'],
                    user_data['account_data']['balance']))
        else:
            print('    \033[0;31m遇到了一些错误 ... 还款失败,请重试 ...\033[0m')
            transaction_logger.error(
                'Account %s - Withdraw %s - Balance %s - Fail' % (
                    user_data['account_data']['account'], money,
                    user_data['account_data']['balance']))


def transfer():
    while True:
        print('''
    - - - - 转账 - - - -
    信用卡额度:%s
    可用金额: %s
                ''' % (user_data['account_data']['limit'], user_data['account_data']['balance']))

        account1 = input("    \033[0;32m收款人('q'退出):\033[0m").strip()
        if account1 == 'q':
            break
        elif account1 == user_data['account_data']['account']:
            print('    \033[0;31m不能给自己转账,请重输 ...\033[0m')
            break
        # 收款人data
        user_data2 = db_handle.db_read(account1)
        if user_data2 == 0:
            print('    \033[0;31m该用户不存在,请重输 ...\033[0m')
        else:
            money = input("    \033[0;32m转账金额('q'退出):\033[0m").strip()
            if money == 'q':
                break
            else:
                money = int(money)
            # 转账
            if user_data['account_data']['balance'] >= money:
                tem_receive = transaction.transaction(user_data2, money, 'transfer in')  # 收款
                if tem_receive == 1:  # 收款成功,无返还
                    if transaction.transaction(user_data['account_data'], -money, 'transfer out') == 1:  #扣款成功
                        print('    \033[0;35m... 转账成功  \033[0m')

                        transaction_logger.info(
                            'Account %s - Receive Account %s - transfer %s - Balance %s' % (
                                user_data['account_data']['account'], account1, money,
                                user_data['account_data']['balance']))
                        continue
                elif tem_receive == 0:  # 收款成功,有返还
                    if transaction.transaction(user_data['account_data'], -user_data2['repayment_money'], 'transfer out') == 1:  # 扣款成功
                        print('    \033[0;31m... 转账成功 ... 超出还款额度,退还:%s \033[0m' % (
                                    money - user_data2['repayment_money']))

                        transaction_logger.info(
                            'Account %s - Receive Account %s - transfer %s - Balance %s - Return %s' % (
                                user_data['account_data']['account'], account1, money,
                                user_data['account_data']['balance'],money - user_data2['repayment_money']))
                        continue
            else:
                print('    \033[0;31m余额不足 ... 转账失败 ...\033[0m')

                transaction_logger.info(
                    'Account %s - Receive Account %s - Transfer %s - Balance %s - Fail(balance not enough)' % (
                        user_data['account_data']['account'], account1, money,
                        user_data['account_data']['balance']))
                continue

            print('    \033[0;31m遇到了一些错误 ... 转账失败,请重试 ...\033[0m')
            transaction_logger.error(
                'Account %s - Transfer %s - Balance %s - Fail' % (
                    user_data['account_data']['account'], money,
                    user_data['account_data']['balance']))


def balance():
    print('''
    - - - - 余额 - - - -
    信用卡额度:%s
    可用金额: %s
    ''' % (user_data['account_data']['limit'], user_data['account_data']['balance']))
    input('    \033[0;31m任意键退出 ...\033[0m')


def bill():
    print('    - - - - 账单 - - - -\n')

    record_option = input('    \033[0;32mPlease write day of bill[e.g:20180101-20180807]:\033[0m').strip()
    record_start = int(record_option.split('-')[0])
    record_end = int(record_option.split('-')[1])

    for i in user_data['account_data']['record'].keys():
        print('    \033[0;35m- - - - %s - - - -\033[0m' % i)
        for j in user_data['account_data']['record'][i].keys():
            if (record_start <= int(j)) and (int(j) <= record_end):
                print('    \033[0;34m[%s-%s-%s]\033[0m' % (j[0:4],j[4:6], j[6:8]))
                for time,money in user_data['account_data']['record'][i][j].items():
                    print('    ',time,'-',money)
    input('    \033[0;31m任意键退出 ...\033[0m')


@login.authentication
def pay_interface(data):
    '''
    外接支付功能
    :return:
    '''
    global user_data
    user_data = data

    print('''
    - - - - 支付 - - - -
    信用卡额度:%s
    可用金额: %s
    ''' % (user_data['account_data']['limit'], user_data['account_data']['balance']))
    money = - user_data['tem_data']['price']
    tem = transaction.transaction(user_data['account_data'], money, 'consumption',user_data['tem_data'])
    if tem == 1:
        print('    \033[0;35m... 支付成功\033[0m')
        transaction_logger.info(
            'Account %s - Pay %s - Goods %s - Balance %s' % (
                user_data['account_data']['account'], abs(money),
                user_data['tem_data']['name'],
                user_data['account_data']['balance']))
    elif tem == 0:
        print('    \033[0;31m余额不足 ... 支付失败 ...\033[0m')
        transaction_logger.info(
            'Account %s - Pay %s -  Goods %s - Balance %s - Fail(balance not enough)' % (
                user_data['account_data']['account'], abs(money),
                user_data['tem_data']['name'],
                user_data['account_data']['balance']))
    else:
        print('    \033[0;31m遇到了一些错误 ... 提现失败,请重试 ...\033[0m')
        transaction_logger.error(
            'Account %s - Pay %s - Balance %s - Fail' % (
                user_data['account_data']['account'], abs(money),
                user_data['account_data']['balance']))
    input('    \033[0;31m任意键退出 ...\033[0m\n')


@login.authentication
def interactive(data):
    global user_data
    user_data = data

    menu = '''
    - - - - welcome - - - -
    1.提现
    2.还款
    3.转账
    4.查询余额
    5.查询账单
    - - - - - - - - - - - -
    '''

    menu_dic = {
        '1': withdraw,
        '2': repayment,
        '3': transfer,
        '4': balance,
        '5': bill
    }

    while True:
        print(menu)
        option = input('>>>').strip()

        if option in menu_dic:
            menu_dic[option]()
        elif option == 'q':
            exit()
        else:
            print('Without this option[%s]' % option)


def root():
    '''
    管理接口
    :return:
    '''
    def add_acc():
        acc_data = {
            'lock state': True,
            'record':{
                'withdraw': {},
                'repayment': {},
                'transfer out': {},
                'transfer in': {},
                'consumption': {}
            }
        }
        acc = input("    \033[0;32m账户名:\033[0m").strip()
        pwd = input("    \033[0;32m密码:\033[0m").strip()
        limit = input("    \033[0;32m额度:\033[0m").strip()

        acc_data['account'] = acc
        acc_data['password'] = pwd
        acc_data['limit'] = int(limit)
        acc_data['balance'] = int(limit)

        if db_handle.db_save(acc_data) == 1:
            print('    \033[0;35m... 账户创建成功\033[0m')
            transaction_logger.info('CreateAccount %s - Limit %s ' % (acc_data['account'], acc_data['limit']))
        else:
            print('    \033[0;31m遇到了一些错误 ... 创建失败,请重试 ...\033[0m')
            transaction_logger.error('CreateAccount %s - Limit %s - Fail ! ' % (acc_data['account'], acc_data['limit']))

    def change_limit():
        acc = input("    \033[0;32m账户名:\033[0m").strip()
        acc_data = db_handle.db_read(acc)
        if acc_data != 0:
            limit = input("    \033[0;32m额度:\033[0m").strip()
            acc_data['limit'] = int(limit)
            if db_handle.db_save(acc_data) == 1:
                print('    \033[0;35m... 额度更改成功\033[0m')
                transaction_logger.info('Change limit %s - Account %s ' % (limit, acc))
            else:
                print('    \033[0;31m遇到了一些错误 ... 额度更改失败,请重试 ...\033[0m')
                transaction_logger.error('Change limit %s - Account %s - Fail ! ' % (limit, acc))
        else:
            print('    \033[0;31m用户不存在,请重试 ...\033[0m')

    def lock():
        acc = input("    \033[0;32m账户名:\033[0m").strip()
        acc_data = db_handle.db_read(acc)
        if acc_data != 0:
            acc_data['lock state'] = False
            if db_handle.db_save(acc_data) == 1:
                print('    \033[0;35m... 冻结成功\033[0m')
                transaction_logger.info('Lock Account %s' % acc)
            else:
                print('    \033[0;31m遇到了一些错误 ... 冻结失败,请重试 ...\033[0m')
                transaction_logger.error('Lock Account %s - Fail ! ' % acc)
        else:
            print('    \033[0;31m用户不存在,请重试 ...\033[0m')

    menu = '''
    - - - - welcome - - - -
    1. 添加账户
    2. 更改用户额度
    3. 冻结账户
    - - - - - - - - - - - -
    '''

    menu_dic = {
        '1': add_acc,
        '2': change_limit,
        '3': lock,
    }

    while True:
        print(menu)
        option = input('>>>').strip()

        if option in menu_dic:
            menu_dic[option]()
        elif option == 'q':
            exit()
        else:
            print('Without this option[%s]' % option)


def run():
    interactive(user_data)
atm/atm/core/transaction.py
# Author:q1.ang

import os
import sys
import time
from core import db_handle

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


def transaction(*args):
    acc_data = args[0]
    money = args[1]
    trans_type = args[2]
    if money <= 0:
        if abs(money) <= acc_data['balance']:
            acc_data['balance'] += money
            if trans_type == 'consumption':
                pay_data = args[3]
                record(acc_data, trans_type, pay_data)
            else:
                record(acc_data,trans_type,abs(money))
            return db_handle.db_save(acc_data)
        else:
            return 0
    elif money >= 0:
        if acc_data['balance'] + money <= acc_data['limit']:
            acc_data['balance'] += money
            record(acc_data, trans_type, money)
            if db_handle.db_save(acc_data) == 1:
                return 1
        else:
            acc_data['repayment_money'] = acc_data['limit'] - acc_data['balance']
            acc_data['balance'] = acc_data['limit']
            record(acc_data, trans_type, acc_data['repayment_money'])
            if db_handle.db_save(acc_data) == 1:
                return 0
    return 3


def record(acc_data, trans_type, money):
    localday = time.strftime('%Y%m%d', time.localtime())
    localtime = time.strftime('%H:%M:%S', time.localtime())
    if localday in acc_data['record'][trans_type]:
        acc_data['record'][trans_type][localday][localtime] = money
    else:
        acc_data['record'][trans_type][localday] = {localtime: money}

atm/atm/db/account/guanyu.json
{"lock state": true, "account": "guanyu", "password": "gy123", "limit": 20000, "balance": 20000, "record": {"withdraw": {"20180807": {"00:00:00": 100, "18:00:15": 123, "18:01:24": 321, "18:05:51": 1, "20:01:08": 1234, "20:04:03": 123, "20:17:42": 100, "20:56:57": 5000, "21:00:57": 5000, "21:07:00": 5000}}, "repayment": {"20180101": {"00:00:00": 1}, "20180807": {"20:38:54": 0, "20:40:27": 0, "20:42:09": 0, "20:43:38": 0, "20:57:06": 0, "21:01:13": 1, "21:02:23": 1, "21:02:38": 4997, "21:06:51": 1, "21:07:08": 10000, "21:40:17": 500, "21:43:38": 500, "21:46:08": 500, "21:59:17": 500}}, "transfer out": {}, "transfer in": {"20180807": {"22:37:54": 123, "22:39:25": 5000, "22:43:40": 1, "22:48:36": 1, "22:49:40": 200, "22:50:41": 3000, "22:52:27": 699, "22:58:38": 0}, "20180808": {"17:06:31": 0}}, "consumption": {"20180101": {"00:00:00": {"name": "\u7535\u8111", "price": 1999}, "23:01:02": {"name": "\u9f20\u6807", "price": 10}}, "20180202": {"00:02:00": {"name": "\u7f8e\u5973", "price": 998}}, "20180724": {"22:11:13": {"name": "\u7535\u8111", "price": 1999}, "22:11:14": {"name": "\u9f20\u6807", "price": 10}, "22:38:21": {"name": "\u7535\u8111", "price": 1999}, "22:40:32": {"name": "\u7535\u8111", "price": 1999}, "22:41:31": {"name": "\u7535\u8111", "price": 1999}, "22:41:35": {"name": "\u9f20\u6807", "price": 10}, "22:42:41": {"name": "\u7535\u8111", "price": 1999}, "22:42:43": {"name": "\u9f20\u6807", "price": 10}, "22:46:16": {"name": "\u9f20\u6807", "price": 10}, "22:56:56": {"name": "\u9f20\u6807", "price": 10}, "23:13:32": {"name": "\u7535\u8111", "price": 1999}}}}, "repayment_money": 0}
atm/atm/db/account/liubei.json
{"lock state": true, "account": "liubei", "password": "lb123", "limit": 15000, "balance": 823.1000000000003, "record": {"withdraw": {"20180807": {"00:00:00": 100, "18:00:15": 123, "18:01:24": 321, "18:05:51": 1, "20:01:08": 1234, "20:04:03": 123, "20:17:42": 100, "20:56:57": 5000, "21:00:57": 5000, "21:07:00": 5000, "22:48:56": 100, "23:18:59": 210.0, "23:22:23": 210.0, "23:22:45": 210.0, "23:23:59": 210.0}, "20180808": {"17:05:34": 105.0, "19:50:45": 1377.6000000000001, "20:20:33": 1.05, "21:36:22": 1.05, "22:45:15": 1.05, "22:56:45": 2.1, "22:57:17": 1.05}}, "repayment": {"20180101": {"00:00:00": 1}, "20180807": {"20:38:54": 0, "20:40:27": 0, "20:42:09": 0, "20:43:38": 0, "20:57:06": 0, "21:01:13": 1, "21:02:23": 1, "21:02:38": 4997, "21:06:51": 1, "21:07:08": 10000, "21:36:09": 500, "21:37:24": 500, "21:38:38": 500, "21:40:17": 500, "21:43:38": 500, "21:46:08": 500, "21:47:09": 1, "21:59:02": 1, "21:59:17": 500, "23:01:55": 1301}, "20180808": {"17:06:10": 100, "17:06:15": 845.0, "22:57:32": 1}}, "transfer out": {"20180807": {"22:37:54": 123, "22:39:25": 0, "22:43:40": 4999, "22:48:36": 1, "22:49:40": 200, "22:50:41": 1000, "22:52:27": 0, "22:58:38": 0}, "20180808": {"17:06:31": 0, "23:02:45": 1}}, "transfer in": {}, "consumption": {"20180808": {"20:24:50": {"name": "\u9f20\u6807", "price": 10}, "20:24:51": {"name": "\u9f20\u6807", "price": 10}, "20:24:52": {"name": "\u9f20\u6807", "price": 10}, "20:24:53": {"name": "\u9f20\u6807", "price": 10}, "20:26:25": {"name": "\u9f20\u6807", "price": 10}, "20:26:26": {"name": "\u9f20\u6807", "price": 10}, "20:26:27": {"name": "\u9f20\u6807", "price": 10}, "20:26:28": {"name": "\u9f20\u6807", "price": 10}, "20:26:29": {"name": "\u9f20\u6807", "price": 10}, "20:29:45": {"name": "\u6e38\u8247", "price": 20}, "20:30:17": {"name": "\u6e38\u8247", "price": 20}, "20:30:24": {"name": "\u6e38\u8247", "price": 20}, "20:30:26": {"name": "\u6e38\u8247", "price": 20}, "20:33:58": {"name": "\u7f8e\u5973", "price": 998}, "20:35:02": {"name": "\u7f8e\u5973", "price": 998}, "20:35:49": {"name": "\u9f20\u6807", "price": 10}, "20:35:51": {"name": "\u9f20\u6807", "price": 10}, "20:37:29": {"name": "\u9f20\u6807", "price": 10}, "20:37:39": {"name": "\u9f20\u6807", "price": 10}, "20:37:53": {"name": "\u9f20\u6807", "price": 10}, "20:37:54": {"name": "\u9f20\u6807", "price": 10}, "20:37:59": {"name": "\u9f20\u6807", "price": 10}, "20:45:08": {"name": "\u9f20\u6807", "price": 10}, "20:45:10": {"name": "\u9f20\u6807", "price": 10}, "20:49:09": {"name": "\u9f20\u6807", "price": 10}, "20:49:10": {"name": "\u9f20\u6807", "price": 10}, "20:49:13": {"name": "\u9f20\u6807", "price": 10}, "20:49:19": {"name": "\u9f20\u6807", "price": 10}, "20:49:38": {"name": "\u9f20\u6807", "price": 10}, "20:49:40": {"name": "\u9f20\u6807", "price": 10}, "20:49:41": {"name": "\u9f20\u6807", "price": 10}, "20:49:42": {"name": "\u9f20\u6807", "price": 10}, "20:49:43": {"name": "\u9f20\u6807", "price": 10}, "20:56:34": {"name": "\u9f20\u6807", "price": 10}, "20:56:36": {"name": "\u9f20\u6807", "price": 10}, "20:58:59": {"name": "\u9f20\u6807", "price": 10}, "20:59:21": {"name": "\u9f20\u6807", "price": 10}, "21:22:02": {"name": "\u9f20\u6807", "price": 10}, "21:23:25": {"name": "\u6e38\u8247", "price": 20}, "21:23:54": {"name": "\u9f20\u6807", "price": 10}, "21:26:59": {"name": "\u7f8e\u5973", "price": 998}, "21:29:53": {"name": "\u9f20\u6807", "price": 10}, "21:34:57": {"name": "\u9f20\u6807", "price": 10}, "21:37:50": {"name": "\u7535\u8111", "price": 1999}, "21:43:46": {"name": "\u6e38\u8247", "price": 20}, "21:44:40": {"name": "\u9f20\u6807", "price": 10}, "21:51:24": {"name": "\u9f20\u6807", "price": 10}, "21:54:54": {"name": "\u9f20\u6807", "price": 10}, "23:04:18": {"name": "\u9f20\u6807", "price": 10}, "23:39:52": {"name": "\u9f20\u6807", "price": 10}}}}, "repayment_money": 845.0}

atm/atm/interface/pay_interface.py
import os
import sys

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

from core import main


def run(data):
    main.pay_interface(data)

atm/atm/logs/...


shopping/shopping.py
{"lock state": true, "account": "liubei", "password": "lb123", "balance": 973, "record": {"20180101": {"00:00:00": {"name": "\u7535\u8111", "price": 1999}, "23:01:02": {"name": "\u9f20\u6807", "price": 10}}, "20180202": {"00:02:00": {"name": "\u7f8e\u5973", "price": 998}}, "20180724": {"22:11:13": {"name": "\u7535\u8111", "price": 1999}, "22:11:14": {"name": "\u9f20\u6807", "price": 10}, "22:38:21": {"name": "\u7535\u8111", "price": 1999}, "22:40:32": {"name": "\u7535\u8111", "price": 1999}, "22:41:31": {"name": "\u7535\u8111", "price": 1999}, "22:41:35": {"name": "\u9f20\u6807", "price": 10}, "22:42:41": {"name": "\u7535\u8111", "price": 1999}, "22:42:43": {"name": "\u9f20\u6807", "price": 10}, "22:46:16": {"name": "\u9f20\u6807", "price": 10}, "22:56:56": {"name": "\u9f20\u6807", "price": 10}, "23:13:32": {"name": "\u7535\u8111", "price": 1999}}, "20180808": {"20:28:50": {"name": "\u9f20\u6807", "price": 10}, "21:53:58": {"name": "\u9f20\u6807", "price": 10}, "21:54:57": {"name": "\u9f20\u6807", "price": 10}, "23:04:07": {"name": "\u7f8e\u5973", "price": 998}, "23:04:20": {"name": "\u9f20\u6807", "price": 10}, "23:39:55": {"name": "\u9f20\u6807", "price": 10}}}}

shopping/data/liubei.json
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
测试账号(用户名:liubei,密码:lb123)
'''

import os
import sys
import time
import json

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

from atm.interface import pay_interface
# from atm.core import main



goods = [
    {'name': '电脑', 'price': 1999},
    {'name': '鼠标', 'price': 10},
    {'name': '游艇', 'price': 20},
    {'name': '美女', 'price': 998}
]


class Shopping(object):
    def __init__(self):
        self.acc_data = {}  # 用户信息

    def authentication(self):
        '''
        用户认证程序
        :return:登陆成功返回True
        '''
        acc = ''
        auth_list = []  # 用于存放每次输入的用户名

        print('- - - Login - - -')
        while auth_list.count(acc) < 3:  # 当相同的用户名登陆失败3次,跳出循环
            acc = input('Account:').strip()
            pwd = input('Password:').strip()

            path = 'data\\%s' % acc  # 用户信息存放路径
            if os.path.isfile(path):  # 用户名是否存在
                with open(path) as f:
                    self.acc_data = json.loads(f.read())    #读取信息
                    if self.acc_data['lock state']:  #用户是否被锁定
                        if self.acc_data['password'] == pwd:
                            print('Login success !')
                            return True
                        else:
                            auth_list.append(acc)
                            print('The password is error,you have %s times' % (3 - auth_list.count(acc)))
                    else:
                        print('You have tried 3 times,your account has locked.')
                        exit()
            else:
                auth_list.append(acc)
                print('The account is not exist...you have %s times' % (3 - auth_list.count(acc)))

        if auth_list.count(acc) == 3:  # 已存在的用户登陆失败三次,锁定,写入文件
            if os.path.isfile(path):
                with open(path, 'w')as f:
                    self.acc_data['lock state'] = False
                    f.write(json.dumps(self.acc_data))

    def shopping(self):
        '''
        购物窗口
        :return:
        '''
        buy_dic = []
        while True:
            print('List of goods'.center(30,'-'))
            for index,item in enumerate(goods,1):
                print('%s . \033[0;33m%s\033[0m   \033[0;32m%s\033[0m'%(index,item['name'],item['price']))
            buy = input('("q" to exit)\nchoose one to buy:').strip()
            if buy.isnumeric() and 0 < int(buy) <= len(goods): #输入是数字且在商品序号范围内
                print('''
                - - - choose how to pay - - -
                1. Shopping VIP Card
                2. Credit Card''')
                pay_way = input('>>>').strip()
                if pay_way == '1':  # 选择使用超市vip付款
                    if self.acc_data['balance'] >= int(goods[int(buy) - 1]['price']):
                        self.acc_data['balance'] -= int(goods[int(buy) - 1]['price'])    # 扣除余额
                    else:
                        print('\033[0;33mYour balance can not afford anyone..\033[0m')
                elif pay_way == '2':
                    pay_interface.run(goods[int(buy) - 1])  # 调用atm

                # 更新购物清单
                buy_dic.append(goods[int(buy) - 1])  # 购物记录
                localday = time.strftime('%Y%m%d', time.localtime())
                localtime = time.strftime('%H:%M:%S', time.localtime())
                if localday in self.acc_data['record']:
                    self.acc_data['record'][localday][localtime] = goods[int(buy) - 1]
                else:
                    self.acc_data['record'][localday] = {localtime: goods[int(buy) - 1]}
                # 写入文件
                if self.db_handle():
                    print('You have buy:\033[0;32m%s\033[0m' % goods[int(buy) - 1]['name'])
                else:
                    print('\033[0;31mSystem error...you have not buy %s\033[0m' % goods[int(buy) - 1]['name'])

            elif buy == 'q':
                if len(buy_dic) != 0:
                    print('\033[1;31;46mShopping receipts\033[0m')
                    for index,item in enumerate(buy_dic,1):
                        print('%s . \033[0;33m%s\033[0m   \033[0;32m%s\033[0m' % (index, item['name'], item['price']))
                break
            else:
                print('\033[0;31minput error...\033[0m')

    def recharge(self):
        '''
        充值
        :return:
        '''
        recharge = input('You want to recharge:').strip()
        if recharge.isnumeric() and int(recharge) < 0:
            print('\033[0;31mPlease input a number greater than zero\033[0m')
        elif recharge.isnumeric():
            self.acc_data['balance'] += int(recharge)
            if self.db_handle():
                print('\033[0;31mRecharge success !\033[0m')
            else:
                print('\033[0;31mRecharge error...\033[0m')
        else:
            print('\033[0;31minput error...\033[0m')

    def record(self):
        '''
        查询历史清单
        :return:
        '''
        for date in self.acc_data['record']:
            print('\033[0;34m%s\033[0m'%date.center(20, '-'))
            for time in self.acc_data['record'][date]:
                print(time, ':', self.acc_data['record'][date][time]['name'],
                      self.acc_data['record'][date][time]['price'])

    def exit(self):
        '''
        退出函数
        :return:
        '''
        print('exit...')
        exit()

    def db_handle(self):
        '''
        文件写入
        :return:
        '''
        with open('data\\'+self.acc_data['account'],'w') as f:
            f.write(json.dumps(self.acc_data))
            return True

    def interaction(self):
        '''
        交互
        :return:
        '''
        print(' Mall '.center(30, '*'))
        if self.authentication():    #登陆认证成功
            exit_flag = False
            while not exit_flag:
                print('''\nVip name:{account}\nBalance:\033[1;31;46m{balance}\033[0m\n\n1.  购物\n2.  充值\n3.  清单\n4.  退出
                '''.format(account=self.acc_data['account'], balance=self.acc_data['balance']))

                menu_dic = { #对应类方法的字典
                    '1': self.shopping,
                    '2': self.recharge,
                    '3': self.record,
                    '4': self.exit
                }
                user_option = input('>>>').strip()
                if user_option in menu_dic:
                    menu_dic[user_option]()
                else:
                    print('Without this option(%s)' % user_option)

if __name__ == '__main__':
    s = Shopping()    #实例化
    s.interaction()

 

posted @ 2018-05-06 23:35  q1ang  阅读(464)  评论(1编辑  收藏  举报