killbill-memoizeit

#611 - Added missing conditions to Json value - Added test

9/14/2016 11:26:54 AM

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/OverdueConditionJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/OverdueConditionJson.java
index 4f93cad..048a3c5 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/OverdueConditionJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/OverdueConditionJson.java
@@ -17,11 +17,13 @@
 
 package org.killbill.billing.jaxrs.json;
 
-import org.killbill.billing.catalog.api.TimeUnit;
+import java.math.BigDecimal;
+
 import org.killbill.billing.jaxrs.json.CatalogJson.DurationJson;
 import org.killbill.billing.overdue.api.OverdueCondition;
 import org.killbill.billing.overdue.config.DefaultDuration;
 import org.killbill.billing.overdue.config.DefaultOverdueCondition;
+import org.killbill.billing.payment.api.PaymentResponse;
 import org.killbill.billing.util.tag.ControlTagType;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
@@ -32,20 +34,33 @@ public class OverdueConditionJson {
     private final DurationJson timeSinceEarliestUnpaidInvoiceEqualsOrExceeds;
     private final ControlTagType controlTagInclusion;
     private final ControlTagType controlTagExclusion;
+    private final Integer numberOfUnpaidInvoicesEqualsOrExceeds;
+    private final PaymentResponse[] responseForLastFailedPayment;
+    private final BigDecimal totalUnpaidInvoiceBalanceEqualsOrExceeds;
+
 
     @JsonCreator
     public OverdueConditionJson(@JsonProperty("timeSinceEarliestUnpaidInvoiceEqualsOrExceeds") final DurationJson timeSinceEarliestUnpaidInvoiceEqualsOrExceeds,
                                 @JsonProperty("controlTagInclusion") final ControlTagType controlTagInclusion,
-                                @JsonProperty("controlTagExclusion") final ControlTagType controlTagExclusion) {
+                                @JsonProperty("controlTagExclusion") final ControlTagType controlTagExclusion,
+                                @JsonProperty("numberOfUnpaidInvoicesEqualsOrExceeds") final Integer numberOfUnpaidInvoicesEqualsOrExceeds,
+                                @JsonProperty("responseForLastFailedPayment") final PaymentResponse[] responseForLastFailedPayment,
+                                @JsonProperty("totalUnpaidInvoiceBalanceEqualsOrExceeds") final BigDecimal totalUnpaidInvoiceBalanceEqualsOrExceeds) {
         this.timeSinceEarliestUnpaidInvoiceEqualsOrExceeds = timeSinceEarliestUnpaidInvoiceEqualsOrExceeds;
         this.controlTagInclusion = controlTagInclusion;
         this.controlTagExclusion = controlTagExclusion;
+        this.numberOfUnpaidInvoicesEqualsOrExceeds = numberOfUnpaidInvoicesEqualsOrExceeds;
+        this.responseForLastFailedPayment = responseForLastFailedPayment;
+        this.totalUnpaidInvoiceBalanceEqualsOrExceeds = totalUnpaidInvoiceBalanceEqualsOrExceeds;
     }
 
     public OverdueConditionJson(final OverdueCondition overdueCondition) {
         this.timeSinceEarliestUnpaidInvoiceEqualsOrExceeds = new DurationJson(overdueCondition.getTimeSinceEarliestUnpaidInvoiceEqualsOrExceeds());
         this.controlTagInclusion = overdueCondition.getInclusionControlTagType();
         this.controlTagExclusion = overdueCondition.getExclusionControlTagType();
+        this.numberOfUnpaidInvoicesEqualsOrExceeds = overdueCondition.getNumberOfUnpaidInvoicesEqualsOrExceeds();
+        this.responseForLastFailedPayment = overdueCondition.getResponseForLastFailedPaymentIn();
+        this.totalUnpaidInvoiceBalanceEqualsOrExceeds = overdueCondition.getTotalUnpaidInvoiceBalanceEqualsOrExceeds();
     }
 
     public DurationJson getTimeSinceEarliestUnpaidInvoiceEqualsOrExceeds() {
@@ -60,12 +75,27 @@ public class OverdueConditionJson {
         return controlTagExclusion;
     }
 
+    public Integer getNumberOfUnpaidInvoicesEqualsOrExceeds() {
+        return numberOfUnpaidInvoicesEqualsOrExceeds;
+    }
+
+    public PaymentResponse[] getResponseForLastFailedPayment() {
+        return responseForLastFailedPayment;
+    }
+
+    public BigDecimal getTotalUnpaidInvoiceBalanceEqualsOrExceeds() {
+        return totalUnpaidInvoiceBalanceEqualsOrExceeds;
+    }
+
     @Override
     public String toString() {
         return "OverdueConditionJson{" +
                "timeSinceEarliestUnpaidInvoiceEqualsOrExceeds=" + timeSinceEarliestUnpaidInvoiceEqualsOrExceeds +
                ", controlTagInclusion=" + controlTagInclusion +
                ", controlTagExclusion=" + controlTagExclusion +
+               ", numberOfUnpaidInvoicesEqualsOrExceeds=" + numberOfUnpaidInvoicesEqualsOrExceeds +
+               ", responseForLastFailedPayment=" + responseForLastFailedPayment +
+               ", totalUnpaidInvoiceBalanceEqualsOrExceeds=" + totalUnpaidInvoiceBalanceEqualsOrExceeds +
                '}';
     }
 
@@ -86,7 +116,16 @@ public class OverdueConditionJson {
         if (controlTagInclusion != that.controlTagInclusion) {
             return false;
         }
-        return controlTagExclusion == that.controlTagExclusion;
+        if (controlTagExclusion != that.controlTagExclusion) {
+            return false;
+        }
+        if (numberOfUnpaidInvoicesEqualsOrExceeds != that.numberOfUnpaidInvoicesEqualsOrExceeds) {
+            return false;
+        }
+        if (responseForLastFailedPayment != that.responseForLastFailedPayment) {
+            return false;
+        }
+        return totalUnpaidInvoiceBalanceEqualsOrExceeds == that.totalUnpaidInvoiceBalanceEqualsOrExceeds;
 
     }
 
@@ -95,6 +134,9 @@ public class OverdueConditionJson {
         int result = timeSinceEarliestUnpaidInvoiceEqualsOrExceeds != null ? timeSinceEarliestUnpaidInvoiceEqualsOrExceeds.hashCode() : 0;
         result = 31 * result + (controlTagInclusion != null ? controlTagInclusion.hashCode() : 0);
         result = 31 * result + (controlTagExclusion != null ? controlTagExclusion.hashCode() : 0);
+        result = 31 * result + (numberOfUnpaidInvoicesEqualsOrExceeds != null ? numberOfUnpaidInvoicesEqualsOrExceeds.hashCode() : 0);
+        result = 31 * result + (responseForLastFailedPayment != null ? responseForLastFailedPayment.hashCode() : 0);
+        result = 31 * result + (totalUnpaidInvoiceBalanceEqualsOrExceeds != null ? totalUnpaidInvoiceBalanceEqualsOrExceeds.hashCode() : 0);
         return result;
     }
 
@@ -105,6 +147,10 @@ public class OverdueConditionJson {
         }
         result.setControlTagInclusion(input.getControlTagInclusion());
         result.setControlTagExclusion(input.getControlTagExclusion());
+        result.setNumberOfUnpaidInvoicesEqualsOrExceeds(input.getNumberOfUnpaidInvoicesEqualsOrExceeds());
+        result.setResponseForLastFailedPayment(input.getResponseForLastFailedPayment());
+        result.setTotalUnpaidInvoiceBalanceEqualsOrExceeds(input.getTotalUnpaidInvoiceBalanceEqualsOrExceeds());
+
         return result;
     }
 }
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 f2f8f2c..dccf9c2 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
@@ -22,11 +22,11 @@ import java.math.BigDecimal;
 import java.util.Comparator;
 import java.util.List;
 
+import org.killbill.billing.client.KillBillClientException;
 import org.killbill.billing.client.model.Account;
 import org.killbill.billing.client.model.Invoice;
 import org.killbill.billing.client.model.InvoicePayment;
 import org.killbill.billing.client.model.Invoices;
-import org.killbill.billing.client.model.Payment;
 import org.killbill.billing.client.model.Tags;
 import org.killbill.billing.util.tag.ControlTagType;
 import org.testng.Assert;
@@ -42,9 +42,9 @@ public class TestOverdue extends TestJaxrsBase {
     @Test(groups = "slow", description = "Upload and retrieve a per tenant overdue config")
     public void testMultiTenantOverdueConfig() throws Exception {
         final String overdueConfigPath = Resources.getResource("overdue.xml").getPath();
-        killBillClient.uploadXMLOverdueConfig(overdueConfigPath, createdBy, reason, comment);
+        killBillClient.uploadXMLOverdueConfig(overdueConfigPath, requestOptions);
 
-        final String overdueConfig = killBillClient.getXMLOverdueConfig();
+        final String overdueConfig = killBillClient.getXMLOverdueConfig(requestOptions);
         Assert.assertNotNull(overdueConfig);
     }
 
@@ -54,51 +54,35 @@ public class TestOverdue extends TestJaxrsBase {
         final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
 
         // Get the invoices
-        final List<Invoice> invoices = killBillClient.getInvoicesForAccount(accountJson.getAccountId());
+        final List<Invoice> invoices = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
         // 2 invoices but look for the non zero dollar one
         assertEquals(invoices.size(), 2);
 
         // We're still clear - see the configuration
-        Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId()).getIsClearState());
+        Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
 
         clock.addDays(30);
         crappyWaitForLackOfProperSynchonization();
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId()).getName(), "OD1");
+        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD1");
 
         clock.addDays(10);
         crappyWaitForLackOfProperSynchonization();
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId()).getName(), "OD2");
+        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD2");
 
         clock.addDays(10);
         crappyWaitForLackOfProperSynchonization();
-        Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId()).getName(), "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).
-        final Invoices invoicesForAccount = killBillClient.getInvoicesForAccount(accountJson.getAccountId());
-        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, createdBy, reason, comment);
-            }
-        }
+        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()).getIsClearState());
+        Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
     }
 
     @Test(groups = "slow", description = "Allow overdue condition by control tag defined in overdue config xml file")
@@ -179,4 +163,128 @@ 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);
+            }
+        }
+    }
 }
diff --git a/profiles/killbill/src/test/resources/overdueWithNumberOfUnpaidInvoicesCondition.xml b/profiles/killbill/src/test/resources/overdueWithNumberOfUnpaidInvoicesCondition.xml
new file mode 100644
index 0000000..f2d2572
--- /dev/null
+++ b/profiles/killbill/src/test/resources/overdueWithNumberOfUnpaidInvoicesCondition.xml
@@ -0,0 +1,54 @@
+<!--
+  ~ Copyright 2014-2016 Groupon, Inc
+  ~ Copyright 2014-2016 The Billing Project, LLC
+  ~
+  ~ The Billing Project licenses this file to you under the Apache License, version 2.0
+  ~ (the "License"); you may not use this file except in compliance with the
+  ~ License.  You may obtain a copy of the License at:
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+  ~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+  ~ License for the specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<overdueConfig>
+   <accountOverdueStates>
+       <state name="OD3">
+           <condition>
+               <numberOfUnpaidInvoicesEqualsOrExceeds>5</numberOfUnpaidInvoicesEqualsOrExceeds>
+           </condition>
+           <externalMessage>Reached OD3</externalMessage>
+           <blockChanges>true</blockChanges>
+           <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>
+           <autoReevaluationInterval>
+               <unit>DAYS</unit><number>5</number>
+           </autoReevaluationInterval>
+       </state>
+       <state name="OD2">
+           <condition>
+               <numberOfUnpaidInvoicesEqualsOrExceeds>3</numberOfUnpaidInvoicesEqualsOrExceeds>
+           </condition>
+           <externalMessage>Reached OD2</externalMessage>
+           <blockChanges>true</blockChanges>
+           <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>
+           <autoReevaluationInterval>
+               <unit>DAYS</unit><number>5</number>
+           </autoReevaluationInterval>
+       </state>
+       <state name="OD1">
+           <condition>
+               <numberOfUnpaidInvoicesEqualsOrExceeds>2</numberOfUnpaidInvoicesEqualsOrExceeds>
+           </condition>
+           <externalMessage>Reached OD1</externalMessage>
+           <blockChanges>true</blockChanges>
+           <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>
+           <autoReevaluationInterval>
+               <unit>DAYS</unit><number>5</number>
+           </autoReevaluationInterval>
+       </state>
+   </accountOverdueStates>
+</overdueConfig>
diff --git a/profiles/killbill/src/test/resources/overdueWithTotalUnpaidInvoiceBalanceCondition.xml b/profiles/killbill/src/test/resources/overdueWithTotalUnpaidInvoiceBalanceCondition.xml
new file mode 100644
index 0000000..3012283
--- /dev/null
+++ b/profiles/killbill/src/test/resources/overdueWithTotalUnpaidInvoiceBalanceCondition.xml
@@ -0,0 +1,54 @@
+<!--
+  ~ Copyright 2014-2016 Groupon, Inc
+  ~ Copyright 2014-2016 The Billing Project, LLC
+  ~
+  ~ The Billing Project licenses this file to you under the Apache License, version 2.0
+  ~ (the "License"); you may not use this file except in compliance with the
+  ~ License.  You may obtain a copy of the License at:
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+  ~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+  ~ License for the specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<overdueConfig>
+   <accountOverdueStates>
+       <state name="OD3">
+           <condition>
+               <totalUnpaidInvoiceBalanceEqualsOrExceeds>1200.0</totalUnpaidInvoiceBalanceEqualsOrExceeds>
+           </condition>
+           <externalMessage>Reached OD3</externalMessage>
+           <blockChanges>true</blockChanges>
+           <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>
+           <autoReevaluationInterval>
+               <unit>DAYS</unit><number>5</number>
+           </autoReevaluationInterval>
+       </state>
+       <state name="OD2">
+           <condition>
+               <totalUnpaidInvoiceBalanceEqualsOrExceeds>600.0</totalUnpaidInvoiceBalanceEqualsOrExceeds>
+           </condition>
+           <externalMessage>Reached OD2</externalMessage>
+           <blockChanges>true</blockChanges>
+           <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>
+           <autoReevaluationInterval>
+               <unit>DAYS</unit><number>5</number>
+           </autoReevaluationInterval>
+       </state>
+       <state name="OD1">
+           <condition>
+               <totalUnpaidInvoiceBalanceEqualsOrExceeds>260.0</totalUnpaidInvoiceBalanceEqualsOrExceeds>
+           </condition>
+           <externalMessage>Reached OD1</externalMessage>
+           <blockChanges>true</blockChanges>
+           <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>
+           <autoReevaluationInterval>
+               <unit>DAYS</unit><number>5</number>
+           </autoReevaluationInterval>
+       </state>
+   </accountOverdueStates>
+</overdueConfig>