Details
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
index c8dd494..3b78afe 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
@@ -144,6 +144,22 @@ public interface InvoiceUserApi {
Currency currency, CallContext context) throws InvoiceApiException;
/**
+ * Add an external charge to an account tied to a particular bundle.
+ *
+ * @param accountId account id
+ * @param bundleId bundle id
+ * @param amount the external charge amount
+ * @param description a description for that charge
+ * @param effectiveDate the day to post the external charge, in the account timezone
+ * @param currency the external charge currency
+ * @param context the call context
+ * @return the external charge invoice item
+ * @throws InvoiceApiException
+ */
+ public InvoiceItem insertExternalChargeForBundle(UUID accountId, UUID bundleId, BigDecimal amount, String description, LocalDate effectiveDate,
+ Currency currency, CallContext context) throws InvoiceApiException;
+
+ /**
* Add an external charge to an invoice.
*
* @param accountId account id
@@ -160,6 +176,23 @@ public interface InvoiceUserApi {
LocalDate effectiveDate, Currency currency, CallContext context) throws InvoiceApiException;
/**
+ * Add an external charge to an invoice tied to a particular bundle.
+ *
+ * @param accountId account id
+ * @param invoiceId invoice id
+ * @param bundleId bundle id
+ * @param amount the external charge amount
+ * @param description a description for that charge
+ * @param effectiveDate the day to post the external charge, in the account timezone
+ * @param currency the external charge currency
+ * @param context the call context
+ * @return the external charge invoice item
+ * @throws InvoiceApiException
+ */
+ public InvoiceItem insertExternalChargeForInvoiceAndBundle(UUID accountId, UUID invoiceId, UUID bundleId, BigDecimal amount, String description,
+ LocalDate effectiveDate, Currency currency, CallContext context) throws InvoiceApiException;
+
+ /**
* Retrieve a credit by id.
*
* @param creditId credit id
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 012bdf2..bd524b2 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -149,17 +149,30 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
@Override
public InvoiceItem insertExternalCharge(final UUID accountId, final BigDecimal amount, @Nullable final String description,
final LocalDate effectiveDate, final Currency currency, final CallContext context) throws InvoiceApiException {
- return insertExternalChargeForInvoice(accountId, null, amount, description, effectiveDate, currency, context);
+ return insertExternalChargeForInvoiceAndBundle(accountId, null, null, amount, description, effectiveDate, currency, context);
+ }
+
+ @Override
+ public InvoiceItem insertExternalChargeForBundle(final UUID accountId, final UUID bundleId, final BigDecimal amount, @Nullable final String description,
+ final LocalDate effectiveDate, final Currency currency, final CallContext context) throws InvoiceApiException {
+ return insertExternalChargeForInvoiceAndBundle(accountId, null, bundleId, amount, description, effectiveDate, currency, context);
}
@Override
public InvoiceItem insertExternalChargeForInvoice(final UUID accountId, final UUID invoiceId, final BigDecimal amount, @Nullable final String description,
final LocalDate effectiveDate, final Currency currency, final CallContext context) throws InvoiceApiException {
+ return insertExternalChargeForInvoiceAndBundle(accountId, invoiceId, null, amount, description, effectiveDate, currency, context);
+ }
+
+ @Override
+ public InvoiceItem insertExternalChargeForInvoiceAndBundle(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final UUID bundleId,
+ final BigDecimal amount, @Nullable final String description, final LocalDate effectiveDate,
+ final Currency currency, final CallContext context) throws InvoiceApiException {
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new InvoiceApiException(ErrorCode.EXTERNAL_CHARGE_AMOUNT_INVALID, amount);
}
- return dao.insertExternalCharge(accountId, invoiceId, description, amount, effectiveDate, currency, context);
+ return dao.insertExternalCharge(accountId, invoiceId, bundleId, description, amount, effectiveDate, currency, context);
}
@Override
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index f6a0e95..c0fc0b4 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -531,7 +531,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
}
@Override
- public InvoiceItem insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, final String description,
+ public InvoiceItem insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final UUID bundleId, final String description,
final BigDecimal amount, final LocalDate effectiveDate, final Currency currency, final CallContext context) {
return invoiceSqlDao.inTransaction(new Transaction<InvoiceItem, InvoiceSqlDao>() {
@Override
@@ -544,7 +544,8 @@ public class DefaultInvoiceDao implements InvoiceDao {
invoiceIdForExternalCharge = invoiceForExternalCharge.getId();
}
- final InvoiceItem externalCharge = new ExternalChargeInvoiceItem(invoiceIdForExternalCharge, accountId, description,
+ final InvoiceItem externalCharge = new ExternalChargeInvoiceItem(invoiceIdForExternalCharge, accountId,
+ bundleId, description,
effectiveDate, amount, currency);
final InvoiceItemSqlDao transInvoiceItemDao = transactional.become(InvoiceItemSqlDao.class);
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index 0c9b60e..ecbda77 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -110,6 +110,7 @@ public interface InvoiceDao {
*
* @param accountId the account id
* @param invoiceId the invoice id
+ * @param bundleId the bundle id
* @param description a description for that charge
* @param amount the external charge amount
* @param effectiveDate the day to post the external charge, in the account timezone
@@ -117,7 +118,7 @@ public interface InvoiceDao {
* @param context the call context
* @return the newly created external charge invoice item
*/
- InvoiceItem insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final String description,
+ InvoiceItem insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final UUID bundleId, @Nullable final String description,
final BigDecimal amount, final LocalDate effectiveDate, final Currency currency, final CallContext context);
/**
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
index d3758c4..2391bc9 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
@@ -134,7 +134,7 @@ public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItem> {
InvoiceItem item = null;
switch (type) {
case EXTERNAL_CHARGE:
- item = new ExternalChargeInvoiceItem(id, invoiceId, accountId, planName, startDate, amount, currency);
+ item = new ExternalChargeInvoiceItem(id, invoiceId, accountId, bundleId, planName, startDate, amount, currency);
break;
case FIXED:
item = new FixedPriceInvoiceItem(id, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, amount, currency);
diff --git a/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
index 1c45243..997bb7a 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
@@ -97,7 +97,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
if (existingInvoices != null) {
for (final Invoice invoice : existingInvoices) {
for (final InvoiceItem item : invoice.getInvoiceItems()) {
- if (item.getSubscriptionId() == null || // Always include migration invoices, credits, external charged etc.
+ if (item.getSubscriptionId() == null || // Always include migration invoices, credits, external charges etc.
!events.getSubscriptionIdsWithAutoInvoiceOff()
.contains(item.getSubscriptionId())) { //don't add items with auto_invoice_off tag
existingItems.add(item);
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/ExternalChargeInvoiceItem.java b/invoice/src/main/java/com/ning/billing/invoice/model/ExternalChargeInvoiceItem.java
index ae5dbae..c8f0245 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/ExternalChargeInvoiceItem.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/ExternalChargeInvoiceItem.java
@@ -19,6 +19,8 @@ package com.ning.billing.invoice.model;
import java.math.BigDecimal;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.joda.time.LocalDate;
import com.ning.billing.catalog.api.Currency;
@@ -27,14 +29,14 @@ import com.ning.billing.invoice.api.InvoiceItemType;
public class ExternalChargeInvoiceItem extends InvoiceItemBase {
- public ExternalChargeInvoiceItem(final UUID invoiceId, final UUID accountId, final String description, final LocalDate date,
- final BigDecimal amount, final Currency currency) {
- super(invoiceId, accountId, null, null, description, null, date, null, amount, currency);
+ public ExternalChargeInvoiceItem(final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId, @Nullable final String description,
+ final LocalDate date, final BigDecimal amount, final Currency currency) {
+ super(invoiceId, accountId, bundleId, null, description, null, date, null, amount, currency);
}
- public ExternalChargeInvoiceItem(final UUID id, final UUID invoiceId, final UUID accountId, final String description,
- final LocalDate date, final BigDecimal amount, final Currency currency) {
- super(id, invoiceId, accountId, null, (UUID) null, description, null, date, null, amount, currency);
+ public ExternalChargeInvoiceItem(final UUID id, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
+ @Nullable final String description, final LocalDate date, final BigDecimal amount, final Currency currency) {
+ super(id, invoiceId, accountId, bundleId, (UUID) null, description, null, date, null, amount, currency);
}
@Override
@@ -77,16 +79,10 @@ public class ExternalChargeInvoiceItem extends InvoiceItemBase {
sb.append("InvoiceItem = {").append("id = ").append(id.toString()).append(", ");
sb.append("invoiceId = ").append(invoiceId.toString()).append(", ");
sb.append("accountId = ").append(accountId.toString()).append(", ");
+ sb.append("bundleId = ").append(bundleId == null ? "null" : bundleId.toString()).append(", ");
sb.append("description = ").append(planName).append(", ");
sb.append("startDate = ").append(startDate.toString()).append(", ");
-
- sb.append("amount = ");
- if (amount == null) {
- sb.append("null");
- } else {
- sb.append(amount.toString());
- }
-
+ sb.append("amount = ").append(amount == null ? "null" : amount.toString()).append(", ");
sb.append("}");
return sb.toString();
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
index 23a3445..ee3e5a4 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
@@ -19,6 +19,8 @@ package com.ning.billing.invoice.api.user;
import java.math.BigDecimal;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -58,8 +60,28 @@ public class TestDefaultInvoiceUserApi extends InvoiceApiTestBase {
final BigDecimal externalChargeAmount = BigDecimal.TEN;
final InvoiceItem externalChargeInvoiceItem = invoiceUserApi.insertExternalCharge(accountId, externalChargeAmount, UUID.randomUUID().toString(),
clock.getUTCToday(), accountCurrency, context);
+ verifyExternalChargeOnNewInvoice(accountBalance, null, externalChargeAmount, externalChargeInvoiceItem);
+ }
+
+ @Test(groups = "slow")
+ public void testPostExternalChargeForBundleOnNewInvoice() throws Exception {
+ // Initial account balance
+ final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId);
+
+ // Post an external charge
+ final BigDecimal externalChargeAmount = BigDecimal.TEN;
+ final UUID bundleId = UUID.randomUUID();
+ final InvoiceItem externalChargeInvoiceItem = invoiceUserApi.insertExternalChargeForBundle(accountId, bundleId, externalChargeAmount,
+ UUID.randomUUID().toString(), clock.getUTCToday(),
+ accountCurrency, context);
+ verifyExternalChargeOnNewInvoice(accountBalance, bundleId, externalChargeAmount, externalChargeInvoiceItem);
+ }
+
+ private void verifyExternalChargeOnNewInvoice(final BigDecimal initialAccountBalance, @Nullable final UUID bundleId,
+ final BigDecimal externalChargeAmount, final InvoiceItem externalChargeInvoiceItem) {
Assert.assertNotNull(externalChargeInvoiceItem.getInvoiceId());
Assert.assertNotEquals(externalChargeInvoiceItem.getInvoiceId(), invoiceId);
+ Assert.assertEquals(externalChargeInvoiceItem.getBundleId(), bundleId);
Assert.assertEquals(externalChargeInvoiceItem.getInvoiceItemType(), InvoiceItemType.EXTERNAL_CHARGE);
Assert.assertEquals(externalChargeInvoiceItem.getAccountId(), accountId);
Assert.assertEquals(externalChargeInvoiceItem.getAmount(), externalChargeAmount);
@@ -72,7 +94,7 @@ public class TestDefaultInvoiceUserApi extends InvoiceApiTestBase {
// Verify the adjusted account balance
final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId);
- Assert.assertEquals(adjustedAccountBalance, accountBalance.add(externalChargeAmount));
+ Assert.assertEquals(adjustedAccountBalance, initialAccountBalance.add(externalChargeAmount));
}
@Test(groups = "slow")
@@ -90,7 +112,32 @@ public class TestDefaultInvoiceUserApi extends InvoiceApiTestBase {
final InvoiceItem externalChargeInvoiceItem = invoiceUserApi.insertExternalChargeForInvoice(accountId, invoiceId,
externalChargeAmount, UUID.randomUUID().toString(),
clock.getUTCToday(), accountCurrency, context);
+ verifyExternalChargeOnExistingInvoice(invoiceBalance, null, externalChargeAmount, externalChargeInvoiceItem);
+ }
+
+ @Test(groups = "slow")
+ public void testPostExternalChargeForBundleOnExistingInvoice() 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);
+
+ // Post an external charge
+ final BigDecimal externalChargeAmount = BigDecimal.TEN;
+ final UUID bundleId = UUID.randomUUID();
+ final InvoiceItem externalChargeInvoiceItem = invoiceUserApi.insertExternalChargeForInvoiceAndBundle(accountId, invoiceId, bundleId,
+ externalChargeAmount, UUID.randomUUID().toString(),
+ clock.getUTCToday(), accountCurrency, context);
+ verifyExternalChargeOnExistingInvoice(invoiceBalance, bundleId, externalChargeAmount, externalChargeInvoiceItem);
+ }
+
+ private void verifyExternalChargeOnExistingInvoice(final BigDecimal initialInvoiceBalance, @Nullable final UUID bundleId,
+ final BigDecimal externalChargeAmount, final InvoiceItem externalChargeInvoiceItem) {
Assert.assertEquals(externalChargeInvoiceItem.getInvoiceId(), invoiceId);
+ Assert.assertEquals(externalChargeInvoiceItem.getBundleId(), bundleId);
Assert.assertEquals(externalChargeInvoiceItem.getInvoiceItemType(), InvoiceItemType.EXTERNAL_CHARGE);
Assert.assertEquals(externalChargeInvoiceItem.getAccountId(), accountId);
Assert.assertEquals(externalChargeInvoiceItem.getAmount(), externalChargeAmount);
@@ -99,7 +146,7 @@ public class TestDefaultInvoiceUserApi extends InvoiceApiTestBase {
// Verify the adjusted invoice balance
final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId).getBalance();
- Assert.assertEquals(adjustedInvoiceBalance.compareTo(invoiceBalance.add(externalChargeAmount)), 0);
+ Assert.assertEquals(adjustedInvoiceBalance.compareTo(initialInvoiceBalance.add(externalChargeAmount)), 0);
// Verify the adjusted account balance
final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index a7884b5..8ea4553 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -27,8 +27,6 @@ import javax.annotation.Nullable;
import org.joda.time.LocalDate;
-import com.google.inject.Inject;
-
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
@@ -38,7 +36,10 @@ import com.ning.billing.invoice.api.user.DefaultInvoiceCreationEvent;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.callcontext.CallContext;
+import com.google.inject.Inject;
+
public class MockInvoiceDao implements InvoiceDao {
+
private final Bus eventBus;
private final Object monitor = new Object();
private final Map<UUID, Invoice> invoices = new LinkedHashMap<UUID, Invoice>();
@@ -264,7 +265,9 @@ public class MockInvoiceDao implements InvoiceDao {
}
@Override
- public InvoiceItem insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final String description, final BigDecimal amount, final LocalDate effectiveDate, final Currency currency, final CallContext context) {
+ public InvoiceItem insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final UUID bundleId,
+ @Nullable final String description, final BigDecimal amount, final LocalDate effectiveDate,
+ final Currency currency, final CallContext context) {
throw new UnsupportedOperationException();
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
index 4bf050e..acf4a79 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
@@ -163,9 +163,10 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
public void testExternalChargeInvoiceSqlDao() throws Exception {
final UUID invoiceId = UUID.randomUUID();
final UUID accountId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
final String description = UUID.randomUUID().toString();
final LocalDate startDate = new LocalDate(2012, 4, 1);
- final InvoiceItem externalChargeInvoiceItem = new ExternalChargeInvoiceItem(invoiceId, accountId, description,
+ final InvoiceItem externalChargeInvoiceItem = new ExternalChargeInvoiceItem(invoiceId, accountId, bundleId, description,
startDate, TEN, Currency.USD);
invoiceItemSqlDao.create(externalChargeInvoiceItem, context);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/model/TestExternalChargeInvoiceItem.java b/invoice/src/test/java/com/ning/billing/invoice/model/TestExternalChargeInvoiceItem.java
index cd59851..c525627 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/model/TestExternalChargeInvoiceItem.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/model/TestExternalChargeInvoiceItem.java
@@ -37,18 +37,19 @@ public class TestExternalChargeInvoiceItem {
final UUID id = UUID.randomUUID();
final UUID invoiceId = UUID.randomUUID();
final UUID accountId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
final String description = UUID.randomUUID().toString();
final LocalDate effectiveDate = clock.getUTCToday();
final BigDecimal amount = BigDecimal.TEN;
final Currency currency = Currency.GBP;
- final ExternalChargeInvoiceItem item = new ExternalChargeInvoiceItem(id, invoiceId, accountId, description,
+ final ExternalChargeInvoiceItem item = new ExternalChargeInvoiceItem(id, invoiceId, accountId, bundleId, description,
effectiveDate, amount, currency);
Assert.assertEquals(item.getAccountId(), accountId);
Assert.assertEquals(item.getAmount(), amount);
+ Assert.assertEquals(item.getBundleId(), bundleId);
Assert.assertEquals(item.getCurrency(), currency);
Assert.assertEquals(item.getInvoiceItemType(), InvoiceItemType.EXTERNAL_CHARGE);
Assert.assertEquals(item.getPlanName(), description);
- Assert.assertNull(item.getBundleId());
Assert.assertNull(item.getEndDate());
Assert.assertNull(item.getLinkedItemId());
Assert.assertNull(item.getPhaseName());
@@ -57,15 +58,15 @@ public class TestExternalChargeInvoiceItem {
Assert.assertEquals(item, item);
- final ExternalChargeInvoiceItem otherItem = new ExternalChargeInvoiceItem(id, invoiceId, UUID.randomUUID(), description,
- effectiveDate, amount, currency);
+ final ExternalChargeInvoiceItem otherItem = new ExternalChargeInvoiceItem(id, invoiceId, UUID.randomUUID(), bundleId,
+ description, effectiveDate, amount, currency);
Assert.assertNotEquals(otherItem, item);
// Check comparison (done by start date)
- final ExternalChargeInvoiceItem itemBefore = new ExternalChargeInvoiceItem(id, invoiceId, accountId, description,
+ final ExternalChargeInvoiceItem itemBefore = new ExternalChargeInvoiceItem(id, invoiceId, accountId, bundleId, description,
effectiveDate.minusDays(1), amount, currency);
Assert.assertEquals(itemBefore.compareTo(item), -1);
- final ExternalChargeInvoiceItem itemAfter = new ExternalChargeInvoiceItem(id, invoiceId, accountId, description,
+ final ExternalChargeInvoiceItem itemAfter = new ExternalChargeInvoiceItem(id, invoiceId, accountId, bundleId, description,
effectiveDate.plusDays(1), amount, currency);
Assert.assertEquals(itemAfter.compareTo(item), 1);
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
index 13960aa..816eaf3 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
@@ -248,9 +248,16 @@ public class InvoiceResource extends JaxRsResourceBase {
}
final Currency currency = Objects.firstNonNull(externalChargeJson.getCurrency(), account.getCurrency());
- final InvoiceItem externalCharge = invoiceApi.insertExternalCharge(account.getId(), externalChargeJson.getAmount(),
- externalChargeJson.getDescription(), requestedDate,
- currency, callContext);
+ final InvoiceItem externalCharge;
+ if (externalChargeJson.getBundleId() != null) {
+ externalCharge = invoiceApi.insertExternalChargeForBundle(account.getId(), UUID.fromString(externalChargeJson.getBundleId()),
+ externalChargeJson.getAmount(), externalChargeJson.getDescription(),
+ requestedDate, currency, callContext);
+ } else {
+ externalCharge = invoiceApi.insertExternalCharge(account.getId(), externalChargeJson.getAmount(),
+ externalChargeJson.getDescription(), requestedDate,
+ currency, callContext);
+ }
return uriBuilder.buildResponse(InvoiceResource.class, "getInvoice", externalCharge.getInvoiceId(), uriInfo.getBaseUri().toString());
}
@@ -280,9 +287,16 @@ public class InvoiceResource extends JaxRsResourceBase {
final UUID invoiceId = UUID.fromString(invoiceIdString);
final Currency currency = Objects.firstNonNull(externalChargeJson.getCurrency(), account.getCurrency());
- final InvoiceItem externalCharge = invoiceApi.insertExternalChargeForInvoice(account.getId(), invoiceId,
- externalChargeJson.getAmount(), externalChargeJson.getDescription(),
- requestedDate, currency, callContext);
+ final InvoiceItem externalCharge;
+ if (externalChargeJson.getBundleId() != null) {
+ externalCharge = invoiceApi.insertExternalChargeForInvoiceAndBundle(account.getId(), invoiceId, UUID.fromString(externalChargeJson.getBundleId()),
+ externalChargeJson.getAmount(), externalChargeJson.getDescription(),
+ requestedDate, currency, callContext);
+ } else {
+ externalCharge = invoiceApi.insertExternalChargeForInvoice(account.getId(), invoiceId,
+ externalChargeJson.getAmount(), externalChargeJson.getDescription(),
+ requestedDate, currency, callContext);
+ }
return uriBuilder.buildResponse(InvoiceResource.class, "getInvoice", externalCharge.getInvoiceId(), uriInfo.getBaseUri().toString());
}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
index 66cfb7c..712baeb 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
@@ -19,6 +19,7 @@ package com.ning.billing.jaxrs;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
+import java.util.UUID;
import org.joda.time.DateTime;
import org.testng.annotations.Test;
@@ -196,9 +197,29 @@ public class TestInvoice extends TestJaxrsBase {
// Post an external charge
final BigDecimal chargeAmount = BigDecimal.TEN;
- final InvoiceJsonWithItems invoiceWithItems = createExternalCharge(accountJson.getAccountId(), chargeAmount, null, null);
+ final InvoiceJsonWithItems invoiceWithItems = createExternalCharge(accountJson.getAccountId(), chargeAmount, null, null, null);
assertEquals(invoiceWithItems.getBalance().compareTo(chargeAmount), 0);
assertEquals(invoiceWithItems.getItems().size(), 1);
+ assertNull(invoiceWithItems.getItems().get(0).getBundleId());
+
+ // Verify the total number of invoices
+ assertEquals(getInvoicesForAccount(accountJson.getAccountId()).size(), 3);
+ }
+
+ @Test(groups = "slow")
+ public void testExternalChargeForBundleOnNewInvoice() throws Exception {
+ final AccountJson accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+ // Get the invoices
+ assertEquals(getInvoicesForAccount(accountJson.getAccountId()).size(), 2);
+
+ // Post an external charge
+ final BigDecimal chargeAmount = BigDecimal.TEN;
+ final String bundleId = UUID.randomUUID().toString();
+ final InvoiceJsonWithItems invoiceWithItems = createExternalCharge(accountJson.getAccountId(), chargeAmount, bundleId, null, null);
+ assertEquals(invoiceWithItems.getBalance().compareTo(chargeAmount), 0);
+ assertEquals(invoiceWithItems.getItems().size(), 1);
+ assertEquals(invoiceWithItems.getItems().get(0).getBundleId(), bundleId);
// Verify the total number of invoices
assertEquals(getInvoicesForAccount(accountJson.getAccountId()).size(), 3);
@@ -218,8 +239,36 @@ public class TestInvoice extends TestJaxrsBase {
// Post an external charge
final BigDecimal chargeAmount = BigDecimal.TEN;
- final InvoiceJsonWithItems invoiceWithItems = createExternalChargeForInvoice(accountJson.getAccountId(), invoiceId, chargeAmount, null, null);
+ final InvoiceJsonWithItems invoiceWithItems = createExternalChargeForInvoice(accountJson.getAccountId(), invoiceId,
+ null, chargeAmount, null, null);
+ assertEquals(invoiceWithItems.getItems().size(), originalNumberOfItemsForInvoice + 1);
+ assertNull(invoiceWithItems.getItems().get(originalNumberOfItemsForInvoice).getBundleId());
+
+ // Verify the new invoice balance
+ final InvoiceJsonSimple adjustedInvoice = getInvoice(invoiceId);
+ final BigDecimal adjustedInvoiceBalance = originalInvoiceAmount.add(chargeAmount.setScale(2, RoundingMode.HALF_UP));
+ assertEquals(adjustedInvoice.getBalance().compareTo(adjustedInvoiceBalance), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testExternalChargeForBundleOnExistingInvoice() throws Exception {
+ final AccountJson accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+ // Get the invoices
+ final List<InvoiceJsonWithItems> invoices = getInvoicesWithItemsForAccount(accountJson.getAccountId());
+ // 2 invoices but look for the non zero dollar one
+ assertEquals(invoices.size(), 2);
+ final String invoiceId = invoices.get(1).getInvoiceId();
+ final BigDecimal originalInvoiceAmount = invoices.get(1).getAmount();
+ final int originalNumberOfItemsForInvoice = invoices.get(1).getItems().size();
+
+ // Post an external charge
+ final BigDecimal chargeAmount = BigDecimal.TEN;
+ final String bundleId = UUID.randomUUID().toString();
+ final InvoiceJsonWithItems invoiceWithItems = createExternalChargeForInvoice(accountJson.getAccountId(), invoiceId,
+ bundleId, chargeAmount, null, null);
assertEquals(invoiceWithItems.getItems().size(), originalNumberOfItemsForInvoice + 1);
+ assertEquals(invoiceWithItems.getItems().get(originalNumberOfItemsForInvoice).getBundleId(), bundleId);
// Verify the new invoice balance
final InvoiceJsonSimple adjustedInvoice = getInvoice(invoiceId);
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index b682877..1ab8f18 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -578,25 +578,25 @@ public class TestJaxrsBase extends ServerTestSuiteWithEmbeddedDB {
Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
}
- protected InvoiceJsonWithItems createExternalCharge(final String accountId, final BigDecimal amount, @Nullable final Currency currency,
- @Nullable final DateTime requestedDate) throws Exception {
- return doCreateExternalCharge(accountId, null, amount, currency, requestedDate, JaxrsResource.CHARGES_PATH);
+ protected InvoiceJsonWithItems createExternalCharge(final String accountId, final BigDecimal amount, @Nullable final String bundleId,
+ @Nullable final Currency currency, @Nullable final DateTime requestedDate) throws Exception {
+ return doCreateExternalCharge(accountId, null, bundleId, amount, currency, requestedDate, JaxrsResource.CHARGES_PATH);
}
- protected InvoiceJsonWithItems createExternalChargeForInvoice(final String accountId, final String invoiceId, final BigDecimal amount,
- @Nullable final Currency currency, @Nullable final DateTime requestedDate) throws Exception {
+ protected InvoiceJsonWithItems createExternalChargeForInvoice(final String accountId, final String invoiceId, @Nullable final String bundleId, final BigDecimal amount,
+ @Nullable final Currency currency, @Nullable final DateTime requestedDate) throws Exception {
final String uri = JaxrsResource.INVOICES_PATH + "/" + invoiceId + "/" + JaxrsResource.CHARGES;
- return doCreateExternalCharge(accountId, invoiceId, amount, currency, requestedDate, uri);
+ return doCreateExternalCharge(accountId, invoiceId, bundleId, amount, currency, requestedDate, uri);
}
- private InvoiceJsonWithItems doCreateExternalCharge(final String accountId, @Nullable final String invoiceId, @Nullable final BigDecimal amount,
+ private InvoiceJsonWithItems doCreateExternalCharge(final String accountId, @Nullable final String invoiceId, @Nullable final String bundleId, @Nullable final BigDecimal amount,
@Nullable final Currency currency, final DateTime requestedDate, final String uri) throws IOException {
final Map<String, String> queryParams = new HashMap<String, String>();
if (requestedDate != null) {
queryParams.put(JaxrsResource.QUERY_REQUESTED_DT, requestedDate.toDateTimeISO().toString());
}
- final InvoiceItemJsonSimple externalCharge = new InvoiceItemJsonSimple(null, invoiceId, accountId, null, null, null, null,
+ final InvoiceItemJsonSimple externalCharge = new InvoiceItemJsonSimple(null, invoiceId, accountId, bundleId, null, null, null,
null, null, null, amount, currency, null);
final String externalChargeJson = mapper.writeValueAsString(externalCharge);
final Response response = doPost(uri, externalChargeJson, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);