Search in sources :

Example 66 with InvoiceItem

use of org.killbill.billing.invoice.api.InvoiceItem in project killbill by killbill.

the class ContiguousIntervalUsageInArrear method computeMissingItemsAndNextNotificationDate.

/**
     * Compute the missing usage invoice items based on what should be billed and what has been billed ($ amount comparison).
     *
     * @param existingUsage existing on disk usage items for the subscription
     * @throws CatalogApiException
     */
public UsageInArrearItemsAndNextNotificationDate computeMissingItemsAndNextNotificationDate(final List<InvoiceItem> existingUsage) throws CatalogApiException {
    Preconditions.checkState(isBuilt.get());
    if (transitionTimes.size() < 2) {
        return new UsageInArrearItemsAndNextNotificationDate(ImmutableList.<InvoiceItem>of(), computeNextNotificationDate());
    }
    final List<InvoiceItem> result = Lists.newLinkedList();
    // We start by generating 'marker' USAGE items with $0 that will allow to correctly insert the next notification for when there is no USAGE to bill.
    // Those will be removed by the invoicing code later so as to not end up with superfluous $0 items
    LocalDate prevDate = null;
    for (final LocalDate curDate : transitionTimes) {
        if (prevDate != null) {
            final InvoiceItem item = new UsageInvoiceItem(invoiceId, accountId, getBundleId(), getSubscriptionId(), getPlanName(), getPhaseName(), usage.getName(), prevDate, curDate, BigDecimal.ZERO, getCurrency());
            result.add(item);
        }
        prevDate = curDate;
    }
    final List<RolledUpUsage> allUsage = getRolledUpUsage();
    for (final RolledUpUsage ru : allUsage) {
        BigDecimal toBeBilledUsage = BigDecimal.ZERO;
        if (usage.getUsageType() == UsageType.CAPACITY) {
            toBeBilledUsage = computeToBeBilledCapacityInArrear(ru.getRolledUpUnits());
        } else /* UsageType.CONSUMABLE */
        {
            // Compute total price amount that should be billed for that period of time (and usage section) across unitTypes.
            for (final RolledUpUnit cur : ru.getRolledUpUnits()) {
                if (!unitTypes.contains(cur.getUnitType())) {
                    log.warn("ContiguousIntervalConsumableInArrear is skipping unitType " + cur.getUnitType());
                    continue;
                }
                final BigDecimal toBeBilledForUnit = computeToBeBilledConsumableInArrear(cur);
                toBeBilledUsage = toBeBilledUsage.add(toBeBilledForUnit);
            }
        }
        // Retrieves current price amount billed for that period of time (and usage section)
        final Iterable<InvoiceItem> billedItems = getBilledItems(ru.getStart(), ru.getEnd(), existingUsage);
        final BigDecimal billedUsage = computeBilledUsage(billedItems);
        // Compare the two and add the missing piece if required.
        if (!billedItems.iterator().hasNext() || billedUsage.compareTo(toBeBilledUsage) < 0) {
            final BigDecimal amountToBill = toBeBilledUsage.subtract(billedUsage);
            if (amountToBill.compareTo(BigDecimal.ZERO) > 0) {
                final InvoiceItem item = new UsageInvoiceItem(invoiceId, accountId, getBundleId(), getSubscriptionId(), getPlanName(), getPhaseName(), usage.getName(), ru.getStart(), ru.getEnd(), amountToBill, getCurrency());
                result.add(item);
            }
        }
    }
    final LocalDate nextNotificationdate = computeNextNotificationDate();
    return new UsageInArrearItemsAndNextNotificationDate(result, nextNotificationdate);
}
Also used : UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RolledUpUnit(org.killbill.billing.usage.api.RolledUpUnit) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) RolledUpUsage(org.killbill.billing.usage.api.RolledUpUsage) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal)

Example 67 with InvoiceItem

use of org.killbill.billing.invoice.api.InvoiceItem in project killbill by killbill.

the class TestDefaultInvoiceUserApi method testPostExternalChargeForBundleOnNewInvoice.

@Test(groups = "slow")
public void testPostExternalChargeForBundleOnNewInvoice() throws Exception {
    // Initial account balance
    final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
    // Post an external charge
    final BigDecimal externalChargeAmount = BigDecimal.TEN;
    final UUID bundleId = UUID.randomUUID();
    final InvoiceItem externalCharge = new ExternalChargeInvoiceItem(null, accountId, bundleId, UUID.randomUUID().toString(), clock.getUTCToday(), externalChargeAmount, accountCurrency);
    final InvoiceItem externalChargeInvoiceItem = invoiceUserApi.insertExternalCharges(accountId, clock.getUTCToday(), ImmutableList.<InvoiceItem>of(externalCharge), true, callContext).get(0);
    verifyExternalChargeOnNewInvoice(accountBalance, bundleId, externalChargeAmount, externalChargeInvoiceItem);
}
Also used : InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) UUID(java.util.UUID) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Example 68 with InvoiceItem

use of org.killbill.billing.invoice.api.InvoiceItem in project killbill by killbill.

the class TestDefaultInvoiceUserApi method testPostExternalChargeForBundleOnExistingInvoice.

@Test(groups = "slow")
public void testPostExternalChargeForBundleOnExistingInvoice() throws Exception {
    // Verify the initial invoice balance
    final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance();
    Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1);
    // Verify the initial account balance
    final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
    Assert.assertEquals(accountBalance, invoiceBalance);
    // Post an external charge
    final BigDecimal externalChargeAmount = BigDecimal.TEN;
    final UUID bundleId = UUID.randomUUID();
    final InvoiceItem externalCharge = new ExternalChargeInvoiceItem(invoiceId, accountId, bundleId, UUID.randomUUID().toString(), clock.getUTCToday(), externalChargeAmount, accountCurrency);
    final InvoiceItem externalChargeInvoiceItem = invoiceUserApi.insertExternalCharges(accountId, clock.getUTCToday(), ImmutableList.<InvoiceItem>of(externalCharge), true, callContext).get(0);
    verifyExternalChargeOnExistingInvoice(invoiceBalance, bundleId, externalChargeAmount, externalChargeInvoiceItem);
}
Also used : InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) UUID(java.util.UUID) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Example 69 with InvoiceItem

use of org.killbill.billing.invoice.api.InvoiceItem in project killbill by killbill.

the class TestDefaultInvoiceUserApi method testCantAdjustInvoiceItemWithNegativeAmount.

@Test(groups = "slow")
public void testCantAdjustInvoiceItemWithNegativeAmount() throws Exception {
    final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId, callContext).getInvoiceItems().get(0);
    try {
        invoiceUserApi.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItem.getId(), clock.getUTCToday(), BigDecimal.TEN.negate(), accountCurrency, null, callContext);
        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_SHOULD_BE_POSITIVE.getCode());
    }
}
Also used : InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) Test(org.testng.annotations.Test)

Example 70 with InvoiceItem

use of org.killbill.billing.invoice.api.InvoiceItem in project killbill by killbill.

the class TestDefaultInvoiceUserApi method testAdjustCommittedInvoice.

@Test(groups = "slow", expectedExceptions = InvoiceApiException.class, expectedExceptionsMessageRegExp = ".*it is already in COMMITTED status")
public void testAdjustCommittedInvoice() throws Exception {
    // Verify the initial invoice balance
    final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance();
    Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1);
    // Verify the initial account balance
    final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
    Assert.assertEquals(accountBalance, invoiceBalance);
    // Adjust the invoice for the full amount
    final InvoiceItem creditInvoiceItem = invoiceUserApi.insertCreditForInvoice(accountId, invoiceId, invoiceBalance, clock.getUTCToday(), accountCurrency, "some description", callContext);
    Assert.assertEquals(creditInvoiceItem.getInvoiceId(), invoiceId);
    Assert.assertEquals(creditInvoiceItem.getInvoiceItemType(), InvoiceItemType.CREDIT_ADJ);
    Assert.assertEquals(creditInvoiceItem.getAccountId(), accountId);
    Assert.assertEquals(creditInvoiceItem.getAmount().compareTo(invoiceBalance.negate()), 0);
    Assert.assertEquals(creditInvoiceItem.getCurrency(), accountCurrency);
    Assert.assertEquals(creditInvoiceItem.getDescription(), "some description");
    Assert.assertNull(creditInvoiceItem.getLinkedItemId());
    // Verify the adjusted invoice balance
    final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance();
    Assert.assertEquals(adjustedInvoiceBalance.compareTo(BigDecimal.ZERO), 0);
    // Verify the adjusted account balance
    final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
    Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance);
}
Also used : InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Aggregations

InvoiceItem (org.killbill.billing.invoice.api.InvoiceItem)168 LocalDate (org.joda.time.LocalDate)118 Test (org.testng.annotations.Test)109 BigDecimal (java.math.BigDecimal)103 FixedPriceInvoiceItem (org.killbill.billing.invoice.model.FixedPriceInvoiceItem)97 RecurringInvoiceItem (org.killbill.billing.invoice.model.RecurringInvoiceItem)92 ItemAdjInvoiceItem (org.killbill.billing.invoice.model.ItemAdjInvoiceItem)79 RepairAdjInvoiceItem (org.killbill.billing.invoice.model.RepairAdjInvoiceItem)76 UUID (java.util.UUID)68 Invoice (org.killbill.billing.invoice.api.Invoice)57 DefaultInvoice (org.killbill.billing.invoice.model.DefaultInvoice)36 ExternalChargeInvoiceItem (org.killbill.billing.invoice.model.ExternalChargeInvoiceItem)32 BillingEvent (org.killbill.billing.junction.BillingEvent)27 InvoiceApiException (org.killbill.billing.invoice.api.InvoiceApiException)25 ArrayList (java.util.ArrayList)23 DateTime (org.joda.time.DateTime)23 MockPlan (org.killbill.billing.catalog.MockPlan)23 MockPlanPhase (org.killbill.billing.catalog.MockPlanPhase)23 Plan (org.killbill.billing.catalog.api.Plan)22 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)21