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

先说最重要的地方,怕忘记在把各个模块做完后记得在最外面的文件夹下,鼠标点击右键找到以下图片上的东西点击,不然程序不能运行

 

模拟实现一个ATM + 购物商城程序_第1张图片

day6 #ATM主程目录

   ├── __init__.py

├──  acc_operation #用户选择命令操作

   │   ├── __init__.py

   │   ├── main_interface.py  #主要的操作执行程序        

   ├── atm #ATM 执行文件 目录

   │   ├── __init__.py

   │   ├── atm.py  #ATM 执行程序

   │  

   ├── conf #配置文件

   │   ├── __init__.py

   │   └── settings.py

   ├── core #主要程序逻辑都 在这个目录

   │   ├── __init__.py

   │   ├── account.py  #用于从文件里加载和存储账户数据

   │   ├── auth.py      #用户认证模块

   │   ├── db_handler.py   #数据库连接引擎

   │   ├── logger.py       #日志记录模块

   │   ├── main.py         #主逻辑交互程序

   │   └── transaction.py  #记账\还钱\取钱等所有的与账户金额相关的操作都 在这

   ├── db  #用户数据存储的地方

   │   ├── __init__.py

   │   ├── account_sample.py #生成一个初始的账户数据 ,把这个数据 存成一个 以这个账户id为文件名的文件,放在accounts目录 就行了,程序自己去会这里找

   │   └── accounts #存各个用户的账户数据 ,一个用户一个文件

   │       └── zhou.json #一个用户账户示例文件

   └── log #日志目录

       ├── __init__.py

       ├── access.log #用户访问和操作的相关日志

       └── transactions.log    #所有的交易日志

 

模拟实现一个ATM + 购物商城程序_第2张图片

模拟实现一个ATM + 购物商城程序_第3张图片

acc_operaption购物,转账,存取钱,等操作。

main_interface

from core import account
from core import logger
from core import transaction
from conf import settings

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

trans_logger = logger.logger('transaction')
access_logger = logger.logger('access')


def account_info(acc_data):
    print(acc_data)


def repay(acc_data):
    account_data = account.load_current_balance(acc_data['id'])
    current_balace = '''
    ----------INFO----------
    Credit  : %s
    Balance : %s
    ''' % (account_data['credit'], account_data['balance'])
    print(current_balace)
    back_flag = False

    while not back_flag:
        repay_amount = input("\033[033;1mInput repay amount(b = break):\033[0m").strip()
        if len(repay_amount) > 0 and repay_amount.isdigit():
            print(repay_amount)
            new_balance = transaction.make_transaction(trans_logger, account_data, 'repay', repay_amount)
            if new_balance:
                print('''\033[42;1mNew Balance:%s\033[0m''' % (new_balance['balance']))
        else:
            print('\033[31;1m[%s] is not a valid amount, only accept integer!\033[0m' % repay_amount)
        if repay_amount == 'b':
            back_flag = True


def withdraw(acc_data):

    account_data = account.load_current_balance(acc_data['id'])
    current_balance = ''' --------- BALANCE INFO --------
        Credit :    %s
        Balance:    %s''' % (account_data['credit'], account_data['balance'])
    print(current_balance)
    back_flag = False
    while not back_flag:
        withdraw_amount = input("\033[33;1mInput withdraw amount(b = break):\033[0m").strip()
        if len(withdraw_amount) > 0 and withdraw_amount.isdigit():
            new_balance = transaction.make_transaction(trans_logger, account_data, 'withdraw', withdraw_amount)
            if new_balance:
                print('''\033[42;1mNew Balance:%s\033[0m''' % (new_balance['balance']))
        else:
            print('\033[31;1m[%s] is not a valid amount, only accept integer!\033[0m' % withdraw_amount)

        if withdraw_amount == 'b':
            back_flag = True


def transfer(acc_data):
    '''
    转账
    :param acc_data:
    :return:
    '''

    account_data = account.load_current_balance(acc_data['id'])

    current_balance = '''
    ---------------INFO----------------
    Credit   :%s
    Balance  :%s
    
    ''' % (account_data['credit'], account_data['balance'])
    back_flag = False
    transfer_ccount = input("\033[31;1mInput transfer account").strip()
    transfer_amount_info = account.load_current_balance(transfer_ccount)
    while not back_flag:
        print(current_balance)

        transfer_amount = input("\033[31;1mInput transfer amount (b = break)").strip()
        if len(transfer_amount) > 0 and transfer_amount.isdigit():
            # transfer_account_data = new_account_data
            new_account_data = transaction.make_transaction(trans_logger, account_data, 'transfer', transfer_amount)
            if new_account_data:
                print("\033[42;1mNew Balance:%s\033[0m" % new_account_data['balance'])
                new_account_data2 = transaction.make_transaction(trans_logger, transfer_amount_info, 'repay', transfer_amount)
                if new_account_data2:
                    print("\033[42;1mNew Balance2:%s\033[0m" % new_account_data2["balance"])
        else:
            print("\033[31;1m%s is not valid amount,Only accept interger!\033[0m" % transfer_amount)

        if transfer_amount == "b" or transfer_amount == "back":
            back_flag = True


def paycheck(acc_data):
    time = input('Please input time (Y-M-D) : ').strip()
    log_file = "%s/log%s" % (settings.BASE_DIR, settings.LOG_TYPES['transaction'])
    print(log_file)
    with open(log_file, 'r', encoding='utf-8')as f:
        for count in f.readlines():
            if time == count[0:10]:
                print(count)
            elif time == count[0:7]:
                print(count)
            elif time == count[0:4]:
                print(count)


def logout(acc_data):
    q = input("if you want to quit, please input q")
    if q == 'q':
        exit()


def shopping(acc_data):

    product_list ={
        ('Iphone', 60000),
        ('Watch', 4600),
        ('Books', 200),
        ('Bike', 50),
        ('Banana', 1),
        ('GaoDaModel', 150)
    }
    shopping_list = []
    salary = acc_data['balance']
    while not False:
        for index, item in enumerate(product_list):
            print(index, item)
        user_choice = input('Enter the serial number(b=break)').strip()
        if user_choice.isdigit():
            user_choice = int(user_choice)
            if user_choice = 0:
                p_item = product_list[user_choice]
                if p_item[1] <= salary:
                    shopping_list.append(p_item)
                    salary -= p_item[1]
                    transaction.make_transaction(access_logger, 'consume', acc_data, p_item[1])
                else:
                    print("You balance is not enough")
            else:
                print("The goods you entered do not exit")

        elif user_choice == 'b':
            print("-------shopping list---------")
            for goods in shopping_list:
                print(goods)
            print("Your current balance is %s" % salary)
            exit()

        else:
            print("Invalid option")


def interactive(acc_data):
    menu = u'''
    \033[32;1m
    1. 账户信息
    2. 还款
    3. 取款
    4. 转账
    5. 账单
    6. 进入商城
    7. 退出
    \033[0m
    '''
    menu_dic = {
        '1': account_info,
        '2': repay,
        '3': withdraw,
        '4': transfer,
        '5': paycheck,
        '6': shopping,
        '7': logout,
    }
    exit_flag = False
    while not exit_flag:
        print(menu)
        user_option = input("please elect number:").strip()
        if user_option in menu_dic:
            print('acc_data', acc_data)
            menu_dic[user_option](acc_data)



atm函数入口

import os
import sys

from core import main
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(base_dir)
sys.path.append(base_dir)

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

conf配置模块

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


DATABASE = {
    'engine': 'file_storage', #support mysql,postgresql in the future
    'name': 'accounts',
    'path': "%s/db" % BASE_DIR
}


LOG_LEVEL = logging.INFO
LOG_TYPES = {
    'transaction': 'transactions.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},
}

core各个模块

account

import json
import time
from core import db_handler
from conf import settings


def load_current_balance(account_id):
    db_api = db_handler.db_handler()
    data = db_api("select * from accounts where account=%s" % account_id)
    return data


def dump_account(account_data):
    db_api = db_handler.db_handler()
    data = db_api("update accounts where account=%s" % account_data['id'], account_data=account_data)

    return True


auth

import os
from core import db_handler
from conf import settings
from core import logger
import json
import time

acc_dic = {
    'id': 1234,
    'password': 'abc',
    'credit': 15000,
    'balance': 15000,
    'enroll_date': '2016-01-02',
    'expire_date': '2021-01-01',
    'pay_day': 22,
    'status': 0  # 0 = normal, 1 = locked, 2 = disabled
}


def user_login(name, password, log):
    acc_dic['id'] = name
    acc_dic['password'] = password
    value = settings.DATABASE
    db_path = '%s/%s' % (value['path'], value['name'])
    # print(db_path)
    account_file = '%s/%s.json' % (db_path, name)
    # content = "%s.json" % name
    print(account_file)
    if os.path.isdir(db_path):
        if os.path.isfile(account_file):
            print("\033[31;lm Account is exist!\033[0m")
        else:
            with open(account_file, 'w', encoding='utf-8')as f:
                acc_data = json.dump(acc_dic, f)
                log.info("%s registration is successful " % acc_dic['id'])
                return acc_data
    else:
        os.mkdir(db_path)
        with open(account_file, 'w', encoding='utf-8')as f:
            acc_data = json.dump(acc_dic, f)
            log.info("%s registration is successful " % acc_dic['id'])
            return acc_data


def acc_auth2(account, password):
    '''
    优化版认证接口
    :param account: credit account number
    :param password: credit card password
    :return: if passed the authentication , retun the account object, otherwise ,return None
    '''

    db_api = db_handler.db_handler()
    data = db_api("select * from accounts where account=%s" % account)
    if data['password'] == password:
        exp_time_stamp = time.mktime(time.strptime(data['expire_date'], "%Y-%m-%d"))
        if time.time() > exp_time_stamp:
            print("\033[31;1mAccount [%s] has expired,please contact the back to get a new card!\033[0m" % account)
        else:  # passed the authentication
            return data
    else:
        print("\033[31;1mAccount ID or password is incorrect!\033[0m")


def acc_login(user_data, log_obj):
    retry_count = 0
    while user_data['is_authenticated'] is not True and retry_count < 3:
        account = input("\033[32;1maccount:\033[0m").strip()
        password = input("\033[32;1mpassword:\033[0m").strip()
        auth = acc_auth2(account, password)
        if auth:  # not None means passed the authentication
            user_data['is_authenticated'] = True
            user_data['account_id'] = account
            # user_data['account_data'] = auth
            print("welcome")
            return auth

        retry_count += 1
        print("Wrong username or password")
    else:

        log_obj.error("account [%s] too many login attempts" % account)
        exit()

db_handler

import json
import time
import os
from conf import settings






def file_db_handle(conn_params):
    '''
    parse the db file path
    :param conn_params: the db connection params set in settings
    :return:
    '''
    print('file db:', conn_params)
    return file_execute


def db_handler():
    '''
    connect to db
    :param conn_parms: the db connection params set in settings
    :return:a
    '''
    conn_params = settings.DATABASE
    if conn_params['engine'] == 'file_storage':
        return file_db_handle(conn_params)
    elif conn_params['engine'] == 'mysql':
        pass


def file_execute(sql, **kwargs):
    conn_params = settings.DATABASE
    db_path = '%s/%s' % (conn_params['path'], conn_params['name'])

    sql_list = sql.split("where")
    if sql_list[0].startswith("select") and len(sql_list) > 1:  # has where clause
        column, val = sql_list[1].strip().split("=")

        if column == 'account':
            account_file = "%s/%s.json" % (db_path, val)
            if os.path.isfile(account_file):
                with open(account_file, 'r') as f:
                    account_data = json.load(f)
                    return account_data
            else:
                exit("\033[31;1mAccount [%s] does not exist!\033[0m" % val)

    elif sql_list[0].startswith("update") and len(sql_list) > 1: # has where clause
        column, val = sql_list[1].strip().split("=")
        if column == 'account':
            account_file = "%s/%s.json" % (db_path, val)
            if os.path.isfile(account_file):
                account_data = kwargs.get("account_data")
                with open(account_file, 'w') as f:
                    acc_data = json.dump(account_data, f)

                return True

logger

import logging
from conf import settings

def logger(log_type):

    #create logger
    logger = logging.getLogger(log_type)
    logger.setLevel(settings.LOG_LEVEL)


    # create console handler and set level to debug
    ch = logging.StreamHandler()
    ch.setLevel(settings.LOG_LEVEL)

    # create file handler and set level to warning
    log_file = "%s/log/%s" % (settings.BASE_DIR, settings.LOG_TYPES[log_type])
    print(log_file)

    fh = logging.FileHandler(log_file)
    fh.setLevel(settings.LOG_LEVEL)
    # create formatter
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    # add formatter to ch and fh
    ch.setFormatter(formatter)
    fh.setFormatter(formatter)

    # add ch and fh to logger
    logger.addHandler(ch)
    logger.addHandler(fh)

    return logger
    # 'application' code
    '''logger.debug('debug message')
    logger.info('info message')
    logger.warn('warn message')
    logger.error('error message')
    logger.critical('critical message')'''

main

from core import auth
from core import logger
from acc_operation import main_interface


trans_logger = logger.logger('transaction')
access_logger = logger.logger('access')

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


def account_info(acc_data):
    print(acc_data)


def run():
    while True:
        msg = u'''
--------------INFO--------------
         \033[31;1m1.registered\033[0m
         \033[31;1m2.login\033[0m

        '''
        print(msg)
        user_choose = input("请输入:").strip()
        if user_choose == '1':
            name = input("\033[31;1m请输入姓名\033[0m").strip()
            pwd = input("\033[31;1m请输入密码\033[0m").strip()
            auth.user_login(name, pwd, access_logger)
            print("success")

        elif user_choose == '2':
            acc_data = auth.acc_login(user_data, access_logger)
            print("\033[31;1mvaregaergg\033[0m")
            if user_data['is_authenticated']:

                user_data['account_data'] = acc_data
                account_info(acc_data)
                main_interface.interactive(acc_data)


transaction

from conf import settings
from core import account
from core import logger


def make_transaction(log_obj, account_data, tran_type, amount):

    amount = float(amount)

    if tran_type in settings.TRANSACTION_TYPE:
        interest = amount * settings.TRANSACTION_TYPE[tran_type]['interest']
        old_balance = account_data['balance']
        if settings.TRANSACTION_TYPE[tran_type]['action'] == 'plus':
            new_balance = old_balance + amount + interest
        elif settings.TRANSACTION_TYPE[tran_type]['action'] == 'minus':
            new_balance = old_balance - amount - interest

            if new_balance < 0:
                print('''\033[31;1mYour credit [%s] is not enough for this transaction [-%s], your current balance is
                                [%s]''' % (account_data['credit'], (amount + interest), old_balance))
                return
        account_data['balance'] = new_balance
        account.dump_account(account_data)
        log_obj.info("account:%s  action:%s  amount:%s interest:%s"% (account_data['id'], tran_type, amount, interest))
        return account_data
    else:
        print("\033[31;1mTransaction type [%s] is not exist!\033[0m" % tran_type)

db

记录用户信息

 

log

存储日志

 

 

你可能感兴趣的:(pychon开荒)