killbill-memoizeit
Changes
beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java 145(+145 -0)
beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java 202(+50 -152)
beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueWithSubscriptionCancellation.java 103(+103 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/SubscriptionDataRepair.java 5(+3 -2)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java 49(+33 -16)
overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java 7(+3 -4)
overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java 14(+13 -1)
overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java 8(+4 -4)
Details
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index 9c280fe..cde8803 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -45,20 +45,23 @@ public interface Subscription extends Entity, Blockable {
TRANSFERED
}
- public boolean cancel(DateTime requestedDate, boolean eot, CallContext context)
- throws EntitlementUserApiException;
+ public boolean cancel(final DateTime requestedDate, final CallContext context)
+ throws EntitlementUserApiException;
+
+ public boolean cancelWithPolicy(final DateTime requestedDate, final ActionPolicy policy, final CallContext context)
+ throws EntitlementUserApiException;
- public boolean uncancel(CallContext context)
+ public boolean uncancel(final CallContext context)
throws EntitlementUserApiException;
- public boolean changePlan(String productName, BillingPeriod term, String priceList, DateTime requestedDate, CallContext context)
+ public boolean changePlan(final String productName, final BillingPeriod term, final String priceList, final DateTime requestedDate, final CallContext context)
throws EntitlementUserApiException;
- public boolean changePlanWithPolicy(String productName, BillingPeriod term, String priceList, DateTime requestedDate,
- ActionPolicy policy, CallContext context)
+ public boolean changePlanWithPolicy(final String productName, final BillingPeriod term, final String priceList, final DateTime requestedDate,
+ final ActionPolicy policy, final CallContext context)
throws EntitlementUserApiException;
- public boolean recreate(PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
+ public boolean recreate(final PlanPhaseSpecifier spec, final DateTime requestedDate, final CallContext context)
throws EntitlementUserApiException;
public UUID getBundleId();
diff --git a/api/src/main/java/com/ning/billing/junction/api/Blockable.java b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
index 73be651..cb5b1a0 100644
--- a/api/src/main/java/com/ning/billing/junction/api/Blockable.java
+++ b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
@@ -18,7 +18,6 @@ package com.ning.billing.junction.api;
import java.util.UUID;
-import com.ning.billing.ErrorCode;
import com.ning.billing.account.api.Account;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
@@ -30,7 +29,7 @@ public interface Blockable {
SUBSCRIPTION_BUNDLE,
SUBSCRIPTION;
- public static Type get(final Blockable o) throws BlockingApiException {
+ public static Type get(final Blockable o) {
if (o instanceof Account) {
return ACCOUNT;
} else if (o instanceof SubscriptionBundle) {
@@ -38,7 +37,7 @@ public interface Blockable {
} else if (o instanceof Subscription) {
return SUBSCRIPTION;
}
- throw new BlockingApiException(ErrorCode.BLOCK_TYPE_NOT_SUPPORTED, o.getClass().getName());
+ throw new IllegalStateException("Unsupported type of blockable " + o);
}
public static Type get(final String type) throws BlockingApiException {
@@ -49,7 +48,7 @@ public interface Blockable {
} else if (type.equalsIgnoreCase(SUBSCRIPTION.name())) {
return SUBSCRIPTION;
}
- throw new BlockingApiException(ErrorCode.BLOCK_TYPE_NOT_SUPPORTED, type);
+ throw new IllegalStateException("Unsupported type of blockable " + type);
}
}
diff --git a/api/src/main/java/com/ning/billing/overdue/Condition.java b/api/src/main/java/com/ning/billing/overdue/Condition.java
index 8319b48..f5fe347 100644
--- a/api/src/main/java/com/ning/billing/overdue/Condition.java
+++ b/api/src/main/java/com/ning/billing/overdue/Condition.java
@@ -16,7 +16,9 @@
package com.ning.billing.overdue;
+
import org.joda.time.LocalDate;
+import org.joda.time.Period;
import com.ning.billing.junction.api.Blockable;
import com.ning.billing.overdue.config.api.BillingState;
@@ -31,5 +33,4 @@ public interface Condition<T extends Blockable> {
* @return true if the condition is true, false otherwise
*/
public boolean evaluate(BillingState<T> state, LocalDate now);
-
}
diff --git a/api/src/main/java/com/ning/billing/overdue/config/api/OverdueStateSet.java b/api/src/main/java/com/ning/billing/overdue/config/api/OverdueStateSet.java
index e423d10..b0218d7 100644
--- a/api/src/main/java/com/ning/billing/overdue/config/api/OverdueStateSet.java
+++ b/api/src/main/java/com/ning/billing/overdue/config/api/OverdueStateSet.java
@@ -39,4 +39,6 @@ public interface OverdueStateSet<T extends Blockable> {
public abstract OverdueState<T> calculateOverdueState(BillingState<T> billingState, LocalDate now) throws OverdueApiException;
public abstract int size();
+
+ public abstract OverdueState<T> getFirstState();
}
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueCancellationPolicicy.java b/api/src/main/java/com/ning/billing/overdue/OverdueCancellationPolicicy.java
new file mode 100644
index 0000000..dda0dd6
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueCancellationPolicicy.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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.
+ */
+package com.ning.billing.overdue;
+
+public enum OverdueCancellationPolicicy {
+ END_OF_TERM,
+ IMMEDIATE,
+ NONE
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueState.java b/api/src/main/java/com/ning/billing/overdue/OverdueState.java
index 39cf93d..0c216b1 100644
--- a/api/src/main/java/com/ning/billing/overdue/OverdueState.java
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueState.java
@@ -31,6 +31,8 @@ public interface OverdueState<T extends Blockable> {
public boolean disableEntitlementAndChangesBlocked();
+ public OverdueCancellationPolicicy getSubscriptionCancellationPolicy();
+
public boolean blockChanges();
public boolean isClearState();
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java b/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
index eca5b18..d06bd7e 100644
--- a/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
@@ -18,16 +18,16 @@ package com.ning.billing.overdue;
import com.ning.billing.junction.api.Blockable;
import com.ning.billing.overdue.config.api.BillingState;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
public interface OverdueUserApi {
- public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueError, OverdueApiException;
+ public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueException, OverdueApiException;
- public <T extends Blockable> void setOverrideBillingStateForAccount(T overdueable, BillingState<T> state) throws OverdueError;
+ public <T extends Blockable> void setOverrideBillingStateForAccount(T overdueable, BillingState<T> state) throws OverdueException;
- public <T extends Blockable> OverdueState<T> getOverdueStateFor(T overdueable) throws OverdueError;
+ public <T extends Blockable> OverdueState<T> getOverdueStateFor(T overdueable) throws OverdueException;
- public <T extends Blockable> BillingState<T> getBillingStateFor(T overdueable) throws OverdueError;
+ public <T extends Blockable> BillingState<T> getBillingStateFor(T overdueable) throws OverdueException;
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java
new file mode 100644
index 0000000..773a1eb
--- /dev/null
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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.
+ */
+package com.ning.billing.beatrix.integration.overdue;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.testng.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.beatrix.integration.BeatrixModule;
+import com.ning.billing.beatrix.integration.TestIntegrationBase;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.overdue.OverdueUserApi;
+import com.ning.billing.overdue.config.OverdueConfig;
+import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
+import com.ning.billing.payment.api.PaymentApi;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
+import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.config.XMLLoader;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+public abstract class TestOverdueBase extends TestIntegrationBase {
+
+ @Inject
+ protected ClockMock clock;
+
+ @Named("yoyo")
+ @Inject
+ protected
+ MockPaymentProviderPlugin paymentPlugin;
+
+ @Inject
+ protected BlockingApi blockingApi;
+
+ @Inject
+ protected OverdueWrapperFactory overdueWrapperFactory;
+
+ @Inject
+ protected OverdueUserApi overdueApi;
+
+ @Inject
+ protected PaymentApi paymentApi;
+
+ @Inject
+ protected InvoiceUserApi invoiceApi;
+
+ protected Account account;
+ protected SubscriptionBundle bundle;
+ protected String productName;
+ protected BillingPeriod term;
+
+
+ public abstract String getOverdueConfig();
+
+ final PaymentMethodPlugin paymentMethodPlugin = new PaymentMethodPlugin() {
+ @Override
+ public boolean isDefaultPaymentMethod() {
+ return false;
+ }
+
+ @Override
+ public String getValueString(final String key) {
+ return null;
+ }
+
+ @Override
+ public List<PaymentMethodKVInfo> getProperties() {
+ return null;
+ }
+
+ @Override
+ public String getExternalPaymentMethodId() {
+ return UUID.randomUUID().toString();
+ }
+ };
+
+ @BeforeMethod(groups = "slow")
+ public void setupOverdue() throws Exception {
+ final String configXml = getOverdueConfig();
+ final InputStream is = new ByteArrayInputStream(configXml.getBytes());
+ final OverdueConfig config = XMLLoader.getObjectFromStreamNoValidation(is, OverdueConfig.class);
+ overdueWrapperFactory.setOverdueConfig(config);
+
+ account = createAccountWithPaymentMethod(getAccountData(0));
+ assertNotNull(account);
+
+ paymentApi.addPaymentMethod(BeatrixModule.PLUGIN_NAME, account, true, paymentMethodPlugin, context);
+
+ bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever", context);
+
+ productName = "Shotgun";
+ term = BillingPeriod.MONTHLY;
+
+ paymentPlugin.clear();
+ }
+
+
+ protected void checkODState(final String expected) {
+ try {
+ // This will test the overdue notification queue: when we move the clock, the overdue system
+ // should get notified to refresh its state.
+ // Calling explicitly refresh here (overdueApi.refreshOverdueStateFor(bundle)) would not fully
+ // test overdue.
+ // Since we're relying on the notification queue, we may need to wait a bit (hence await()).
+ await().atMost(10, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return expected.equals(blockingApi.getBlockingStateFor(bundle).getStateName());
+ }
+ });
+ } catch (Exception e) {
+ Assert.assertEquals(blockingApi.getBlockingStateFor(bundle).getStateName(), expected, "Got exception: " + e.toString());
+ }
+ }
+
+
+}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index 420516c..6aa69ad 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -16,25 +16,18 @@
package com.ning.billing.beatrix.integration.overdue;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Collection;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.Callable;
+
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
+
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
-import com.ning.billing.account.api.Account;
import com.ning.billing.api.TestApiListener.NextEvent;
import com.ning.billing.beatrix.integration.BeatrixModule;
-import com.ning.billing.beatrix.integration.TestIntegrationBase;
import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedItemCheck;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Currency;
@@ -42,149 +35,72 @@ import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItemType;
import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.invoice.api.InvoiceUserApi;
-import com.ning.billing.junction.api.Blockable;
import com.ning.billing.junction.api.BlockingApi;
import com.ning.billing.junction.api.BlockingApiException;
-import com.ning.billing.overdue.OverdueUserApi;
-import com.ning.billing.overdue.config.OverdueConfig;
-import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
import com.ning.billing.payment.api.Payment;
-import com.ning.billing.payment.api.PaymentApi;
-import com.ning.billing.payment.api.PaymentMethodPlugin;
-import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
-import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.config.XMLLoader;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-
-import static com.jayway.awaitility.Awaitility.await;
-import static java.util.concurrent.TimeUnit.SECONDS;
import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "slow")
@Guice(modules = {BeatrixModule.class})
-public class TestOverdueIntegration extends TestIntegrationBase {
-
- @Inject
- private ClockMock clock;
-
- @Named("yoyo")
- @Inject
- private
- MockPaymentProviderPlugin paymentPlugin;
-
- @Inject
- private BlockingApi blockingApi;
-
- @Inject
- private OverdueWrapperFactory overdueWrapperFactory;
-
- @Inject
- private OverdueUserApi overdueApi;
-
- @Inject
- private PaymentApi paymentApi;
-
- @Inject
- private InvoiceUserApi invoiceApi;
-
- private Account account;
- private SubscriptionBundle bundle;
- private String productName;
- private BillingPeriod term;
-
- final PaymentMethodPlugin paymentMethodPlugin = new PaymentMethodPlugin() {
- @Override
- public boolean isDefaultPaymentMethod() {
- return false;
- }
+public class TestOverdueIntegration extends TestOverdueBase {
- @Override
- public String getValueString(final String key) {
- return null;
- }
-
- @Override
- public List<PaymentMethodKVInfo> getProperties() {
- return null;
- }
- @Override
- public String getExternalPaymentMethodId() {
- return UUID.randomUUID().toString();
- }
- };
- @BeforeMethod(groups = "slow")
- public void setupOverdue() throws Exception {
+ @Override
+ public String getOverdueConfig() {
final String configXml = "<overdueConfig>" +
- " <bundleOverdueStates>" +
- " <state name=\"OD3\">" +
- " <condition>" +
- " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " <unit>DAYS</unit><number>50</number>" +
- " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " </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>" +
- " </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>" +
- " </condition>" +
- " <externalMessage>Reached OD1</externalMessage>" +
- " <blockChanges>true</blockChanges>" +
- " <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>" +
- " <autoReevaluationInterval>" +
- " <unit>DAYS</unit><number>5</number>" +
- " </autoReevaluationInterval>" +
- " </state>" +
- " </bundleOverdueStates>" +
- "</overdueConfig>";
- final InputStream is = new ByteArrayInputStream(configXml.getBytes());
- final OverdueConfig config = XMLLoader.getObjectFromStreamNoValidation(is, OverdueConfig.class);
- overdueWrapperFactory.setOverdueConfig(config);
-
- account = createAccountWithPaymentMethod(getAccountData(0));
- assertNotNull(account);
-
- paymentApi.addPaymentMethod(BeatrixModule.PLUGIN_NAME, account, true, paymentMethodPlugin, context);
-
- bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever", context);
-
- productName = "Shotgun";
- term = BillingPeriod.MONTHLY;
-
- paymentPlugin.clear();
+ " <bundleOverdueStates>" +
+ " <state name=\"OD3\">" +
+ " <condition>" +
+ " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " <unit>DAYS</unit><number>50</number>" +
+ " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " </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>" +
+ " </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>" +
+ " </condition>" +
+ " <externalMessage>Reached OD1</externalMessage>" +
+ " <blockChanges>true</blockChanges>" +
+ " <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>" +
+ " <autoReevaluationInterval>" +
+ " <unit>DAYS</unit><number>5</number>" +
+ " </autoReevaluationInterval>" +
+ " </state>" +
+ " </bundleOverdueStates>" +
+ "</overdueConfig>";
+
+ return configXml;
}
+
// We set the the property killbill.payment.retry.days=8,8,8,8,8,8,8,8 so that Payment retry logic does not end with an ABORTED state
// preventing final instant payment to succeed.
@Test(groups = "slow")
@@ -645,22 +561,4 @@ public class TestOverdueIntegration extends TestIntegrationBase {
changeSubscriptionAndCheckForCompletion(subscription, "Assault-Rifle", BillingPeriod.MONTHLY, NextEvent.CHANGE, NextEvent.INVOICE);
}
}
-
- private void checkODState(final String expected) {
- try {
- // This will test the overdue notification queue: when we move the clock, the overdue system
- // should get notified to refresh its state.
- // Calling explicitly refresh here (overdueApi.refreshOverdueStateFor(bundle)) would not fully
- // test overdue.
- // Since we're relying on the notification queue, we may need to wait a bit (hence await()).
- await().atMost(10, SECONDS).until(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return expected.equals(blockingApi.getBlockingStateFor(bundle).getStateName());
- }
- });
- } catch (Exception e) {
- Assert.assertEquals(blockingApi.getBlockingStateFor(bundle).getStateName(), expected, "Got exception: " + e.toString());
- }
- }
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueWithSubscriptionCancellation.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueWithSubscriptionCancellation.java
new file mode 100644
index 0000000..618162b
--- /dev/null
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueWithSubscriptionCancellation.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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.
+ */
+package com.ning.billing.beatrix.integration.overdue;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import junit.framework.Assert;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import com.ning.billing.api.TestApiListener.NextEvent;
+import com.ning.billing.beatrix.integration.BeatrixModule;
+import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedItemCheck;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.junction.api.BlockingApi;
+
+@Test(groups = "slow")
+@Guice(modules = {BeatrixModule.class})
+public class TestOverdueWithSubscriptionCancellation extends TestOverdueBase {
+
+
+ @Override
+ public String getOverdueConfig() {
+ final String configXml = "<overdueConfig>" +
+ " <bundleOverdueStates>" +
+ " <state name=\"OD1\">" +
+ " <condition>" +
+ " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " <unit>DAYS</unit><number>5</number>" +
+ " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " </condition>" +
+ " <externalMessage>Reached OD1</externalMessage>" +
+ " <blockChanges>true</blockChanges>" +
+ " <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>" +
+ " <subscriptionCancellationPolicy>IMMEDIATE</subscriptionCancellationPolicy>" +
+ " <autoReevaluationInterval>" +
+ " <unit>DAYS</unit><number>5</number>" +
+ " </autoReevaluationInterval>" +
+ " </state>" +
+ " </bundleOverdueStates>" +
+ "</overdueConfig>";
+ return configXml;
+ }
+
+ @Test(groups = "slow")
+ public void testCheckSubscriptionCancellation() throws Exception {
+ clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
+
+ // Set next invoice to fail and create subscription
+ paymentPlugin.makeAllInvoicesFailWithError(true);
+ final Subscription baseSubscription = createSubscriptionAndCheckForCompletion(bundle.getId(), productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.INVOICE);
+
+ invoiceChecker.checkInvoice(account.getId(), 1, new ExpectedItemCheck(new LocalDate(2012, 5, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
+ invoiceChecker.checkChargedThroughDate(baseSubscription.getId(), new LocalDate(2012, 5, 1));
+
+ // DAY 30 have to get out of trial before first payment
+ addDaysAndCheckForCompletion(30, NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR);
+
+ invoiceChecker.checkInvoice(account.getId(), 2, new ExpectedItemCheck(new LocalDate(2012, 5, 31), new LocalDate(2012, 6, 30), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
+ invoiceChecker.checkChargedThroughDate(baseSubscription.getId(), new LocalDate(2012, 6, 30));
+
+ // Should still be in clear state
+ checkODState(BlockingApi.CLEAR_STATE_NAME);
+
+ // DAY 36 -- RIGHT AFTER OD1
+ addDaysAndCheckForCompletion(6, NextEvent.CANCEL);
+
+ // Should be in OD1
+ checkODState("OD1");
+
+ Subscription cancelledBaseSubscription = entitlementUserApi.getSubscriptionFromId(baseSubscription.getId());
+ assertTrue(cancelledBaseSubscription.getState() == SubscriptionState.CANCELLED);
+ }
+}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
index 8728ac9..0dfcc78 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
@@ -158,7 +158,7 @@ public class TestAnalytics extends TestIntegrationBase {
// Cancel end of term - refetch the subscription to have the CTD set
// (otherwise, cancellation would be immediate)
subscription = entitlementUserApi.getSubscriptionFromId(subscription.getId());
- subscription.cancel(clock.getUTCNow(), true, context);
+ subscription.cancel(clock.getUTCNow(), context);
waitALittle();
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
index b5860e8..d9efb35 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
@@ -539,7 +539,7 @@ public class TestIntegration extends TestIntegrationBase {
assertTrue(busHandler.isCompleted(DELAY));
subscription = subscriptionDataFromSubscription(entitlementUserApi.getSubscriptionFromId(subscription.getId()));
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
// MOVE AFTER CANCEL DATE AND EXPECT EVENT : NextEvent.CANCEL
busHandler.pushExpectedEvent(NextEvent.CANCEL);
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index e9c42b0..900e621 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -20,6 +20,7 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import java.util.concurrent.Callable;
import javax.annotation.Nullable;
@@ -60,6 +61,7 @@ import com.ning.billing.entitlement.api.transfer.EntitlementTransferApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
@@ -69,6 +71,7 @@ import com.ning.billing.invoice.api.InvoicePaymentApi;
import com.ning.billing.invoice.api.InvoiceService;
import com.ning.billing.invoice.api.InvoiceUserApi;
import com.ning.billing.invoice.model.InvoicingConfiguration;
+import com.ning.billing.junction.api.BlockingApi;
import com.ning.billing.junction.plumbing.api.BlockingSubscription;
import com.ning.billing.mock.MockAccountBuilder;
import com.ning.billing.mock.api.MockBillCycleDay;
@@ -92,6 +95,8 @@ import com.google.common.base.Joiner;
import com.google.inject.Inject;
import com.google.inject.name.Named;
+import static com.jayway.awaitility.Awaitility.await;
+import static java.util.concurrent.TimeUnit.SECONDS;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@@ -456,7 +461,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
refreshedSubscription.changePlan(productName, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow(), context);
return refreshedSubscription;
} catch (EntitlementUserApiException e) {
- fail();
+ fail(e.getMessage());
return null;
}
}
@@ -472,7 +477,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
try {
// Need to fetch again to get latest CTD updated from the system
final Subscription refreshedSubscription = entitlementUserApi.getSubscriptionFromId(subscription.getId());
- refreshedSubscription.cancel(requestedDate, true, context);
+ refreshedSubscription.cancel(requestedDate, context);
return refreshedSubscription;
} catch (EntitlementUserApiException e) {
fail();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/SubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/SubscriptionApiService.java
index 1e35021..4721c66 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/SubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/SubscriptionApiService.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -38,8 +38,11 @@ public interface SubscriptionApiService {
public boolean recreatePlan(SubscriptionData subscription, PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
throws EntitlementUserApiException;
- public boolean cancel(SubscriptionData subscription, DateTime requestedDate, boolean eot, CallContext context)
- throws EntitlementUserApiException;
+ public boolean cancel(SubscriptionData subscription, DateTime requestedDate, CallContext context)
+ throws EntitlementUserApiException;
+
+ public boolean cancelWithPolicy(SubscriptionData subscription, DateTime requestedDate, ActionPolicy policy, CallContext context)
+ throws EntitlementUserApiException;
public boolean uncancel(SubscriptionData subscription, CallContext context)
throws EntitlementUserApiException;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/SubscriptionDataRepair.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/SubscriptionDataRepair.java
index 66cf27c..87c71f8 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/SubscriptionDataRepair.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/SubscriptionDataRepair.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -99,7 +99,7 @@ public class SubscriptionDataRepair extends SubscriptionData {
trickleDownBPEffectForAddon(addonSubscriptions, getLastUserEventEffectiveDate(), context);
break;
case CANCEL:
- cancel(input.getRequestedDate(), false, context);
+ cancel(input.getRequestedDate(), context);
trickleDownBPEffectForAddon(addonSubscriptions, getLastUserEventEffectiveDate(), context);
break;
case PHASE:
@@ -178,6 +178,7 @@ public class SubscriptionDataRepair extends SubscriptionData {
}
}
+ @Override
public void rebuildTransitions(final List<EntitlementEvent> inputEvents, final Catalog catalog) {
this.events = inputEvents;
super.rebuildTransitions(inputEvents, catalog);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java
index ac3e704..16814cb 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java
@@ -154,16 +154,14 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
}
@Override
- public boolean cancel(final SubscriptionData subscription, final DateTime requestedDateWithMs, final boolean eot, final CallContext context) throws EntitlementUserApiException {
+ public boolean cancel(final SubscriptionData subscription, final DateTime requestedDateWithMs, final CallContext context) throws EntitlementUserApiException {
try {
final SubscriptionState currentState = subscription.getState();
if (currentState != SubscriptionState.ACTIVE) {
throw new EntitlementUserApiException(ErrorCode.ENT_CANCEL_BAD_STATE, subscription.getId(), currentState);
}
-
final DateTime now = clock.getUTCNow();
final DateTime requestedDate = (requestedDateWithMs != null) ? DefaultClock.truncateMs(requestedDateWithMs) : now;
- validateRequestedDate(subscription, now, requestedDate);
final Plan currentPlan = subscription.getCurrentPlan();
final PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
@@ -173,26 +171,45 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
subscription.getCurrentPhase().getPhaseType());
final ActionPolicy policy = catalogService.getFullCatalog().planCancelPolicy(planPhase, requestedDate);
- final DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, requestedDate);
- final EntitlementEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
- .setSubscriptionId(subscription.getId())
- .setActiveVersion(subscription.getActiveVersion())
- .setProcessedDate(now)
- .setEffectiveDate(effectiveDate)
- .setRequestedDate(requestedDate)
- .setUserToken(context.getUserToken())
- .setFromDisk(true));
-
- dao.cancelSubscription(subscription, cancelEvent, context, 0);
- subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
- return (policy == ActionPolicy.IMMEDIATE);
+ return doCancelPlan(subscription, requestedDateWithMs, now, policy, context);
} catch (CatalogApiException e) {
throw new EntitlementUserApiException(e);
}
}
@Override
+ public boolean cancelWithPolicy(final SubscriptionData subscription, final DateTime requestedDateWithMs, final ActionPolicy policy, final CallContext context) throws EntitlementUserApiException {
+ final SubscriptionState currentState = subscription.getState();
+ if (currentState != SubscriptionState.ACTIVE) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_CANCEL_BAD_STATE, subscription.getId(), currentState);
+ }
+ final DateTime now = clock.getUTCNow();
+ return doCancelPlan(subscription, requestedDateWithMs, now, policy, context);
+ }
+
+ private boolean doCancelPlan(final SubscriptionData subscription, final DateTime requestedDateWithMs, final DateTime now, final ActionPolicy policy, final CallContext context) throws EntitlementUserApiException {
+
+ final DateTime requestedDate = (requestedDateWithMs != null) ? DefaultClock.truncateMs(requestedDateWithMs) : now;
+ validateRequestedDate(subscription, now, requestedDate);
+ final DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, requestedDate);
+
+ final EntitlementEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
+ .setSubscriptionId(subscription.getId())
+ .setActiveVersion(subscription.getActiveVersion())
+ .setProcessedDate(now)
+ .setEffectiveDate(effectiveDate)
+ .setRequestedDate(requestedDate)
+ .setUserToken(context.getUserToken())
+ .setFromDisk(true));
+
+ dao.cancelSubscription(subscription, cancelEvent, context, 0);
+ subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
+ return (policy == ActionPolicy.IMMEDIATE);
+ }
+
+
+ @Override
public boolean uncancel(final SubscriptionData subscription, final CallContext context) throws EntitlementUserApiException {
if (!subscription.isSubscriptionFutureCancelled()) {
throw new EntitlementUserApiException(ErrorCode.ENT_UNCANCEL_BAD_STATE, subscription.getId().toString());
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index db4f78f..4e8c923 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -181,9 +181,13 @@ public class SubscriptionData extends EntityBase implements Subscription {
@Override
- public boolean cancel(final DateTime requestedDate, final boolean eot,
- final CallContext context) throws EntitlementUserApiException {
- return apiService.cancel(this, requestedDate, eot, context);
+ public boolean cancel(final DateTime requestedDate, final CallContext context) throws EntitlementUserApiException {
+ return apiService.cancel(this, requestedDate, context);
+ }
+
+ @Override
+ public boolean cancelWithPolicy(final DateTime requestedDate, final ActionPolicy policy, final CallContext context) throws EntitlementUserApiException {
+ return apiService.cancelWithPolicy(this, requestedDate, policy, context);
}
@Override
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
index 2ec89a3..3dd0927 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
@@ -71,7 +71,7 @@ public class TestUserApiAddOn extends TestApiBase {
assertEquals(aoSubscription.getState(), SubscriptionState.ACTIVE);
final DateTime now = clock.getUTCNow();
- aoSubscription.cancel(now, false, context);
+ aoSubscription.cancel(now, context);
testListener.reset();
testListener.pushExpectedEvent(NextEvent.CANCEL);
@@ -119,7 +119,7 @@ public class TestUserApiAddOn extends TestApiBase {
baseSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(baseSubscription.getId());
// FUTURE CANCELLATION
- baseSubscription.cancel(now, false, context);
+ baseSubscription.cancel(now, context);
// REFETCH AO SUBSCRIPTION AND CHECK THIS IS ACTIVE
aoSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(aoSubscription.getId());
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
index 8e70eee..6e3becc 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
@@ -64,7 +64,7 @@ public abstract class TestUserApiCancel extends TestApiBase {
// CANCEL in trial period to get IMM policy
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
currentPhase = subscription.getCurrentPhase();
testListener.isCompleted(3000);
@@ -121,7 +121,7 @@ public abstract class TestUserApiCancel extends TestApiBase {
// CANCEL
testListener.setNonExpectedMode();
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
assertFalse(testListener.isCompleted(3000));
testListener.reset();
@@ -186,7 +186,7 @@ public abstract class TestUserApiCancel extends TestApiBase {
testListener.pushExpectedEvent(NextEvent.CANCEL);
// CANCEL
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
assertTrue(testListener.isCompleted(5000));
final PlanPhase currentPhase = subscription.getCurrentPhase();
@@ -232,7 +232,7 @@ public abstract class TestUserApiCancel extends TestApiBase {
subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
// CANCEL EOT
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
subscription.uncancel(context);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
index dffd3de..29e8a87 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
@@ -159,7 +159,7 @@ public class TestUserApiDemos extends TestApiBase {
/* STEP 8. CANCEL IMM (NO CTD) */
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
displayState(subscription.getId(), "STEP 8. CANCELLATION");
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
index 3beb9a9..f26bc35 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
@@ -146,7 +146,7 @@ public class TestUserApiError extends TestApiBase {
final Subscription subscription = createSubscription("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME);
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
try {
subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow(), context);
} catch (EntitlementUserApiException e) {
@@ -199,7 +199,7 @@ public class TestUserApiError extends TestApiBase {
subscription = entitlementApi.getSubscriptionFromId(subscription.getId());
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
try {
subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow(), context);
} catch (EntitlementUserApiException e) {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
index d35c9f3..026f262 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
@@ -92,7 +92,7 @@ public abstract class TestUserApiRecreate extends TestApiBase {
// NOW CANCEL ADN THIS SHOULD WORK
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel(null, false, context);
+ subscription.cancel(null, context);
testListener.pushExpectedEvent(NextEvent.PHASE);
testListener.pushExpectedEvent(NextEvent.RE_CREATE);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
index e53c706..8859d69 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
@@ -71,7 +71,7 @@ public class TestUserApiScenarios extends TestApiBase {
// CANCEL EOT
testListener.setNonExpectedMode();
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel(clock.getUTCNow(), false, context);
+ subscription.cancel(clock.getUTCNow(), context);
assertFalse(testListener.isCompleted(5000));
testListener.reset();
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/OverdueErrorMapper.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/OverdueErrorMapper.java
index 98ac732..12c3a5f 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/OverdueErrorMapper.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/OverdueErrorMapper.java
@@ -23,11 +23,11 @@ import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
@Singleton
@Provider
-public class OverdueErrorMapper extends ExceptionMapperBase implements ExceptionMapper<OverdueError> {
+public class OverdueErrorMapper extends ExceptionMapperBase implements ExceptionMapper<OverdueException> {
private final UriInfo uriInfo;
@@ -36,7 +36,7 @@ public class OverdueErrorMapper extends ExceptionMapperBase implements Exception
}
@Override
- public Response toResponse(final OverdueError exception) {
+ public Response toResponse(final OverdueException exception) {
return buildBadRequestResponse(exception, uriInfo);
}
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/OverdueResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/OverdueResource.java
index b4c6f64..3fcc1fc 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/OverdueResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/OverdueResource.java
@@ -36,7 +36,7 @@ import com.ning.billing.jaxrs.json.OverdueStateJson;
import com.ning.billing.overdue.OverdueApiException;
import com.ning.billing.overdue.OverdueState;
import com.ning.billing.overdue.OverdueUserApi;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -63,7 +63,7 @@ public class OverdueResource implements JaxrsResource {
@GET
@Path("/" + ACCOUNTS + "/{accountId:" + UUID_PATTERN + "}")
@Produces(APPLICATION_JSON)
- public Response getOverdueAccount(@PathParam("accountId") final String accountId) throws AccountApiException, OverdueError, OverdueApiException {
+ public Response getOverdueAccount(@PathParam("accountId") final String accountId) throws AccountApiException, OverdueException, OverdueApiException {
final Account account = accountApi.getAccountById(UUID.fromString(accountId));
final OverdueState<Account> overdueState = overdueApi.getOverdueStateFor(account);
@@ -73,7 +73,7 @@ public class OverdueResource implements JaxrsResource {
@GET
@Path("/" + BUNDLES + "/{bundleId:" + UUID_PATTERN + "}")
@Produces(APPLICATION_JSON)
- public Response getOverdueBundle(@PathParam("bundleId") final String bundleId) throws EntitlementUserApiException, OverdueError, OverdueApiException {
+ public Response getOverdueBundle(@PathParam("bundleId") final String bundleId) throws EntitlementUserApiException, OverdueException, OverdueApiException {
final SubscriptionBundle bundle = entitlementApi.getBundleFromId(UUID.fromString(bundleId));
final OverdueState<SubscriptionBundle> overdueState = overdueApi.getOverdueStateFor(bundle);
@@ -83,7 +83,7 @@ public class OverdueResource implements JaxrsResource {
@GET
@Path("/" + SUBSCRIPTIONS + "/{subscriptionId:" + UUID_PATTERN + "}")
@Produces(APPLICATION_JSON)
- public Response getOverdueSubscription(@PathParam("subscriptionId") final String subscriptionId) throws EntitlementUserApiException, OverdueError, OverdueApiException {
+ public Response getOverdueSubscription(@PathParam("subscriptionId") final String subscriptionId) throws EntitlementUserApiException, OverdueException, OverdueApiException {
final Subscription subscription = entitlementApi.getSubscriptionFromId(UUID.fromString(subscriptionId));
final OverdueState<Subscription> overdueState = overdueApi.getOverdueStateFor(subscription);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
index 68dacad..178eea9 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
@@ -220,6 +220,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
@QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
@QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion,
@QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("5") final long timeoutSec,
+ @QueryParam(QUERY_POLICY) final String policyString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@@ -237,7 +238,12 @@ public class SubscriptionResource extends JaxRsResourceBase {
final Subscription current = entitlementApi.getSubscriptionFromId(uuid);
final DateTime inputDate = (requestedDate != null) ? DATE_TIME_FORMATTER.parseDateTime(requestedDate) : null;
- isImmediateOp = current.cancel(inputDate, false, ctx);
+ if (policyString == null) {
+ isImmediateOp = current.cancel(inputDate, ctx);
+ } else {
+ final ActionPolicy policy = ActionPolicy.valueOf(policyString.toUpperCase());
+ isImmediateOp = current.cancelWithPolicy(inputDate, policy, ctx);
+ }
return Response.status(Status.OK).build();
}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscription.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscription.java
index ddc67e8..1bf3906 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscription.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscription.java
@@ -56,11 +56,18 @@ public class BlockingSubscription implements Subscription {
}
@Override
- public boolean cancel(final DateTime requestedDate, final boolean eot, final CallContext context) throws EntitlementUserApiException {
- return subscription.cancel(requestedDate, eot, context);
+ public boolean cancel(final DateTime requestedDate, final CallContext context) throws EntitlementUserApiException {
+ return subscription.cancel(requestedDate, context);
}
@Override
+ public boolean cancelWithPolicy(DateTime requestedDate, ActionPolicy policy, CallContext context)
+ throws EntitlementUserApiException {
+ return subscription.cancelWithPolicy(requestedDate, policy, context);
+ }
+
+
+ @Override
public boolean uncancel(final CallContext context) throws EntitlementUserApiException {
return subscription.uncancel(context);
}
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
index cf51e2b..c1fa16c 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
@@ -16,7 +16,6 @@
package com.ning.billing.ovedue.notification;
-import java.util.UUID;
import org.joda.time.DateTime;
import org.slf4j.Logger;
@@ -77,7 +76,7 @@ public class DefaultOverdueCheckNotifier implements OverdueCheckNotifier {
}
final OverdueCheckNotificationKey key = (OverdueCheckNotificationKey) notificationKey;
- processEvent(key.getUuidKey(), eventDate);
+ processEvent(key, eventDate);
} catch (IllegalArgumentException e) {
log.error("The key returned from the NextBillingNotificationQueue is not a valid UUID", e);
}
@@ -112,7 +111,7 @@ public class DefaultOverdueCheckNotifier implements OverdueCheckNotifier {
}
}
- private void processEvent(final UUID overdueableId, final DateTime eventDateTime) {
- listener.handleNextOverdueCheck(overdueableId);
+ private void processEvent(final OverdueCheckNotificationKey key, final DateTime eventDateTime) {
+ listener.handleNextOverdueCheck(key);
}
}
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
index ad11522..5c90516 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
@@ -50,7 +50,7 @@ public class DefaultOverdueCheckPoster implements OverdueCheckPoster {
DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
log.info("Queuing overdue check notification. id: {}, timestamp: {}", overdueable.getId().toString(), futureNotificationTime.toString());
- checkOverdueQueue.recordFutureNotification(futureNotificationTime, null, new OverdueCheckNotificationKey(overdueable.getId()));
+ checkOverdueQueue.recordFutureNotification(futureNotificationTime, null, new OverdueCheckNotificationKey(overdueable.getId(), Blockable.Type.get(overdueable)));
} catch (NoSuchNotificationQueue e) {
log.error("Attempting to put items on a non-existent queue (DefaultOverdueCheck).", e);
} catch (IOException e) {
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java
index 3483e8d..70a72d0 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java
@@ -20,11 +20,23 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
+
+import com.ning.billing.junction.api.Blockable;
import com.ning.billing.util.notificationq.DefaultUUIDNotificationKey;
public class OverdueCheckNotificationKey extends DefaultUUIDNotificationKey {
+
+ private final Blockable.Type type;
+
@JsonCreator
- public OverdueCheckNotificationKey(@JsonProperty("uuidKey") UUID uuidKey) {
+ public OverdueCheckNotificationKey(@JsonProperty("uuidKey") UUID uuidKey,
+ @JsonProperty("type") Blockable.Type type) {
super(uuidKey);
+ this.type = type;
+ }
+
+ // Hack : We default to SubscriptionBundle which is the only one supported at the time
+ public Blockable.Type getType() {
+ return type == null ? Blockable.Type.SUBSCRIPTION_BUNDLE : type;
}
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
index c659083..3e5ffa5 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
@@ -30,7 +30,7 @@ import com.ning.billing.overdue.OverdueState;
import com.ning.billing.overdue.OverdueUserApi;
import com.ning.billing.overdue.config.OverdueConfig;
import com.ning.billing.overdue.config.api.BillingState;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.overdue.config.api.OverdueStateSet;
import com.ning.billing.overdue.wrapper.OverdueWrapper;
import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
@@ -51,25 +51,25 @@ public class DefaultOverdueUserApi implements OverdueUserApi {
@SuppressWarnings("unchecked")
@Override
- public <T extends Blockable> OverdueState<T> getOverdueStateFor(final T overdueable) throws OverdueError {
+ public <T extends Blockable> OverdueState<T> getOverdueStateFor(final T overdueable) throws OverdueException {
try {
final String stateName = accessApi.getBlockingStateFor(overdueable).getStateName();
final OverdueStateSet<SubscriptionBundle> states = overdueConfig.getBundleStateSet();
return (OverdueState<T>) states.findState(stateName);
} catch (OverdueApiException e) {
- throw new OverdueError(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED, overdueable.getId(), overdueable.getClass().getSimpleName());
+ throw new OverdueException(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED, overdueable.getId(), overdueable.getClass().getSimpleName());
}
}
@Override
- public <T extends Blockable> BillingState<T> getBillingStateFor(final T overdueable) throws OverdueError {
+ public <T extends Blockable> BillingState<T> getBillingStateFor(final T overdueable) throws OverdueException {
log.info(String.format("Billing state of of %s requested", overdueable.getId()));
final OverdueWrapper<T> wrapper = factory.createOverdueWrapperFor(overdueable);
return wrapper.billingState();
}
@Override
- public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(final T blockable) throws OverdueError, OverdueApiException {
+ public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(final T blockable) throws OverdueException, OverdueApiException {
log.info(String.format("Refresh of %s requested", blockable.getId()));
final OverdueWrapper<T> wrapper = factory.createOverdueWrapperFor(blockable);
return wrapper.refresh();
diff --git a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
index 86c9a72..40a93bd 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
@@ -16,64 +16,105 @@
package com.ning.billing.overdue.applicator;
+import java.util.LinkedList;
+import java.util.List;
+
import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.junction.api.Blockable;
import com.ning.billing.junction.api.BlockingApi;
import com.ning.billing.junction.api.BlockingApiException;
import com.ning.billing.junction.api.DefaultBlockingState;
import com.ning.billing.ovedue.notification.OverdueCheckPoster;
import com.ning.billing.overdue.OverdueApiException;
+import com.ning.billing.overdue.OverdueCancellationPolicicy;
import com.ning.billing.overdue.OverdueChangeEvent;
import com.ning.billing.overdue.OverdueService;
import com.ning.billing.overdue.OverdueState;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.UserType;
import com.ning.billing.util.clock.Clock;
public class OverdueStateApplicator<T extends Blockable> {
+
+ private static final String API_USER_NAME = "OverdueStateApplicator";
+
private static final Logger log = LoggerFactory.getLogger(OverdueStateApplicator.class);
private final BlockingApi blockingApi;
private final Clock clock;
private final OverdueCheckPoster poster;
private final Bus bus;
+ private final EntitlementUserApi entitlementUserApi;
+ private final CallContextFactory factory;
@Inject
- public OverdueStateApplicator(final BlockingApi accessApi, final Clock clock, final OverdueCheckPoster poster, final Bus bus) {
+ public OverdueStateApplicator(final BlockingApi accessApi, final EntitlementUserApi entitlementUserApi, final Clock clock,
+ final OverdueCheckPoster poster, final Bus bus, final CallContextFactory factory) {
this.blockingApi = accessApi;
+ this.entitlementUserApi = entitlementUserApi;
this.clock = clock;
this.poster = poster;
this.bus = bus;
+ this.factory = factory;
}
- public void apply(final T overdueable, final String previousOverdueStateName, final OverdueState<T> nextOverdueState) throws OverdueError {
- if (previousOverdueStateName.equals(nextOverdueState.getName())) {
- return; // nothing to do
- }
- storeNewState(overdueable, nextOverdueState);
+ public void apply(final OverdueState<T> firstOverdueState, final BillingState<T> billingState,
+ final T overdueable, final String previousOverdueStateName, final OverdueState<T> nextOverdueState) throws OverdueException {
+
try {
+
+ // We did not reach first state, we we need to check if there is any pending condition for which we will not receive
+ // any notifications.. (last two conditions are there for test purpose)
+ if (nextOverdueState.isClearState() && firstOverdueState != null && billingState != null) {
+ final LocalDate firstUnpaidInvoice = billingState.getDateOfEarliestUnpaidInvoice();
+ if (firstUnpaidInvoice != null) {
+ final Period reevaluationInterval = firstOverdueState.getReevaluationInterval();
+ createFutureNotification(overdueable, firstUnpaidInvoice.toDateTimeAtCurrentTime().plus(reevaluationInterval));
+ }
+ }
+
+ if (nextOverdueState == null || previousOverdueStateName.equals(nextOverdueState.getName())) {
+ return; //That's it we are done...
+ }
+
+ storeNewState(overdueable, nextOverdueState);
+
+ cancelSubscriptionsIfRequired(overdueable, nextOverdueState);
+
final Period reevaluationInterval = nextOverdueState.getReevaluationInterval();
if (!nextOverdueState.isClearState()) {
createFutureNotification(overdueable, clock.getUTCNow().plus(reevaluationInterval));
}
} catch (OverdueApiException e) {
if (e.getCode() != ErrorCode.OVERDUE_NO_REEVALUATION_INTERVAL.getCode()) {
- throw new OverdueError(e);
+ throw new OverdueException(e);
}
}
if (nextOverdueState.isClearState()) {
clear(overdueable);
}
-
+
try {
bus.post(createOverdueEvent(overdueable, previousOverdueStateName, nextOverdueState.getName()));
} catch (Exception e) {
@@ -86,12 +127,12 @@ public class OverdueStateApplicator<T extends Blockable> {
return new DefaultOverdueChangeEvent(overdueable.getId(), Blockable.Type.get(overdueable), previousOverdueStateName, nextOverdueStateName, null);
}
- protected void storeNewState(final T blockable, final OverdueState<T> nextOverdueState) throws OverdueError {
+ protected void storeNewState(final T blockable, final OverdueState<T> nextOverdueState) throws OverdueException {
try {
blockingApi.setBlockingState(new DefaultBlockingState(blockable.getId(), nextOverdueState.getName(), Blockable.Type.get(blockable),
OverdueService.OVERDUE_SERVICE_NAME, blockChanges(nextOverdueState), blockEntitlement(nextOverdueState), blockBilling(nextOverdueState)));
} catch (Exception e) {
- throw new OverdueError(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED, blockable.getId(), blockable.getClass().getName());
+ throw new OverdueException(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED, blockable.getId(), blockable.getClass().getName());
}
}
@@ -118,4 +159,46 @@ public class OverdueStateApplicator<T extends Blockable> {
poster.clearNotificationsFor(blockable);
}
+ private void cancelSubscriptionsIfRequired(final T blockable, final OverdueState<T> nextOverdueState) throws OverdueException {
+ if (nextOverdueState.getSubscriptionCancellationPolicy() == OverdueCancellationPolicicy.NONE) {
+ return;
+ }
+ try {
+ ActionPolicy actionPolicy = null;
+ switch(nextOverdueState.getSubscriptionCancellationPolicy()) {
+ case END_OF_TERM:
+ actionPolicy = ActionPolicy.END_OF_TERM;
+ break;
+ case IMMEDIATE:
+ actionPolicy = ActionPolicy.IMMEDIATE;
+ break;
+ default :
+ throw new IllegalStateException("Unexpected OverdueCancellationPolicy " + nextOverdueState.getSubscriptionCancellationPolicy());
+ }
+ final List<Subscription> toBeCancelled = new LinkedList<Subscription>();
+ computeSubscriptionsToCancel(blockable, toBeCancelled);
+ final CallContext context = factory.createCallContext(API_USER_NAME, CallOrigin.INTERNAL, UserType.SYSTEM);
+ for (Subscription cur : toBeCancelled) {
+ cur.cancelWithPolicy(clock.getUTCNow(), actionPolicy, context);
+ }
+ } catch (EntitlementUserApiException e) {
+ throw new OverdueException(e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void computeSubscriptionsToCancel(final T blockable, final List<Subscription> result) throws EntitlementUserApiException{
+ if (blockable instanceof Subscription) {
+ result.add((Subscription) blockable);
+ return;
+ } else if (blockable instanceof SubscriptionBundle) {
+ for (Subscription cur : entitlementUserApi.getSubscriptionsForBundle(blockable.getId())) {
+ computeSubscriptionsToCancel((T) cur, result);
+ }
+ } else if (blockable instanceof Account) {
+ for (SubscriptionBundle cur : entitlementUserApi.getBundlesForAccount(blockable.getId())) {
+ computeSubscriptionsToCancel((T) cur, result);
+ }
+ }
+ }
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
index 8346357..feb0bf4 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
@@ -31,7 +31,7 @@ import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceUserApi;
import com.ning.billing.junction.api.Blockable;
import com.ning.billing.overdue.config.api.BillingState;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.util.clock.Clock;
import com.google.inject.Inject;
@@ -60,7 +60,7 @@ public abstract class BillingStateCalculator<T extends Blockable> {
this.clock = clock;
}
- public abstract BillingState<T> calculateBillingState(T overdueable) throws OverdueError;
+ public abstract BillingState<T> calculateBillingState(T overdueable) throws OverdueException;
protected Invoice earliest(final SortedSet<Invoice> unpaidInvoices) {
try {
diff --git a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
index a72ca90..3a5b607 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
@@ -42,7 +42,7 @@ import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.api.InvoiceUserApi;
import com.ning.billing.overdue.config.api.BillingStateBundle;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.overdue.config.api.PaymentResponse;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.tag.Tag;
@@ -61,7 +61,7 @@ public class BillingStateCalculatorBundle extends BillingStateCalculator<Subscri
}
@Override
- public BillingStateBundle calculateBillingState(final SubscriptionBundle bundle) throws OverdueError {
+ public BillingStateBundle calculateBillingState(final SubscriptionBundle bundle) throws OverdueException {
try {
final Account account = accountApi.getAccountById(bundle.getAccountId());
final SortedSet<Invoice> unpaidInvoices = unpaidInvoicesForBundle(bundle.getId(), bundle.getAccountId(), account.getTimeZone());
@@ -111,9 +111,9 @@ public class BillingStateCalculatorBundle extends BillingStateCalculator<Subscri
basePlanPriceList,
basePlanPhaseType);
} catch (EntitlementUserApiException e) {
- throw new OverdueError(e);
+ throw new OverdueException(e);
} catch (AccountApiException e) {
- throw new OverdueError(e);
+ throw new OverdueException(e);
}
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
index cd50142..359beaa 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
@@ -24,7 +24,9 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
+import org.joda.time.DateTime;
import org.joda.time.LocalDate;
+import org.joda.time.Period;
import com.ning.billing.catalog.api.Duration;
import com.ning.billing.catalog.api.TimeUnit;
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
index cc4e859..383b3fd 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
@@ -28,6 +28,7 @@ import com.ning.billing.ErrorCode;
import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.junction.api.Blockable;
import com.ning.billing.overdue.OverdueApiException;
+import com.ning.billing.overdue.OverdueCancellationPolicicy;
import com.ning.billing.overdue.OverdueState;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationError;
@@ -38,6 +39,7 @@ public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<O
private static final int MAX_NAME_LENGTH = 50;
+
@XmlElement(required = false, name = "condition")
private DefaultCondition<T> condition;
@@ -54,6 +56,9 @@ public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<O
@XmlElement(required = false, name = "disableEntitlementAndChangesBlocked")
private Boolean disableEntitlement = false;
+ @XmlElement(required = false, name = "subscriptionCancellationPolicy")
+ private OverdueCancellationPolicicy subscriptionCancellationPolicy = OverdueCancellationPolicicy.NONE;
+
@XmlElement(required = false, name = "isClearState")
private Boolean isClearState = false;
@@ -99,6 +104,11 @@ public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<O
}
@Override
+ public OverdueCancellationPolicicy getSubscriptionCancellationPolicy() {
+ return subscriptionCancellationPolicy;
+ }
+
+ @Override
public Period getReevaluationInterval() throws OverdueApiException {
if (autoReevaluationInterval == null || autoReevaluationInterval.getUnit() == TimeUnit.UNLIMITED || autoReevaluationInterval.getNumber() == 0) {
throw new OverdueApiException(ErrorCode.OVERDUE_NO_REEVALUATION_INTERVAL, name);
@@ -106,6 +116,7 @@ public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<O
return autoReevaluationInterval.toJodaPeriod();
}
+ @Override
public DefaultCondition<T> getCondition() {
return condition;
}
@@ -130,6 +141,12 @@ public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<O
return this;
}
+ public DefaultOverdueState<T> setSubscriptionCancellationPolicy(final OverdueCancellationPolicicy policy) {
+ this.subscriptionCancellationPolicy = policy;
+ return this;
+ }
+
+
protected DefaultOverdueState<T> setBlockChanges(final boolean cancel) {
this.blockChanges = cancel;
return this;
@@ -159,6 +176,4 @@ public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<O
final Integer daysBetweenPaymentRetries = 8;
return daysBetweenPaymentRetries;
}
-
-
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueStateSet.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueStateSet.java
index 8b3419a..263a8e1 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueStateSet.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueStateSet.java
@@ -19,7 +19,6 @@ package com.ning.billing.overdue.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
-import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
@@ -95,4 +94,8 @@ public abstract class DefaultOverdueStateSet<T extends Blockable> extends Valida
return getStates().length;
}
+ @Override
+ public OverdueState<T> getFirstState() {
+ return getStates()[0];
+ }
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueDispatcher.java b/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueDispatcher.java
index a94448f..e7dcda8 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueDispatcher.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueDispatcher.java
@@ -28,7 +28,7 @@ import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.junction.api.Blockable;
import com.ning.billing.overdue.OverdueApiException;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
public class OverdueDispatcher {
@@ -64,17 +64,17 @@ public class OverdueDispatcher {
public void processOverdue(final Blockable blockable) {
try {
factory.createOverdueWrapperFor(blockable).refresh();
- } catch (OverdueError e) {
+ } catch (OverdueException e) {
log.error("Error processing Overdue for Blockable with id: " + blockable.getId().toString(), e);
} catch (OverdueApiException e) {
log.error("Error processing Overdue for Blockable with id: " + blockable.getId().toString(), e);
}
}
- public void processOverdue(final UUID blockableId) {
+ public void processOverdue(final Blockable.Type type, final UUID blockableId) {
try {
- factory.createOverdueWrapperFor(blockableId).refresh();
- } catch (OverdueError e) {
+ factory.createOverdueWrapperFor(type, blockableId).refresh();
+ } catch (OverdueException e) {
log.error("Error processing Overdue for Blockable with id: " + blockableId.toString(), e);
} catch (OverdueApiException e) {
log.error("Error processing Overdue for Blockable with id: " + blockableId.toString(), e);
diff --git a/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueListener.java b/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueListener.java
index b4688b5..b9c7c89 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueListener.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/listener/OverdueListener.java
@@ -22,6 +22,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ning.billing.invoice.api.InvoiceAdjustmentEvent;
+import com.ning.billing.ovedue.notification.OverdueCheckNotificationKey;
import com.ning.billing.payment.api.PaymentErrorEvent;
import com.ning.billing.payment.api.PaymentInfoEvent;
@@ -59,8 +60,9 @@ public class OverdueListener {
dispatcher.processOverdueForAccount(accountId);
}
- public void handleNextOverdueCheck(final UUID overdueableId) {
- log.info(String.format("Received OD checkup notification for %s", overdueableId));
- dispatcher.processOverdue(overdueableId);
+ public void handleNextOverdueCheck(final OverdueCheckNotificationKey notificationKey) {
+ log.info(String.format("Received OD checkup notification for type = %s, id = %s",
+ notificationKey.getType(), notificationKey.getUuidKey()));
+ dispatcher.processOverdue(notificationKey.getType(), notificationKey.getUuidKey());
}
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
index 5ed1d52..e7330ac 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
@@ -23,7 +23,7 @@ import com.ning.billing.overdue.OverdueState;
import com.ning.billing.overdue.applicator.OverdueStateApplicator;
import com.ning.billing.overdue.calculator.BillingStateCalculator;
import com.ning.billing.overdue.config.api.BillingState;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.overdue.config.api.OverdueStateSet;
import com.ning.billing.util.clock.Clock;
@@ -48,7 +48,7 @@ public class OverdueWrapper<T extends Blockable> {
this.overdueStateApplicator = overdueStateApplicator;
}
- public OverdueState<T> refresh() throws OverdueError, OverdueApiException {
+ public OverdueState<T> refresh() throws OverdueException, OverdueApiException {
if (overdueStateSet.size() < 1) { // No configuration available
return overdueStateSet.getClearState();
}
@@ -57,14 +57,12 @@ public class OverdueWrapper<T extends Blockable> {
final String previousOverdueStateName = api.getBlockingStateFor(overdueable).getStateName();
final OverdueState<T> nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getToday(billingState.getAccountTimeZone()));
- if (nextOverdueState != null && !previousOverdueStateName.equals(nextOverdueState.getName())) {
- overdueStateApplicator.apply(overdueable, previousOverdueStateName, nextOverdueState);
- }
+ overdueStateApplicator.apply(overdueStateSet.getFirstState(), billingState, overdueable, previousOverdueStateName, nextOverdueState);
return nextOverdueState;
}
- public BillingState<T> billingState() throws OverdueError {
+ public BillingState<T> billingState() throws OverdueException {
return billingStateCalcuator.calculateBillingState(overdueable);
}
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
index aed2aad..c410e28 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
@@ -34,7 +34,7 @@ import com.ning.billing.overdue.calculator.BillingStateCalculatorBundle;
import com.ning.billing.overdue.config.DefaultOverdueState;
import com.ning.billing.overdue.config.DefaultOverdueStateSet;
import com.ning.billing.overdue.config.OverdueConfig;
-import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.overdue.config.api.OverdueStateSet;
import com.ning.billing.util.clock.Clock;
@@ -61,34 +61,32 @@ public class OverdueWrapperFactory {
}
@SuppressWarnings("unchecked")
- public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(final T bloackable) throws OverdueError {
+ public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(final T bloackable) throws OverdueException {
if (bloackable instanceof SubscriptionBundle) {
return (OverdueWrapper<T>) new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle) bloackable, api, getOverdueStateSetBundle(),
clock, billingStateCalcuatorBundle, overdueStateApplicatorBundle);
} else {
- throw new OverdueError(ErrorCode.OVERDUE_TYPE_NOT_SUPPORTED, bloackable.getId(), bloackable.getClass());
+ throw new OverdueException(ErrorCode.OVERDUE_TYPE_NOT_SUPPORTED, bloackable.getId(), bloackable.getClass());
}
}
@SuppressWarnings("unchecked")
- public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(final UUID id) throws OverdueError {
- final BlockingState state = api.getBlockingStateFor(id);
-
+ public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(final Blockable.Type type, final UUID id) throws OverdueException {
try {
- switch (state.getType()) {
+ switch (type) {
case SUBSCRIPTION_BUNDLE: {
final SubscriptionBundle bundle = entitlementApi.getBundleFromId(id);
return (OverdueWrapper<T>) new OverdueWrapper<SubscriptionBundle>(bundle, api, getOverdueStateSetBundle(),
clock, billingStateCalcuatorBundle, overdueStateApplicatorBundle);
}
default: {
- throw new OverdueError(ErrorCode.OVERDUE_TYPE_NOT_SUPPORTED, id, state.getType());
+ throw new OverdueException(ErrorCode.OVERDUE_TYPE_NOT_SUPPORTED, id, type);
}
}
} catch (EntitlementUserApiException e) {
- throw new OverdueError(e);
+ throw new OverdueException(e);
}
}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java b/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java
index 87347a3..067b2c1 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java
@@ -63,17 +63,17 @@ public class TestOverdueStateApplicator extends OverdueTestBase {
OverdueState<SubscriptionBundle> state;
state = config.getBundleStateSet().findState("OD1");
- applicator.apply(bundle, BlockingApi.CLEAR_STATE_NAME, state);
+ applicator.apply(null, null, bundle, BlockingApi.CLEAR_STATE_NAME, state);
checkStateApplied(state);
checkBussEvent("OD1");
state = config.getBundleStateSet().findState("OD2");
- applicator.apply(bundle, BlockingApi.CLEAR_STATE_NAME, state);
+ applicator.apply(null, null,bundle, BlockingApi.CLEAR_STATE_NAME, state);
checkStateApplied(state);
checkBussEvent("OD2");
state = config.getBundleStateSet().findState("OD3");
- applicator.apply(bundle, BlockingApi.CLEAR_STATE_NAME, state);
+ applicator.apply(null, null, bundle, BlockingApi.CLEAR_STATE_NAME, state);
checkStateApplied(state);
checkBussEvent("OD3");
bus.stop();
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
index 5965e02..d2cecf1 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
@@ -50,6 +50,7 @@ import com.ning.billing.mock.glue.MockJunctionModule;
import com.ning.billing.mock.glue.MockPaymentModule;
import com.ning.billing.ovedue.notification.DefaultOverdueCheckNotifier;
import com.ning.billing.ovedue.notification.DefaultOverdueCheckPoster;
+import com.ning.billing.ovedue.notification.OverdueCheckNotificationKey;
import com.ning.billing.ovedue.notification.OverdueCheckPoster;
import com.ning.billing.overdue.OverdueProperties;
import com.ning.billing.overdue.OverdueTestSuiteWithEmbeddedDB;
@@ -92,9 +93,9 @@ public class TestOverdueCheckNotifier extends OverdueTestSuiteWithEmbeddedDB {
}
@Override
- public void handleNextOverdueCheck(final UUID subscriptionId) {
+ public void handleNextOverdueCheck(final OverdueCheckNotificationKey key) {
eventCount++;
- latestSubscriptionId = subscriptionId;
+ latestSubscriptionId = key.getUuidKey();
}
public int getEventCount() {
@@ -109,6 +110,7 @@ public class TestOverdueCheckNotifier extends OverdueTestSuiteWithEmbeddedDB {
@BeforeClass(groups = "slow")
public void setup() throws ServiceException, IOException, ClassNotFoundException, SQLException, EntitlementUserApiException {
final Injector g = Guice.createInjector(Stage.PRODUCTION, new MockInvoiceModule(), new MockPaymentModule(), new BusModule(), new DefaultOverdueModule() {
+ @Override
protected void configure() {
super.configure();
bind(Clock.class).to(ClockMock.class).asEagerSingleton();
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueNotificationKeyJson.java b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueNotificationKeyJson.java
new file mode 100644
index 0000000..183ffae
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueNotificationKeyJson.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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.
+ */
+package com.ning.billing.overdue.notification;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.ovedue.notification.OverdueCheckNotificationKey;
+import com.ning.billing.util.jackson.ObjectMapper;
+
+public class TestOverdueNotificationKeyJson {
+
+
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ @Test(groups = "fast")
+ public void testOverdueNotificationKeyJson() throws Exception {
+
+ final UUID uuid = UUID.randomUUID();
+ final Blockable.Type type = Blockable.Type.SUBSCRIPTION;
+
+ final OverdueCheckNotificationKey e = new OverdueCheckNotificationKey(uuid, type);
+
+ final String json = mapper.writeValueAsString(e);
+
+ final Class<?> claz = Class.forName(OverdueCheckNotificationKey.class.getName());
+ final Object obj = mapper.readValue(json, claz);
+ Assert.assertTrue(obj.equals(e));
+ }
+
+ @Test(groups = "fast")
+ public void testOverdueNotificationKeyJsonWithNoKey() throws Exception {
+
+ final String uuidString = "bab0fca4-c628-4997-8980-14d6c3a98c48";
+ final String json = "{\"uuidKey\":\"" + uuidString + "\"}";
+
+ final Class<?> claz = Class.forName(OverdueCheckNotificationKey.class.getName());
+ final OverdueCheckNotificationKey obj = (OverdueCheckNotificationKey) mapper.readValue(json, claz);
+ assertEquals(obj.getUuidKey().toString(), uuidString);
+ assertEquals(obj.getType(), Blockable.Type.SUBSCRIPTION_BUNDLE);
+ }
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java b/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java
index 45a5626..6b8d67e 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java
@@ -60,10 +60,11 @@ import com.ning.billing.overdue.service.DefaultOverdueService;
import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
import com.ning.billing.util.bus.BusService;
import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.glue.CallContextModule;
import com.ning.billing.util.glue.NotificationQueueModule;
import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
-@Guice(modules = {DefaultOverdueModule.class, OverdueListenerTesterModule.class, MockClockModule.class, ApplicatorMockJunctionModule.class, CatalogModule.class, MockInvoiceModule.class, MockPaymentModule.class, NotificationQueueModule.class, TestDbiModule.class})
+@Guice(modules = {DefaultOverdueModule.class, OverdueListenerTesterModule.class, MockClockModule.class, ApplicatorMockJunctionModule.class, CallContextModule.class, CatalogModule.class, MockInvoiceModule.class, MockPaymentModule.class, NotificationQueueModule.class, TestDbiModule.class})
public abstract class OverdueTestBase extends OverdueTestSuiteWithEmbeddedDB {
protected final String configXml =
"<overdueConfig>" +
diff --git a/util/src/test/java/com/ning/billing/mock/MockSubscription.java b/util/src/test/java/com/ning/billing/mock/MockSubscription.java
index 1425500..0ff6407 100644
--- a/util/src/test/java/com/ning/billing/mock/MockSubscription.java
+++ b/util/src/test/java/com/ning/billing/mock/MockSubscription.java
@@ -70,8 +70,15 @@ public class MockSubscription implements Subscription {
Subscription sub = Mockito.mock(Subscription.class);
@Override
- public boolean cancel(final DateTime requestedDate, final boolean eot, final CallContext context) throws EntitlementUserApiException {
- return sub.cancel(requestedDate, eot, context);
+ public boolean cancel(final DateTime requestedDate, final CallContext context) throws EntitlementUserApiException {
+ return sub.cancel(requestedDate, context);
+ }
+
+ @Override
+ public boolean cancelWithPolicy(DateTime requestedDate,
+ ActionPolicy policy, CallContext context)
+ throws EntitlementUserApiException {
+ return sub.cancelWithPolicy(requestedDate, policy, context);
}
@Override