diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
index 17a7e68..fb7b805 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
@@ -108,6 +108,8 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
@BeforeMethod(groups = "slow")
public void setUp() throws Exception {
testInvoicePluginApi.additionalInvoiceItem = null;
+ testInvoicePluginApi.isAborted = false;
+ testInvoicePluginApi.rescheduleDate = null;
}
@Test(groups = "slow")
@@ -247,6 +249,108 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
}
@Test(groups = "slow")
+ public void testAborted() throws Exception {
+ testInvoicePluginApi.shouldAddTaxItem = false;
+
+ // We take april as it has 30 days (easier to play with BCD)
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDay(new LocalDate(2012, 4, 1));
+
+ final AccountData accountData = getAccountData(1);
+ final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
+ accountChecker.checkAccount(account.getId(), accountData, callContext);
+
+ // Create original subscription (Trial PHASE) -> $0 invoice
+ final DefaultEntitlement bpSubscription = createBaseEntitlementAndCheckForCompletion(account.getId(), "bundleKey", "Pistol", ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
+ invoiceChecker.checkInvoice(account.getId(), 1, callContext,
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 4, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
+ subscriptionChecker.checkSubscriptionCreated(bpSubscription.getId(), internalCallContext);
+
+ // Abort invoice runs
+ testInvoicePluginApi.isAborted = true;
+
+ // Move to Evergreen PHASE
+ busHandler.pushExpectedEvents(NextEvent.PHASE);
+ clock.addDays(30);
+ assertListenerStatus();
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext).size(), 1);
+
+ // Move one month (the plugin is still aborting invoices)
+ clock.addMonths(1);
+ assertListenerStatus();
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext).size(), 1);
+
+ // Re-enable invoicing
+ testInvoicePluginApi.isAborted = false;
+
+ // No notification, so by default, the account will not be re-invoiced
+ clock.addMonths(1);
+ assertListenerStatus();
+
+ // Trigger a manual invoice run
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+ invoiceUserApi.triggerInvoiceGeneration(account.getId(), clock.getUTCToday(), null, callContext);
+ assertListenerStatus();
+ invoiceChecker.checkInvoice(account.getId(), 2, callContext,
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 1), new LocalDate(2012, 7, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 1), new LocalDate(2012, 8, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")));
+
+ // Invoicing resumes
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+ clock.addMonths(1);
+ assertListenerStatus();
+ invoiceChecker.checkInvoice(account.getId(), 3, callContext,
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 8, 1), new LocalDate(2012, 9, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")));
+ }
+
+ @Test(groups = "slow")
+ public void testRescheduled() throws Exception {
+ testInvoicePluginApi.shouldAddTaxItem = false;
+
+ // We take april as it has 30 days (easier to play with BCD)
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDay(new LocalDate(2012, 4, 1));
+
+ final AccountData accountData = getAccountData(1);
+ final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
+ accountChecker.checkAccount(account.getId(), accountData, callContext);
+
+ // Create original subscription (Trial PHASE) -> $0 invoice
+ final DefaultEntitlement bpSubscription = createBaseEntitlementAndCheckForCompletion(account.getId(), "bundleKey", "Pistol", ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
+ invoiceChecker.checkInvoice(account.getId(), 1, callContext,
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 4, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
+ subscriptionChecker.checkSubscriptionCreated(bpSubscription.getId(), internalCallContext);
+
+ // Reschedule invoice generation
+ final DateTime utcNow = clock.getUTCNow();
+ testInvoicePluginApi.rescheduleDate = new DateTime(2012, 5, 2, utcNow.getHourOfDay(), utcNow.getMinuteOfHour(), utcNow.getSecondOfMinute(), DateTimeZone.UTC);
+
+ // Move to Evergreen PHASE
+ busHandler.pushExpectedEvents(NextEvent.PHASE);
+ clock.addDays(30);
+ assertListenerStatus();
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext).size(), 1);
+
+ // PHASE invoice has been rescheduled, reset rescheduleDate
+ testInvoicePluginApi.rescheduleDate = null;
+
+ // Move one day
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+ clock.addDays(1);
+ assertListenerStatus();
+ invoiceChecker.checkInvoice(account.getId(), 2, callContext,
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")));
+
+ // Invoicing resumes as expected
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+ clock.addDays(30);
+ assertListenerStatus();
+ invoiceChecker.checkInvoice(account.getId(), 3, callContext,
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 1), new LocalDate(2012, 7, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")));
+ }
+
+ @Test(groups = "slow")
public void testWithRetries() throws Exception {
// We take april as it has 30 days (easier to play with BCD)
// Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
@@ -404,10 +508,24 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
boolean shouldThrowException = false;
InvoiceItem additionalInvoiceItem;
+ boolean shouldAddTaxItem = false;
+ boolean isAborted = false;
+ DateTime rescheduleDate;
@Override
public PriorInvoiceResult priorCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
- return null;
+ return new PriorInvoiceResult() {
+
+ @Override
+ public boolean isAborted() {
+ return isAborted;
+ }
+
+ @Override
+ public DateTime getRescheduleDate() {
+ return rescheduleDate;
+ }
+ };
}
@Override
@@ -416,8 +534,10 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
throw new InvoicePluginApiRetryException();
} else if (additionalInvoiceItem != null) {
return ImmutableList.<InvoiceItem>of(additionalInvoiceItem);
- } else {
+ } else if (shouldAddTaxItem) {
return ImmutableList.<InvoiceItem>of(createTaxInvoiceItem(invoice));
+ } else {
+ return ImmutableList.<InvoiceItem>of();
}
}
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java
index d0cfcee..d9b37e5 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java
@@ -49,6 +49,7 @@ import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.util.callcontext.CallContext;
+import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -297,7 +298,7 @@ public class TestWithTaxItems extends TestIntegrationBase {
}
@Override
- public PriorInvoiceResult priorCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ public PriorInvoiceResult priorCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> pluginProperties) {
return null;
}
@@ -307,17 +308,34 @@ public class TestWithTaxItems extends TestIntegrationBase {
for (final TaxInvoiceItem item : taxItems) {
result.add(new TaxInvoiceItem(item.getId(), invoice.getId(), invoice.getAccountId(), item.getBundleId(), "Tax Item", item.getStartDate(), item.getAmount(), invoice.getCurrency()));
}
- taxItems.clear();
return result;
}
@Override
- public OnSuccessInvoiceResult onSuccessCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ public OnSuccessInvoiceResult onSuccessCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> pluginProperties) {
+ Assert.assertFalse(invoiceContext.isRescheduled());
+
+ final Invoice invoice = invoiceContext.getInvoice();
+ Assert.assertNotNull(invoice);
+ for (final TaxInvoiceItem taxInvoiceItem : taxItems) {
+ final InvoiceItem createdTaxInvoiceItem = Iterables.<InvoiceItem>find(invoice.getInvoiceItems(),
+ new Predicate<InvoiceItem>() {
+ @Override
+ public boolean apply(final InvoiceItem invoiceItem) {
+ return invoiceItem.getId().compareTo(taxInvoiceItem.getId()) == 0;
+ }
+ });
+ Assert.assertEquals(createdTaxInvoiceItem.getAccountId(), taxInvoiceItem.getAccountId());
+ }
+
+ reset();
+
return null;
}
@Override
- public OnFailureInvoiceResult onFailureCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ public OnFailureInvoiceResult onFailureCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> pluginProperties) {
+ Assert.fail();
return null;
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/notification/TestNextBillingDateNotificationKey.java b/invoice/src/test/java/org/killbill/billing/invoice/notification/TestNextBillingDateNotificationKey.java
index 0e6e941..9086ccb 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/notification/TestNextBillingDateNotificationKey.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/notification/TestNextBillingDateNotificationKey.java
@@ -45,9 +45,9 @@ public class TestNextBillingDateNotificationKey {
Assert.assertEquals(result.getUuidKey(), uuidKey);
Assert.assertEquals(result.getTargetDate().compareTo(targetDate), 0);
Assert.assertEquals(result.isDryRunForInvoiceNotification(), isDryRunForInvoiceNotification);
+ Assert.assertFalse(key.isRescheduled());
}
-
@Test(groups = "fast")
public void testBasicWithUUIDKeys() throws Exception {
@@ -56,13 +56,14 @@ public class TestNextBillingDateNotificationKey {
final DateTime targetDate = new DateTime();
final Boolean isDryRunForInvoiceNotification = Boolean.FALSE;
- final NextBillingDateNotificationKey key = new NextBillingDateNotificationKey(null, ImmutableList.of(uuidKey1, uuidKey2), targetDate, isDryRunForInvoiceNotification, false);
+ final NextBillingDateNotificationKey key = new NextBillingDateNotificationKey(null, ImmutableList.of(uuidKey1, uuidKey2), targetDate, isDryRunForInvoiceNotification, true);
final String json = mapper.writeValueAsString(key);
final NextBillingDateNotificationKey result = mapper.readValue(json, NextBillingDateNotificationKey.class);
Assert.assertNull(result.getUuidKey());
Assert.assertEquals(result.getTargetDate().compareTo(targetDate), 0);
Assert.assertEquals(result.isDryRunForInvoiceNotification(), isDryRunForInvoiceNotification);
+ Assert.assertTrue(key.isRescheduled());
Assert.assertNotNull(result.getUuidKeys());
Assert.assertTrue(Iterables.contains(result.getUuidKeys(), uuidKey1));
@@ -80,6 +81,5 @@ public class TestNextBillingDateNotificationKey {
// Compatibility mode : Although the uuidKeys is not in the json, we verify the getter return the right result
Assert.assertNotNull(result.getUuidKeys());
Assert.assertEquals(result.getUuidKeys().iterator().next().toString(), "a38c363f-b25b-4287-8ebc-55964e116d2f");
-
}
}