Details
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/calculator/BillingStateCalculator.java b/overdue/src/main/java/org/killbill/billing/overdue/calculator/BillingStateCalculator.java
index 7d594fc..d1bec8d 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/calculator/BillingStateCalculator.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/calculator/BillingStateCalculator.java
@@ -19,6 +19,7 @@ package org.killbill.billing.overdue.calculator;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Comparator;
+import java.util.List;
import java.util.NoSuchElementException;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -26,6 +27,7 @@ import java.util.UUID;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
+import org.killbill.billing.ObjectType;
import org.killbill.billing.account.api.ImmutableAccountData;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.invoice.api.Invoice;
@@ -33,6 +35,7 @@ import org.killbill.billing.invoice.api.InvoiceInternalApi;
import org.killbill.billing.overdue.config.api.BillingState;
import org.killbill.billing.overdue.config.api.OverdueException;
import org.killbill.billing.payment.api.PaymentResponse;
+import org.killbill.billing.tag.TagInternalApi;
import org.killbill.billing.util.tag.Tag;
import org.killbill.clock.Clock;
@@ -41,6 +44,7 @@ import com.google.inject.Inject;
public class BillingStateCalculator {
private final InvoiceInternalApi invoiceApi;
+ private final TagInternalApi tagApi;
private final Clock clock;
protected class InvoiceDateComparator implements Comparator<Invoice> {
@@ -57,9 +61,10 @@ public class BillingStateCalculator {
}
@Inject
- public BillingStateCalculator(final InvoiceInternalApi invoiceApi, final Clock clock) {
+ public BillingStateCalculator(final InvoiceInternalApi invoiceApi, final Clock clock, final TagInternalApi tagApi) {
this.invoiceApi = invoiceApi;
this.clock = clock;
+ this.tagApi = tagApi;
}
public BillingState calculateBillingState(final ImmutableAccountData account, final InternalTenantContext context) throws OverdueException {
@@ -75,7 +80,8 @@ public class BillingStateCalculator {
idOfEarliestUnpaidInvoice = invoice.getId();
}
final PaymentResponse responseForLastFailedPayment = PaymentResponse.INSUFFICIENT_FUNDS; //TODO MDW
- final Tag[] tags = new Tag[]{}; //TODO MDW
+ final List<Tag> accountTags = tagApi.getTags(account.getId(), ObjectType.ACCOUNT, context);
+ final Tag[] tags = accountTags.toArray(new Tag[accountTags.size()]);
return new BillingState(account.getId(), numberOfUnpaidInvoices, unpaidInvoiceBalance, dateOfEarliestUnpaidInvoice, account.getTimeZone(), idOfEarliestUnpaidInvoice, responseForLastFailedPayment, tags);
}
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java
index ee30861..3cca103 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java
@@ -57,8 +57,11 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
@XmlElement(required = false, name = "response")
private PaymentResponse[] responseForLastFailedPayment;
- @XmlElement(required = false, name = "controlTag")
- private ControlTagType controlTag;
+ @XmlElement(required = false, name = "controlTagInclusion")
+ private ControlTagType controlTagInclusion;
+
+ @XmlElement(required = false, name = "controlTagExclusion")
+ private ControlTagType controlTagExclusion;
@Override
public boolean evaluate(final BillingState state, final LocalDate date) {
@@ -73,7 +76,8 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
(timeSinceEarliestUnpaidInvoiceEqualsOrExceeds == null ||
(unpaidInvoiceTriggerDate != null && !unpaidInvoiceTriggerDate.isAfter(date))) &&
(responseForLastFailedPayment == null || responseIsIn(state.getResponseForLastFailedPayment(), responseForLastFailedPayment)) &&
- (controlTag == null || isTagIn(controlTag, state.getTags()));
+ (controlTagInclusion == null || isTagIn(controlTagInclusion, state.getTags())) &&
+ (controlTagExclusion == null || isTagNotIn(controlTagExclusion, state.getTags()));
}
private boolean responseIsIn(final PaymentResponse actualResponse,
@@ -95,6 +99,15 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
return false;
}
+ private boolean isTagNotIn(final ControlTagType tagType, final Tag[] tags) {
+ for (final Tag t : tags) {
+ if (t.getTagDefinitionId().equals(tagType.getId())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
@Override
public ValidationErrors validate(final DefaultOverdueConfig root,
final ValidationErrors errors) {
@@ -135,8 +148,13 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
}
@Override
- public ControlTagType getControlTagType() {
- return controlTag;
+ public ControlTagType getInclusionControlTagType() {
+ return controlTagInclusion;
+ }
+
+ @Override
+ public ControlTagType getExclusionControlTagType() {
+ return controlTagExclusion;
}
@Override
@@ -146,7 +164,8 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
sb.append(", totalUnpaidInvoiceBalanceEqualsOrExceeds=").append(totalUnpaidInvoiceBalanceEqualsOrExceeds);
sb.append(", timeSinceEarliestUnpaidInvoiceEqualsOrExceeds=").append(timeSinceEarliestUnpaidInvoiceEqualsOrExceeds);
sb.append(", responseForLastFailedPayment=").append(Arrays.toString(responseForLastFailedPayment));
- sb.append(", controlTag=").append(controlTag);
+ sb.append(", controlTagInclusion=").append(controlTagInclusion);
+ sb.append(", controlTagExclusion=").append(controlTagExclusion);
sb.append('}');
return sb.toString();
}
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/calculator/TestBillingStateCalculator.java b/overdue/src/test/java/org/killbill/billing/overdue/calculator/TestBillingStateCalculator.java
index d8f7b9d..a5db764 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/calculator/TestBillingStateCalculator.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/calculator/TestBillingStateCalculator.java
@@ -60,7 +60,7 @@ public class TestBillingStateCalculator extends OverdueTestSuiteNoDB {
Mockito.when(invoiceApi.getUnpaidInvoicesByAccountId(Mockito.<UUID>any(), Mockito.<LocalDate>any(), Mockito.<InternalTenantContext>any())).thenReturn(invoices);
- return new BillingStateCalculator(invoiceApi, clock) {
+ return new BillingStateCalculator(invoiceApi, clock, tagInternalApi) {
@Override
public BillingState calculateBillingState(final ImmutableAccountData overdueable,
final InternalTenantContext context) {
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/config/TestCondition.java b/overdue/src/test/java/org/killbill/billing/overdue/config/TestCondition.java
index 1e6ee8c..99efef6 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/config/TestCondition.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/config/TestCondition.java
@@ -139,7 +139,7 @@ public class TestCondition extends OverdueTestSuiteNoDB {
public void testHasControlTag() throws Exception {
final String xml =
"<condition>" +
- " <controlTag>OVERDUE_ENFORCEMENT_OFF</controlTag>" +
+ " <controlTagInclusion>OVERDUE_ENFORCEMENT_OFF</controlTagInclusion>" +
"</condition>";
final InputStream is = new ByteArrayInputStream(xml.getBytes());
final MockCondition c = XMLLoader.getObjectFromStreamNoValidation(is, MockCondition.class);
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/glue/TestOverdueModule.java b/overdue/src/test/java/org/killbill/billing/overdue/glue/TestOverdueModule.java
index 39ead21..8d603af 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/glue/TestOverdueModule.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/glue/TestOverdueModule.java
@@ -21,7 +21,6 @@ package org.killbill.billing.overdue.glue;
import java.util.List;
import java.util.UUID;
-import org.joda.time.DateTime;
import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.entitlement.api.BlockingState;
@@ -49,8 +48,6 @@ import org.killbill.billing.util.glue.CallContextModule;
import org.killbill.billing.util.glue.ConfigModule;
import org.killbill.billing.util.glue.CustomFieldModule;
import org.killbill.billing.util.glue.MemoryGlobalLockerModule;
-import org.killbill.clock.Clock;
-import org.killbill.clock.ClockMock;
import com.google.inject.name.Names;
@@ -73,7 +70,7 @@ public class TestOverdueModule extends DefaultOverdueModule {
install(new MockAccountModule(configSource));
install(new MockEntitlementModule(configSource, new ApplicatorBlockingApi()));
install(new MockInvoiceModule(configSource));
- install(new MockTagModule(configSource));
+ install(new MockTagModule(configSource, true));
install(new TemplateModule(configSource));
install(new MockTenantModule(configSource));
install(new MemoryGlobalLockerModule(configSource));
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
index 0e1f5e5..d7d6462 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
@@ -37,6 +37,7 @@ import org.killbill.billing.overdue.notification.OverdueNotifier;
import org.killbill.billing.overdue.notification.OverduePoster;
import org.killbill.billing.overdue.service.DefaultOverdueService;
import org.killbill.billing.overdue.wrapper.OverdueWrapperFactory;
+import org.killbill.billing.tag.TagInternalApi;
import org.killbill.billing.tenant.api.TenantInternalApi;
import org.killbill.billing.util.cache.CacheControllerDispatcher;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
@@ -102,6 +103,8 @@ public abstract class OverdueTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
protected OverdueCacheInvalidationCallback cacheInvalidationCallback;
@Inject
protected TenantInternalApi tenantInternalApi;
+ @Inject
+ protected TagInternalApi tagInternalApi;
@BeforeClass(groups = "fast")
protected void beforeClass() throws Exception {
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/TestOverdueHelper.java b/overdue/src/test/java/org/killbill/billing/overdue/TestOverdueHelper.java
index 3f09ee6..f805d5d 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/TestOverdueHelper.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/TestOverdueHelper.java
@@ -25,22 +25,24 @@ import java.util.UUID;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
+import org.killbill.billing.ObjectType;
+import org.killbill.billing.account.api.AccountApiException;
+import org.killbill.billing.account.api.AccountInternalApi;
import org.killbill.billing.account.api.ImmutableAccountData;
+import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.entitlement.api.BlockingState;
+import org.killbill.billing.invoice.api.Invoice;
+import org.killbill.billing.invoice.api.InvoiceInternalApi;
+import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.junction.BlockingInternalApi;
import org.killbill.billing.overdue.api.OverdueState;
import org.killbill.billing.overdue.glue.TestOverdueModule.ApplicatorBlockingApi;
+import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
+import org.killbill.billing.tag.TagInternalApi;
+import org.killbill.billing.util.tag.Tag;
import org.mockito.Mockito;
import org.testng.Assert;
-import org.killbill.billing.account.api.AccountApiException;
-import org.killbill.billing.invoice.api.Invoice;
-import org.killbill.billing.invoice.api.InvoiceItem;
-import org.killbill.billing.entitlement.api.BlockingState;
-import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
-import org.killbill.billing.callcontext.InternalTenantContext;
-import org.killbill.billing.account.api.AccountInternalApi;
-import org.killbill.billing.invoice.api.InvoiceInternalApi;
-import org.killbill.billing.junction.BlockingInternalApi;
-
import com.google.inject.Inject;
public class TestOverdueHelper {
@@ -79,6 +81,7 @@ public class TestOverdueHelper {
" <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
" <unit>DAYS</unit><number>30</number>" +
" </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " <controlTagInclusion>TEST</controlTagInclusion>" +
" </condition>" +
" <externalMessage>Reached OD1</externalMessage>" +
" <blockChanges>true</blockChanges>" +
@@ -93,14 +96,17 @@ public class TestOverdueHelper {
private final AccountInternalApi accountInternalApi;
private final InvoiceInternalApi invoiceInternalApi;
private final BlockingInternalApi blockingInternalApi;
+ private final TagInternalApi tagInternalApi;
@Inject
public TestOverdueHelper(final AccountInternalApi accountInternalApi,
final InvoiceInternalApi invoiceInternalApi,
- final BlockingInternalApi blockingInternalApi) {
+ final BlockingInternalApi blockingInternalApi,
+ final TagInternalApi tagInternalApi) {
this.accountInternalApi = accountInternalApi;
this.invoiceInternalApi = invoiceInternalApi;
this.blockingInternalApi = blockingInternalApi;
+ this.tagInternalApi = tagInternalApi;
}
public void checkStateApplied(final OverdueState state) {
@@ -138,6 +144,15 @@ public class TestOverdueHelper {
invoices.add(invoice);
Mockito.when(invoiceInternalApi.getUnpaidInvoicesByAccountId(Mockito.<UUID>any(), Mockito.<LocalDate>any(), Mockito.<InternalTenantContext>any())).thenReturn(invoices);
+ final Tag tag = Mockito.mock(Tag.class);
+ Mockito.when(tag.getObjectId()).thenReturn(accountId);
+ Mockito.when(tag.getObjectType()).thenReturn(ObjectType.ACCOUNT);
+ Mockito.when(tag.getTagDefinitionId()).thenReturn(new UUID(0, 6));
+ final List<Tag> tags = new ArrayList<Tag>();
+ tags.add(tag);
+ Mockito.when(tagInternalApi.getTags(Mockito.eq(account.getId()), Mockito.eq(ObjectType.ACCOUNT), Mockito.<InternalTenantContext>any()))
+ .thenReturn(tags);
+
return account;
}
diff --git a/overdue/src/test/resources/OverdueConfigSchema.xsd b/overdue/src/test/resources/OverdueConfigSchema.xsd
index d8f014b..7b95f24 100644
--- a/overdue/src/test/resources/OverdueConfigSchema.xsd
+++ b/overdue/src/test/resources/OverdueConfigSchema.xsd
@@ -71,7 +71,8 @@
</xs:sequence>
</xs:complexType>
</xs:element>
-<xs:element minOccurs="0" name="controlTag" type="controlTagType"/>
+<xs:element minOccurs="0" name="controlTagInclusion" type="controlTagType"/>
+<xs:element minOccurs="0" name="controlTagExclusion" type="controlTagType"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java
index d504896..1380883 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java
@@ -147,6 +147,19 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
return accountJson;
}
+ protected Account createAccountNoPMBundleAndSubscription() throws Exception {
+ // Create an account with no payment method
+ final Account accountJson = createAccount();
+ assertNotNull(accountJson);
+
+ // Add a bundle, subscription and move the clock to get the first invoice
+ final Subscription subscriptionJson = createEntitlement(accountJson.getAccountId(), UUID.randomUUID().toString(), "Shotgun",
+ ProductCategory.BASE, BillingPeriod.MONTHLY, true);
+ assertNotNull(subscriptionJson);
+
+ return accountJson;
+ }
+
protected Account createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice() throws Exception {
// Create an account with no payment method
final Account accountJson = createAccount();
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 6685955..f2f8f2c 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
@@ -27,6 +27,8 @@ 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;
import org.testng.annotations.Test;
@@ -46,7 +48,6 @@ public class TestOverdue extends TestJaxrsBase {
Assert.assertNotNull(overdueConfig);
}
-
@Test(groups = "slow", description = "Can retrieve the account overdue status")
public void testOverdueStatus() throws Exception {
// Create an account without a payment method
@@ -99,4 +100,83 @@ public class TestOverdue extends TestJaxrsBase {
// Verify we're in clear state
Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId()).getIsClearState());
}
+
+ @Test(groups = "slow", description = "Allow overdue condition by control tag defined in overdue config xml file")
+ public void testControlTagOverdueConfig() throws Exception {
+ final String overdueConfigPath = Resources.getResource("overdueWithControlTag.xml").getPath();
+ killBillClient.uploadXMLOverdueConfig(overdueConfigPath, requestOptions);
+
+ // Create an account without a payment method and assign a TEST tag
+ final Account accountJson = createAccountNoPMBundleAndSubscription();
+ final Tags accountTag = killBillClient.createAccountTag(accountJson.getAccountId(), ControlTagType.TEST.getId(), requestOptions);
+ assertEquals(accountTag.get(0).getTagDefinitionId(), ControlTagType.TEST.getId());
+
+ // Create an account without a TEST tag
+ final Account accountJsonNoTag = createAccountNoPMBundleAndSubscription();
+
+ // No payment will be triggered as the account doesn't have a payment method
+ clock.addMonths(1);
+ crappyWaitForLackOfProperSynchonization();
+
+ // Get the invoices
+ final List<Invoice> invoices = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
+ // 2 invoices but look for the non zero dollar one
+ assertEquals(invoices.size(), 2);
+
+ final List<Invoice> invoicesNoTag = killBillClient.getInvoicesForAccount(accountJsonNoTag.getAccountId(), requestOptions);
+ // 2 invoices but look for the non zero dollar one
+ assertEquals(invoicesNoTag.size(), 2);
+
+ // We're still clear - see the configuration
+ Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
+ Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJsonNoTag.getAccountId(), requestOptions).getIsClearState());
+
+ clock.addDays(30);
+ crappyWaitForLackOfProperSynchonization();
+
+ // This account is expected to move to OD1 state because it matches with controlTag defined
+ Assert.assertEquals(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getName(), "OD1");
+ // This account is not expected to move to OD1 state because it does not match with controlTag defined
+ Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJsonNoTag.getAccountId(), requestOptions).getIsClearState());
+ }
+
+ @Test(groups = "slow", description = "Allow overdue condition by exclusion control tag defined in overdue config xml file")
+ public void testExclusionControlTagOverdueConfig() throws Exception {
+ final String overdueConfigPath = Resources.getResource("overdueWithExclusionControlTag.xml").getPath();
+ killBillClient.uploadXMLOverdueConfig(overdueConfigPath, requestOptions);
+
+ // Create an account without a payment method and assign a TEST tag
+ final Account accountJson = createAccountNoPMBundleAndSubscription();
+ final Tags accountTag = killBillClient.createAccountTag(accountJson.getAccountId(), ControlTagType.TEST.getId(), requestOptions);
+ assertEquals(accountTag.get(0).getTagDefinitionId(), ControlTagType.TEST.getId());
+
+ // Create an account without a TEST tag
+ final Account accountJsonNoTag = createAccountNoPMBundleAndSubscription();
+
+ // move a month a wait for invoicing
+ // No payment will be triggered as the account doesn't have a payment method
+ clock.addMonths(1);
+ crappyWaitForLackOfProperSynchonization();
+
+ // Get the invoices
+ final List<Invoice> invoices = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
+ // 2 invoices but look for the non zero dollar one
+ assertEquals(invoices.size(), 2);
+
+ final List<Invoice> invoicesNoTag = killBillClient.getInvoicesForAccount(accountJsonNoTag.getAccountId(), requestOptions);
+ // 2 invoices but look for the non zero dollar one
+ assertEquals(invoicesNoTag.size(), 2);
+
+ // We're still clear - see the configuration
+ Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
+ Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJsonNoTag.getAccountId(), requestOptions).getIsClearState());
+
+ clock.addDays(30);
+ crappyWaitForLackOfProperSynchonization();
+
+ // This account is not expected to move to OD1 state because it does not match with exclusion controlTag defined
+ Assert.assertTrue(killBillClient.getOverdueStateForAccount(accountJson.getAccountId(), requestOptions).getIsClearState());
+ // 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");
+ }
}
diff --git a/profiles/killbill/src/test/resources/overdueWithControlTag.xml b/profiles/killbill/src/test/resources/overdueWithControlTag.xml
new file mode 100644
index 0000000..6d20b0e
--- /dev/null
+++ b/profiles/killbill/src/test/resources/overdueWithControlTag.xml
@@ -0,0 +1,63 @@
+<!--
+ ~ 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>
+ <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <unit>DAYS</unit><number>50</number>
+ </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <controlTagInclusion>TEST</controlTagInclusion>
+ </condition>
+ <externalMessage>Reached OD3</externalMessage>
+ <blockChanges>true</blockChanges>
+ <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>
+ <autoReevaluationInterval>
+ <unit>DAYS</unit><number>5</number>
+ </autoReevaluationInterval>
+ </state>
+ <state name="OD2">
+ <condition>
+ <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <unit>DAYS</unit><number>40</number>
+ </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <controlTagInclusion>TEST</controlTagInclusion>
+ </condition>
+ <externalMessage>Reached OD2</externalMessage>
+ <blockChanges>true</blockChanges>
+ <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>
+ <autoReevaluationInterval>
+ <unit>DAYS</unit><number>5</number>
+ </autoReevaluationInterval>
+ </state>
+ <state name="OD1">
+ <condition>
+ <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <unit>DAYS</unit><number>30</number>
+ </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <controlTagInclusion>TEST</controlTagInclusion>
+ </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/overdueWithExclusionControlTag.xml b/profiles/killbill/src/test/resources/overdueWithExclusionControlTag.xml
new file mode 100644
index 0000000..1da2113
--- /dev/null
+++ b/profiles/killbill/src/test/resources/overdueWithExclusionControlTag.xml
@@ -0,0 +1,63 @@
+<!--
+ ~ 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>
+ <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <unit>DAYS</unit><number>50</number>
+ </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <controlTagExclusion>TEST</controlTagExclusion>
+ </condition>
+ <externalMessage>Reached OD3</externalMessage>
+ <blockChanges>true</blockChanges>
+ <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>
+ <autoReevaluationInterval>
+ <unit>DAYS</unit><number>5</number>
+ </autoReevaluationInterval>
+ </state>
+ <state name="OD2">
+ <condition>
+ <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <unit>DAYS</unit><number>40</number>
+ </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <controlTagExclusion>TEST</controlTagExclusion>
+ </condition>
+ <externalMessage>Reached OD2</externalMessage>
+ <blockChanges>true</blockChanges>
+ <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>
+ <autoReevaluationInterval>
+ <unit>DAYS</unit><number>5</number>
+ </autoReevaluationInterval>
+ </state>
+ <state name="OD1">
+ <condition>
+ <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <unit>DAYS</unit><number>30</number>
+ </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>
+ <controlTagExclusion>TEST</controlTagExclusion>
+ </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/util/src/test/java/org/killbill/billing/mock/glue/MockTagModule.java b/util/src/test/java/org/killbill/billing/mock/glue/MockTagModule.java
index 6f77943..7c3e1a5 100644
--- a/util/src/test/java/org/killbill/billing/mock/glue/MockTagModule.java
+++ b/util/src/test/java/org/killbill/billing/mock/glue/MockTagModule.java
@@ -19,16 +19,27 @@
package org.killbill.billing.mock.glue;
import org.killbill.billing.platform.api.KillbillConfigSource;
+import org.killbill.billing.tag.TagInternalApi;
import org.killbill.billing.util.glue.TagStoreModule;
+import org.killbill.billing.util.tag.DefaultTagInternalApi;
import org.killbill.billing.util.tag.dao.MockTagDao;
import org.killbill.billing.util.tag.dao.MockTagDefinitionDao;
import org.killbill.billing.util.tag.dao.TagDao;
import org.killbill.billing.util.tag.dao.TagDefinitionDao;
+import org.mockito.Mockito;
public class MockTagModule extends TagStoreModule {
+ private final boolean mockInternalApi;
+
public MockTagModule(final KillbillConfigSource configSource) {
super(configSource);
+ this.mockInternalApi = false;
+ }
+
+ public MockTagModule(final KillbillConfigSource configSource, final boolean mockInternalApi) {
+ super(configSource);
+ this.mockInternalApi = mockInternalApi;
}
@Override
@@ -36,4 +47,13 @@ public class MockTagModule extends TagStoreModule {
bind(TagDefinitionDao.class).to(MockTagDefinitionDao.class).asEagerSingleton();
bind(TagDao.class).to(MockTagDao.class).asEagerSingleton();
}
+
+ @Override
+ public void installInternalApi() {
+ if (mockInternalApi) {
+ bind(TagInternalApi.class).toInstance(Mockito.mock(TagInternalApi.class));
+ } else {
+ bind(TagInternalApi.class).to(DefaultTagInternalApi.class).asEagerSingleton();
+ }
+ }
}