killbill-uncached

beatrix: initial set of tests for #893 Signed-off-by: Pierre-Alexandre

3/27/2018 4:04:37 AM

Details

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/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
index 71accaa..dcd487e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -651,8 +651,8 @@ public class InvoiceDispatcher {
                 commitInvoiceAndSetFutureNotifications(account, null, futureAccountNotifications, internalCallContext);
             }
 
-            if (success) {
-                final DefaultInvoice refreshedInvoice = new DefaultInvoice(invoiceDao.getById(invoice.getId(), internalCallContext));
+            if (isDryRun || success) {
+                final DefaultInvoice refreshedInvoice = isDryRun ? invoice : new DefaultInvoice(invoiceDao.getById(invoice.getId(), internalCallContext));
                 invoicePluginDispatcher.onSuccessCall(targetDate, refreshedInvoice, existingInvoices, isDryRun, isRescheduled, callContext, internalCallContext);
             } else {
                 invoicePluginDispatcher.onFailureCall(targetDate, invoice, existingInvoices, isDryRun, isRescheduled, callContext, internalCallContext);
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");
-
     }
 }