/*
* Copyright 2010-2012 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.ning.billing.invoice.api.user;
import java.math.BigDecimal;
import java.util.UUID;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.ning.billing.ErrorCode;
import com.ning.billing.account.api.Account;
import com.ning.billing.invoice.api.InvoiceApiException;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.api.InvoiceItemType;
import com.ning.billing.invoice.api.migration.InvoiceApiTestBase;
import com.ning.billing.invoice.model.InvoicingConfiguration;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallOrigin;
import com.ning.billing.util.callcontext.DefaultCallContextFactory;
import com.ning.billing.util.callcontext.UserType;
public class TestDefaultInvoiceUserApi extends InvoiceApiTestBase {
private UUID accountId;
private UUID invoiceId;
private CallContext context;
@BeforeMethod(groups = "slow")
public void setupMethod() throws Exception {
final Account account = createAccount();
accountId = account.getId();
invoiceId = generateRegularInvoice(account, clock.getUTCNow());
context = new DefaultCallContextFactory(clock).createCallContext("Unit test", CallOrigin.TEST, UserType.TEST);
}
@Test(groups = "slow")
public void testAdjustFullInvoice() throws Exception {
// Verify the initial invoice balance
final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1);
// Verify the initial account balance
final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(accountBalance, invoiceBalance);
// Adjust the invoice for the full amount
final InvoiceItem creditInvoiceItem = invoiceUserApi.insertCreditForInvoice(accountId, invoiceId, invoiceBalance,
clock.getUTCToday(), accountCurrency, context);
Assert.assertEquals(creditInvoiceItem.getInvoiceId(), invoiceId);
Assert.assertEquals(creditInvoiceItem.getInvoiceItemType(), InvoiceItemType.CREDIT_ADJ);
Assert.assertEquals(creditInvoiceItem.getAccountId(), accountId);
Assert.assertEquals(creditInvoiceItem.getAmount(), invoiceBalance.negate());
Assert.assertEquals(creditInvoiceItem.getCurrency(), accountCurrency);
Assert.assertNull(creditInvoiceItem.getLinkedItemId());
// Verify the adjusted invoice balance
final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
Assert.assertEquals(adjustedInvoiceBalance.compareTo(BigDecimal.ZERO), 0);
// Verify the adjusted account balance
final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance);
}
@Test(groups = "slow")
public void testAdjustPartialInvoice() throws Exception {
// Verify the initial invoice balance
final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1);
// Verify the initial account balance
final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(accountBalance, invoiceBalance);
// Adjust the invoice for a fraction of the balance
final BigDecimal creditAmount = invoiceBalance.divide(BigDecimal.TEN);
final InvoiceItem creditInvoiceItem = invoiceUserApi.insertCreditForInvoice(accountId, invoiceId, creditAmount,
clock.getUTCToday(), accountCurrency, context);
Assert.assertEquals(creditInvoiceItem.getInvoiceId(), invoiceId);
Assert.assertEquals(creditInvoiceItem.getInvoiceItemType(), InvoiceItemType.CREDIT_ADJ);
Assert.assertEquals(creditInvoiceItem.getAccountId(), accountId);
Assert.assertEquals(creditInvoiceItem.getAmount(), creditAmount.negate());
Assert.assertEquals(creditInvoiceItem.getCurrency(), accountCurrency);
Assert.assertNull(creditInvoiceItem.getLinkedItemId());
// Verify the adjusted invoice balance
final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
// Note! The invoice code will round (see InvoiceItemList)
Assert.assertEquals(adjustedInvoiceBalance, invoiceBalance.add(creditAmount.negate()).setScale(InvoicingConfiguration.getNumberOfDecimals(),
InvoicingConfiguration.getRoundingMode()));
// Verify the adjusted account balance
final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance);
}
@Test(groups = "slow")
public void testCantAdjustInvoiceWithNegativeAmount() throws Exception {
try {
invoiceUserApi.insertCreditForInvoice(accountId, invoiceId, BigDecimal.TEN.negate(), clock.getUTCToday(), accountCurrency, context);
Assert.fail("Should not have been able to adjust an invoice with a negative amount");
} catch (InvoiceApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.CREDIT_AMOUNT_INVALID.getCode());
}
}
@Test(groups = "slow")
public void testAdjustFullInvoiceItem() throws Exception {
final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId).getInvoiceItems().get(0);
// Verify we picked a non zero item
Assert.assertEquals(invoiceItem.getAmount().compareTo(BigDecimal.ZERO), 1);
// Verify the initial invoice balance
final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1);
// Verify the initial account balance
final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(accountBalance, invoiceBalance);
// Adjust the invoice for the full amount
final InvoiceItem adjInvoiceItem = invoiceUserApi.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItem.getId(),
clock.getUTCToday(), null, null, context);
Assert.assertEquals(adjInvoiceItem.getInvoiceId(), invoiceId);
Assert.assertEquals(adjInvoiceItem.getInvoiceItemType(), InvoiceItemType.ITEM_ADJ);
Assert.assertEquals(adjInvoiceItem.getAccountId(), accountId);
Assert.assertEquals(adjInvoiceItem.getAmount(), invoiceItem.getAmount().negate());
Assert.assertEquals(adjInvoiceItem.getCurrency(), accountCurrency);
Assert.assertEquals(adjInvoiceItem.getLinkedItemId(), invoiceItem.getId());
// Verify the adjusted invoice balance
final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
// Note! The invoice code will round (see InvoiceItemList)
Assert.assertEquals(adjustedInvoiceBalance, invoiceBalance.add(invoiceItem.getAmount().negate()).setScale(InvoicingConfiguration.getNumberOfDecimals(),
InvoicingConfiguration.getRoundingMode()));
// Verify the adjusted account balance
final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance);
}
@Test(groups = "slow")
public void testAdjustPartialInvoiceItem() throws Exception {
final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId).getInvoiceItems().get(0);
// Verify we picked a non zero item
Assert.assertEquals(invoiceItem.getAmount().compareTo(BigDecimal.ZERO), 1);
// Verify the initial invoice balance
final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1);
// Verify the initial account balance
final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(accountBalance, invoiceBalance);
// Adjust the invoice for a fraction of the balance
final BigDecimal adjAmount = invoiceItem.getAmount().divide(BigDecimal.TEN);
final InvoiceItem adjInvoiceItem = invoiceUserApi.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItem.getId(),
clock.getUTCToday(), adjAmount, accountCurrency,
context);
Assert.assertEquals(adjInvoiceItem.getInvoiceId(), invoiceId);
Assert.assertEquals(adjInvoiceItem.getInvoiceItemType(), InvoiceItemType.ITEM_ADJ);
Assert.assertEquals(adjInvoiceItem.getAccountId(), accountId);
Assert.assertEquals(adjInvoiceItem.getAmount(), adjAmount.negate());
Assert.assertEquals(adjInvoiceItem.getCurrency(), accountCurrency);
Assert.assertEquals(adjInvoiceItem.getLinkedItemId(), invoiceItem.getId());
// Verify the adjusted invoice balance
final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
// Note! The invoice code will round (see InvoiceItemList)
Assert.assertEquals(adjustedInvoiceBalance, invoiceBalance.add(adjAmount.negate()).setScale(InvoicingConfiguration.getNumberOfDecimals(),
InvoicingConfiguration.getRoundingMode()));
// Verify the adjusted account balance
final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId);
Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance);
}
@Test(groups = "slow")
public void testCantAdjustInvoiceItemWithNegativeAmount() throws Exception {
final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId).getInvoiceItems().get(0);
try {
invoiceUserApi.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItem.getId(), clock.getUTCToday(),
BigDecimal.TEN.negate(), accountCurrency, context);
Assert.fail("Should not have been able to adjust an item with a negative amount");
} catch (InvoiceApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.INVOICE_ITEM_ADJUSTMENT_AMOUNT_INVALID.getCode());
}
}
}