def pay_deposit(**kwargs):
    """
    pay deposit
    :param data:
        card_no: card number
        deposit_fee: deposit amount
    :return:
    """
    card_no = kwargs["card_no"]
    deposit_fee = float(kwargs["deposit_fee"])

    out_trade_no = kwargs["out_trade_no"]

    virtual_card = VirtualCard.get(VirtualCard.card_no == card_no)

    virtual_card.deposit = deposit_fee
    result = virtual_card.save()
    record = ConsumeRecord.create(
        card=card_no,
        consume_event="deposit",
        consume_date_time=datetime.utcnow(),
        consume_fee=deposit_fee,
        balance=virtual_card.balance,
        out_trade_no=out_trade_no
    )
    # 给用户虚拟卡也存一个订单号
    virtual_card = VirtualCard.get(card_no=card_no)
    virtual_card.out_trade_no = out_trade_no
    virtual_card.save()

    return result, record
def top_up(**kwargs):
    """

    2. top up virtual card
    :param data:
        card_no: card number
        top_up_fee: top up amount
    :return:
    """
    card_no = kwargs["card_no"]
    top_up_fee = float(kwargs["top_up_fee"])

    virtual_card = VirtualCard.get(VirtualCard.card_no == card_no)

    if virtual_card.deposit < get_custom_const("DEFAULT_DEPOSIT"):
        raise Error("No deposit")
    else:
        balance = virtual_card.balance + top_up_fee
        virtual_card.balance = balance
        result = virtual_card.save()
        record = ConsumeRecord.create(
            card=card_no,
            consume_event="top up",
            consume_date_time=datetime.utcnow(),
            consume_fee=top_up_fee,
            balance=balance)
        return result, record
def get_virtual_card(card_no):
    """
    get virtual card information
    :param card_no: card number
    :return: card number, deposit and balance
    """
    virtual_card = VirtualCard.get(VirtualCard.card_no == card_no)
    return virtual_card
def add(**kwargs):
    """
    add new virtual card to database
    :param kwargs: parameters to insert to database
    :return:
    """
    virtual_card = VirtualCard.create(**kwargs)
    return virtual_card
def re_freeze(card_no):
    virtual_card = VirtualCard.get(card_no=card_no)
    virtual_card.situation = "正常"
    ConsumeRecord.create(
        card=card_no,
        consume_event="解冻账号",
        consume_date_time=datetime.utcnow(),
        consume_fee=0,
        balance=virtual_card.balance)
    return virtual_card.save()
def pre_top_up(**kwargs):
    """
    1. check
    :param kwargs:
    :type kwargs:
    :return:
    :rtype:
    """
    card_no = kwargs["card_no"]
    virtual_card = VirtualCard.get(VirtualCard.card_no == card_no)
    if virtual_card.deposit < get_custom_const("DEFAULT_DEPOSIT"):
        raise Error("No deposit")
def freeze(card_no, consume_event):
    virtual_card = VirtualCard.get(card_no=card_no)
    if virtual_card.situation == "冻结":
        return False

    virtual_card.situation = "冻结"
    ConsumeRecord.create(
        card=card_no,
        consume_event="冻结账户: "+consume_event,
        consume_date_time=datetime.utcnow(),
        consume_fee=0,
        balance=virtual_card.balance)
    return virtual_card.save()
def check_deposit(username):
    """
    check if the card has enough deposit
    :param username: card holder
    :return: True or raise an error
    """
    virtual_card = VirtualCard.get(VirtualCard.card_no == username)
    if virtual_card:
        deposit = virtual_card.deposit
        if deposit < get_custom_const("DEFAULT_DEPOSIT"):
            raise Error("没有足够的押金")
    else:
        raise Error("未开通虚拟卡")
def return_deposit(**kwargs):
    """
    return deposit
    :param kwargs:
        card_no: card number
    :return:
    """
    card_no = kwargs["card_no"]
    # 获取支付押金订单号
    out_trade_no = VirtualCard.get(card_no=card_no).out_trade_no

    on_loan = Battery.select().where(Battery.user == card_no)
    if on_loan:
        raise Error("电池使用中")

    virtual_card = VirtualCard.get(VirtualCard.card_no == card_no)
    deposit = virtual_card.deposit
    if deposit <= 0:
        raise Error("无可退还押金")
    else:
        virtual_card.deposit = 0
        result = virtual_card.save()
        record = ConsumeRecord.create(
            card=card_no,
            consume_event="return deposit",
            consume_date_time=datetime.utcnow(),
            consume_fee=-deposit,
            balance=virtual_card.balance)
        # 记录退款
        refund_record = refund_table_service.add(
            user=kwargs["card_no"],
            out_trade_no=out_trade_no,
            type="退虚拟卡押金",
            value=deposit,
        )
        print("退虚拟卡押金" + str(deposit))
        return result, record, refund_record
def pre_pay_deposit(**kwargs):
    card_no = kwargs["card_no"]

    deposit_fee = get_custom_const("DEFAULT_DEPOSIT")
    virtual_card = VirtualCard.get(VirtualCard.card_no == card_no)
    deposit = virtual_card.deposit
    if deposit >= deposit_fee:
        # 充值押金失败
        ConsumeRecord.create(
            card=card_no,
            consume_event="deposit failed",
            consume_date_time=datetime.utcnow(),
            consume_fee=deposit_fee,
            balance=virtual_card.balance)

        raise Error("无需充值押金")
    return deposit_fee
def check_status(username):
    """
    检查账户状态是否异常

    :param username:
    :type username:
    :return:
    :rtype:
    """
    virtual_card = VirtualCard.get(VirtualCard.card_no == username)
    # 0. 检查是否实名认证
    if virtual_card.real_name_authentication != "已认证":
        raise Error(VirtualCardErrorMessage.abnormal_situation)
    # 1. 检查状态
    if virtual_card.situation != "正常":
        raise Error(VirtualCardErrorMessage.no_real_name_authentication)
    # 2. 检查押金
    if virtual_card.deposit < get_custom_const("DEFAULT_DEPOSIT"):
        raise Error(VirtualCardErrorMessage.no_enough_deposit)
    # 3. 检查余额
    if virtual_card.balance < 0:
        raise Error(VirtualCardErrorMessage.no_enough_balance)
def consume_virtual_card(**kwargs):
    """
    consume virtual card
    :param data:
        card_no: card number
        consume_event: consume event
        amount: consume amount
    :return:
    """
    card_no = kwargs["card_no"]
    amount = float(kwargs["amount"])
    virtual_card = VirtualCard.get(VirtualCard.card_no == card_no)
    balance = virtual_card.balance - amount

    virtual_card.balance = balance
    result = virtual_card.save()
    record = ConsumeRecord.create(
        card=card_no,
        consume_event="consume",
        consume_date_time=datetime.utcnow(),
        consume_fee=-amount,
        balance=balance)
    return result, record
def get(*args, **kwargs):
    virtual_card = VirtualCard.get(*args, **kwargs)
    return virtual_card
def real_name_authentication(card_no):
    virtual_card = VirtualCard.get(card_no=card_no)
    virtual_card.real_name_authentication = "已认证"
    return virtual_card.save()
def get_all():
    virtual_cards = VirtualCard.select()
    return virtual_cards