killbill-memoizeit

Details

diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index beb7246..7b6b8da 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -46,13 +46,16 @@ import org.killbill.billing.invoice.api.InvoiceItem;
 import org.killbill.billing.invoice.api.InvoiceItemType;
 import org.killbill.billing.invoice.api.InvoicePayment;
 import org.killbill.billing.invoice.model.ExternalChargeInvoiceItem;
+import org.killbill.billing.overdue.config.DefaultOverdueConfig;
 import org.killbill.billing.overdue.wrapper.OverdueWrapper;
 import org.killbill.billing.payment.api.Payment;
 import org.killbill.billing.payment.api.PluginProperty;
+import org.killbill.xmlloader.XMLLoader;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.io.Resources;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
@@ -949,6 +952,151 @@ public class TestOverdueIntegration extends TestOverdueBase {
         checkODState(OverdueWrapper.CLEAR_STATE_NAME);
     }
 
+    @Test(groups = "slow", description = "Test overdue state with number of unpaid invoices condition")
+    public void testOverdueStateWithNumberOfUnpaidInvoicesCondition() throws Exception {
+        // 2012-05-01T00:03:42.000Z
+        clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
+
+        final DefaultOverdueConfig config = XMLLoader.getObjectFromString(Resources.getResource("overdueWithNumberOfUnpaidInvoicesCondition.xml").toExternalForm(), DefaultOverdueConfig.class);
+        overdueConfigCache.loadDefaultOverdueConfig(config);
+
+        setupAccount();
+
+        paymentPlugin.makeAllInvoicesFailWithError(true);
+
+        createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE,
+                                                   term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
+
+        // 2012-05-31 => DAY 30 have to get out of trial before first payment
+        addMonthsAndCheckForCompletion(1, NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+        // Verify that number of unpaid invoices is 1
+        Assert.assertEquals(invoiceUserApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext).size(), 1);
+        // Should still be in clear state
+        checkODState(OverdueWrapper.CLEAR_STATE_NAME);
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.BLOCK, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+        // Verify that number of unpaid invoices is 2
+        Assert.assertEquals(invoiceUserApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext).size(), 2);
+        // Now we should be in OD1
+        checkODState("OD1");
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.BLOCK, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+        // Verify that number of unpaid invoices is 3
+        Assert.assertEquals(invoiceUserApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext).size(), 3);
+        // Now we should be in OD2
+        checkODState("OD2");
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+        // Verify that number of unpaid invoices is 4
+        Assert.assertEquals(invoiceUserApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext).size(), 4);
+        // We should still be in OD2
+        checkODState("OD2");
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR, NextEvent.TAG,  NextEvent.BLOCK);
+        // Verify that number of unpaid invoices is 5
+        Assert.assertEquals(invoiceUserApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext).size(), 5);
+        // Now we should be in OD3
+        checkODState("OD3");
+
+        // Get all unpaid invoices and pay them to clear the overdue state
+        paymentPlugin.makeAllInvoicesFailWithError(false);
+        List<Invoice> unpaidInvoices = getUnpaidInvoicesOrderFromRecent();
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(0), NextEvent.BLOCK, NextEvent.TAG, NextEvent.NULL_INVOICE, NextEvent.NULL_INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(1), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(2), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.BLOCK);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(3), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.BLOCK);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(4), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+
+        // We should be clear now
+        checkODState(OverdueWrapper.CLEAR_STATE_NAME);
+    }
+
+    @Test(groups = "slow", description = "Test overdue state with total unpaid invoice balance condition")
+    public void testOverdueStateWithTotalUnpaidInvoiceBalanceCondition() throws Exception {
+        // 2012-05-01T00:03:42.000Z
+        clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
+
+        final DefaultOverdueConfig config = XMLLoader.getObjectFromString(Resources.getResource("overdueWithTotalUnpaidInvoiceBalanceCondition.xml").toExternalForm(), DefaultOverdueConfig.class);
+        overdueConfigCache.loadDefaultOverdueConfig(config);
+
+        setupAccount();
+
+        paymentPlugin.makeAllInvoicesFailWithError(true);
+
+        createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE,
+                                                   term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
+
+        // 2012-05-31 => DAY 30 have to get out of trial before first payment
+        addMonthsAndCheckForCompletion(1, NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+
+        // Amount balance should be USD 249.95
+        assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(BigDecimal.valueOf(249.95)), 0);
+        // Should still be in clear state
+        checkODState(OverdueWrapper.CLEAR_STATE_NAME);
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.BLOCK, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+        // Amount balance should be USD 499.90
+        assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(BigDecimal.valueOf(499.90)), 0);
+        // Now we should be in OD1
+        checkODState("OD1");
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.BLOCK, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+        // Amount balance should be USD 749.85
+        assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(BigDecimal.valueOf(749.85)), 0);
+        // Now we should be in OD2
+        checkODState("OD2");
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
+        // Amount balance should be USD 999.80
+        assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(BigDecimal.valueOf(999.80)), 0);
+        // We should still be in OD2
+        checkODState("OD2");
+
+        // Add 1 month
+        addMonthsAndCheckForCompletion(1, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR,
+                                       NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR, NextEvent.TAG,  NextEvent.BLOCK);
+        // Amount balance should be USD 1249.75
+        assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(BigDecimal.valueOf(1249.75)), 0);
+        // Now we should be in OD3
+        checkODState("OD3");
+
+        // Get all unpaid invoices and pay them to clear the overdue state
+        paymentPlugin.makeAllInvoicesFailWithError(false);
+        List<Invoice> unpaidInvoices = getUnpaidInvoicesOrderFromRecent();
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(0), NextEvent.BLOCK, NextEvent.TAG, NextEvent.NULL_INVOICE, NextEvent.NULL_INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(1), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(2), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.BLOCK);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(3), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.BLOCK);
+        createPaymentAndCheckForCompletion(account, unpaidInvoices.get(4), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+
+        // We should be clear now
+        checkODState(OverdueWrapper.CLEAR_STATE_NAME);
+    }
+
     private void allowPaymentsAndResetOverdueToClearByPayingAllUnpaidInvoices(final boolean extraPayment) {
 
         // Reset plugin so payments should now succeed
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
index dccf9c2..6b13996 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
@@ -76,7 +76,23 @@ public class TestOverdue extends TestJaxrsBase {
         // Post external payments, paying the most recent invoice first: this is to avoid a race condition where
         // a refresh overdue notification kicks in after the first payment, which makes the account goes CLEAR and
         // triggers an AUTO_INVOICE_OFF tag removal (hence adjustment of the other invoices balance).
-        postExternalPayments(accountJson);
+        final Invoices invoicesForAccount = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
+        final List<Invoice> mostRecentInvoiceFirst = Ordering.<Invoice>from(new Comparator<Invoice>() {
+            @Override
+            public int compare(final Invoice invoice1, final Invoice invoice2) {
+                return invoice1.getInvoiceDate().compareTo(invoice2.getInvoiceDate());
+            }
+        }).reverse().sortedCopy(invoicesForAccount);
+        for (final Invoice invoice : mostRecentInvoiceFirst) {
+            if (invoice.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+
+                final InvoicePayment invoicePayment = new InvoicePayment();
+                invoicePayment.setPurchasedAmount(invoice.getAmount());
+                invoicePayment.setAccountId(accountJson.getAccountId());
+                invoicePayment.setTargetInvoiceId(invoice.getInvoiceId());
+                killBillClient.createInvoicePayment(invoicePayment, true, requestOptions);
+            }
+        }
 
         // Wait a bit for overdue to pick up the payment events...
         crappyWaitForLackOfProperSynchonization();
@@ -163,128 +179,4 @@ public class TestOverdue extends TestJaxrsBase {
         // This account is expected to move to OD1 state because it matches with exclusion controlTag defined
         Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJsonNoTag.getAccountId(), requestOptions).getName(), "OD1");
     }
-
-    @Test(groups = "slow", description = "Allow overdue condition by number of unpaid invoices defined in overdue config xml file")
-    public void testOverdueStatusWithNumberOfUnpaidInvoicesCondition() throws Exception {
-        final String overdueConfigPath = Resources.getResource("overdueWithNumberOfUnpaidInvoicesCondition.xml").getPath();
-        killBillClient.uploadXMLOverdueConfig(overdueConfigPath, requestOptions);
-
-        // Create an account without a payment method
-        final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
-
-        // Get the invoices
-        // 2 invoices but look for the non zero dollar one
-        assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions).size(), 2);
-
-        // We're still clear - see the configuration
-        Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // 3 invoices, 2 unpaid, must be inside OD1
-        assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions).size(), 3);
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD1");
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // 4 invoices, 3 unpaid, must be inside OD2
-        assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions).size(), 4);
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD2");
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // 5 invoices, 4 unpaid, must be still in OD2
-        assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions).size(), 5);
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD2");
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // 6 invoices, 5 unpaid, must be inside OD3
-        assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions).size(), 6);
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD3");
-
-        // Post external payments, paying the most recent invoice first: this is to avoid a race condition where
-        // a refresh overdue notification kicks in after the first payment, which makes the account goes CLEAR and
-        // triggers an AUTO_INVOICE_OFF tag removal (hence adjustment of the other invoices balance).
-        postExternalPayments(accountJson);
-
-        // Wait a bit for overdue to pick up the payment events...
-        crappyWaitForLackOfProperSynchonization();
-
-        // Verify we're in clear state
-        Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
-    }
-
-    @Test(groups = "slow", description = "Allow overdue condition by total unpaid invoice balance defined in overdue config xml file")
-    public void testOverdueStatusWithTotalUnpaidInvoiceBalanceCondition() throws Exception {
-        final String overdueConfigPath = Resources.getResource("overdueWithTotalUnpaidInvoiceBalanceCondition.xml").getPath();
-        killBillClient.uploadXMLOverdueConfig(overdueConfigPath, requestOptions);
-
-        // Create an account without a payment method
-        final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
-
-        // Amount balance should be USD 249.95
-        assertEquals(killBillClient.getAccount(accountJson.getAccountId(), true, false, requestOptions).getAccountBalance().compareTo(BigDecimal.valueOf(249.95)), 0);
-        // We're still clear - see the configuration
-        Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // Amount balance should be USD 499.90
-        assertEquals(killBillClient.getAccount(accountJson.getAccountId(), true, false, requestOptions).getAccountBalance().compareTo(BigDecimal.valueOf(499.90)), 0);
-        // State must be inside OD1
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD1");
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // Amount balance should be USD 749.85
-        assertEquals(killBillClient.getAccount(accountJson.getAccountId(), true, false, requestOptions).getAccountBalance().compareTo(BigDecimal.valueOf(749.85)), 0);
-        // State must be inside OD2
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD2");
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // Amount balance should be USD 999.80
-        assertEquals(killBillClient.getAccount(accountJson.getAccountId(), true, false, requestOptions).getAccountBalance().compareTo(BigDecimal.valueOf(999.80)), 0);
-        // State must be still OD2
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD2");
-
-        clock.addMonths(1);
-        crappyWaitForLackOfProperSynchonization();
-        // Amount balance should be USD 1249.75
-        assertEquals(killBillClient.getAccount(accountJson.getAccountId(), true, false, requestOptions).getAccountBalance().compareTo(BigDecimal.valueOf(1249.75)), 0);
-        // State must be inside OD3
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD3");
-
-        // Post external payments, paying the most recent invoice first: this is to avoid a race condition where
-        // a refresh overdue notification kicks in after the first payment, which makes the account goes CLEAR and
-        // triggers an AUTO_INVOICE_OFF tag removal (hence adjustment of the other invoices balance).
-        postExternalPayments(accountJson);
-
-        // Wait a bit for overdue to pick up the payment events...
-        crappyWaitForLackOfProperSynchonization();
-
-        // Verify we're in clear state
-        Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
-    }
-
-    private void postExternalPayments(final Account accountJson) throws KillBillClientException {
-        final Invoices invoicesForAccount = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
-        final List<Invoice> mostRecentInvoiceFirst = Ordering.<Invoice>from(new Comparator<Invoice>() {
-            @Override
-            public int compare(final Invoice invoice1, final Invoice invoice2) {
-                return invoice1.getInvoiceDate().compareTo(invoice2.getInvoiceDate());
-            }
-        }).reverse().sortedCopy(invoicesForAccount);
-        for (final Invoice invoice : mostRecentInvoiceFirst) {
-            if (invoice.getBalance().compareTo(BigDecimal.ZERO) > 0) {
-
-                final InvoicePayment invoicePayment = new InvoicePayment();
-                invoicePayment.setPurchasedAmount(invoice.getAmount());
-                invoicePayment.setAccountId(accountJson.getAccountId());
-                invoicePayment.setTargetInvoiceId(invoice.getInvoiceId());
-                killBillClient.createInvoicePayment(invoicePayment, true, requestOptions);
-            }
-        }
-    }
 }