예제 #1
0
def add_payment(sale, payment_opt):
    """ Add a payment to the specified sale """

    db = current.db
    T = current.T

    add_new_payment = False

    # allow multiple payments for the same payment option
    if payment_opt.requires_account or common_utils.is_wallet(
            payment_opt) or sale.is_deferred:

        add_new_payment = True
    else:
        # get payments with the same payment option
        payment = db((db.payment.id_sale == sale.id)
                     & (db.payment.id_payment_opt == payment_opt.id)
                     & (db.payment.is_updatable == True)).select().first()
        if not payment:
            add_new_payment = True

    if add_new_payment:
        new_payment_id = db.payment.insert(id_payment_opt=payment_opt.id,
                                           id_sale=sale.id)
        return new_payment_id
    else:
        raise CP_PaymentError(
            T("You already have a payment with that payment option."))
예제 #2
0
def add_payment(sale, payment_opt):
    """ Add a payment to the specified sale """

    db = current.db
    T = current.T

    add_new_payment = False

    # allow multiple payments for the same payment option
    if payment_opt.requires_account or common_utils.is_wallet(payment_opt) or sale.is_deferred:

        add_new_payment = True
    else:
        # get payments with the same payment option
        payment = db((db.payment.id_sale == sale.id)
            & (db.payment.id_payment_opt == payment_opt.id)
            & (db.payment.is_updatable == True)
        ).select().first()
        if not payment:
            add_new_payment = True

    if add_new_payment:
        new_payment_id = db.payment.insert(id_payment_opt=payment_opt.id, id_sale=sale.id)
        return new_payment_id
    else:
        raise CP_PaymentError(
            T("You already have a payment with that payment option.")
        )
예제 #3
0
def modify_payment(sale, payment, payment_data, delete=False):
    """
        payment_data: {
            'amount',
            'wallet_code',
            'account'
        }

    """

    db = current.db
    T = current.T

    new_amount = payment_data.get('amount')

    # is wallet payment
    if payment.wallet_code:
        new_amount = payment.amount

    # delete payment
    if delete:
        new_amount = 0

    # since calling this function, could cause modification to other payments, we have to store the modified payments, so the client can render the changes
    extra_updated_payments = []
    total, change, payments = get_payments_data(sale.id)
    new_total = total - change - (payment.amount -
                                  payment.change_amount) + new_amount
    if new_total > (sale.total - sale.discount):
        # when the payment does not allow change, cut the amount to the exact remaining
        if not payment.id_payment_opt.allow_change:
            new_amount -= new_total - (sale.total - sale.discount)
    else:
        remaining = (sale.total - sale.discount) - new_total
        # when the payment modification makes the new total lower than the sale total, we have to find all the payments with change > 0 (if any) and recalculate their amount and their change
        for other_payment in payments:
            if not other_payment.id_payment_opt.allow_change or other_payment.id == payment.id:
                continue
            if remaining == 0:
                break
            if other_payment.change_amount > 0:
                new_remaining = min(remaining, other_payment.change_amount)
                new_change = other_payment.change_amount - new_remaining
                remaining -= new_remaining
                other_payment.change_amount = new_change
                other_payment.update_record()
                extra_updated_payments.append(other_payment)

    change = max(0, new_total - (sale.total - sale.discount))
    account = payment_data.get('account')
    wallet_code = payment_data.get('wallet_code')
    # fix payment info
    if not payment.id_payment_opt.allow_change:
        change = 0
    if not payment.id_payment_opt.requires_account:
        account = None
    if not common_utils.is_wallet(payment.id_payment_opt):
        wallet_code = None
    else:
        if payment.wallet_code:
            # return wallet funds, if the wallet payment is removed or the wallet code is changed
            if delete or wallet_code != payment.wallet_code:
                wallet = db(
                    db.wallet.wallet_code == payment.wallet_code).select(
                        for_update=True).first()
                if wallet:
                    wallet.balance += payment.amount
                    wallet.update_record()
        else:
            new_amount = 0

        # only accept the first wallet code specified
        if wallet_code != payment.wallet_code:
            wallet = db(db.wallet.wallet_code == wallet_code).select(
                for_update=True).first()
            if wallet:
                new_amount = min(wallet.balance,
                                 (sale.total - sale.discount) - new_total)
                wallet.balance -= new_amount
                wallet.update_record()
            # if the code is invalid, remove its specified value
            else:
                wallet_code = None
                new_amount = 0

    payment.amount = new_amount
    payment.change_amount = change
    payment.account = account
    payment.wallet_code = wallet_code
    payment.update_record()
    if not delete:
        extra_updated_payments.append(payment)
    elif payment.is_updatable:
        payment.delete_record()

    # get the total payments data
    payments_data = get_payments_data(sale.id)
    # amount - change_amount
    payments_total = payments_data[0] - payments_data[1]

    data = dict(payments_total=payments_total,
                updated_payments=extra_updated_payments)

    return data
예제 #4
0
def modify_payment(sale, payment, payment_data, delete=False):
    """
        payment_data: {
            'amount',
            'wallet_code',
            'account'
        }

    """

    db = current.db
    T = current.T


    new_amount = payment_data.get('amount')

    # delete payment
    if delete:
        new_amount = 0

    # since calling this function, could cause modification to other payments, we have to store the modified payments, so the client can render the changes
    extra_updated_payments = []
    total, change, payments = get_payments_data(sale.id)
    new_total = total - change - (payment.amount - payment.change_amount) + new_amount
    if new_total > (sale.total - sale.discount):
        # when the payment does not allow change, cut the amount to the exact remaining
        if not payment.id_payment_opt.allow_change:
            new_amount -= new_total - (sale.total - sale.discount)
    else:
        remaining = (sale.total - sale.discount) - new_total
        # when the payment modification makes the new total lower than the sale total, we have to find all the payments with change > 0 (if any) and recalculate their amount and their change
        for other_payment in payments:
            if not other_payment.id_payment_opt.allow_change or other_payment.id == payment.id:
                continue
            if remaining == 0:
                break
            if other_payment.change_amount > 0:
                new_remaining = min(remaining, other_payment.change_amount)
                new_change = other_payment.change_amount - new_remaining
                remaining -= new_remaining
                other_payment.change_amount = new_change
                other_payment.update_record()
                extra_updated_payments.append(other_payment)

    change = max(0, new_total - (sale.total - sale.discount))
    account = payment_data.get('account')
    wallet_code = payment_data.get('wallet_code')
    # fix payment info
    if not payment.id_payment_opt.allow_change:
        change = 0
    if not payment.id_payment_opt.requires_account:
         account = None
    if not common_utils.is_wallet(payment.id_payment_opt):
         wallet_code = None
    # in this case the payment is wallet
    else:
        if payment.wallet_code:
            # return wallet funds, if the wallet payment is removed or the wallet code is changed
            if delete or wallet_code != payment.wallet_code:
                wallet_utils.transaction(
                    payment.amount, wallet_utils.UNDO_PAYMENT, ref=payment.id,
                    wallet_code=payment.wallet_code
                )

        # only accept the first wallet code specified
        if wallet_code != payment.wallet_code:
            try:
                # new_amount = max(0, min(wallet.balance, (sale.total - sale.discount) - new_total))

                rem_q = (sale.total - sale.discount) - new_total
                if rem_q >= 0:
                    _wallet, _amount = wallet_utils.transaction(
                        -rem_q, wallet_utils.CONCEPT_PAYMENT, ref=payment.id,
                        wallet_code=wallet_code
                    )
                    new_amount = abs(_amount)
            except:
                wallet_code = None
                new_amount = 0

    payment.amount = new_amount
    payment.change_amount = change
    payment.account = account
    payment.wallet_code = wallet_code
    payment.update_record()
    if not delete:
        extra_updated_payments.append(payment)
    elif payment.is_updatable:
        payment.delete_record()

    # get the total payments data
    payments_data = get_payments_data(sale.id)
    # amount - change_amount
    payments_total = payments_data[0] - payments_data[1]

    data = dict(
        payments_total=payments_total,
        updated_payments=extra_updated_payments
    )

    return data