killbill-aplcache
Changes
entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java 27(+12 -15)
Details
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
index dce8c99..541c57c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
@@ -135,7 +135,7 @@ public class PlanAligner {
lastPlanTransition.getNextPhase().getPhaseType(),
lastPlanTransition.getNextPriceList());
return getTimedPhase(timedPhases, effectiveDate, WhichPhase.NEXT);
- // If we went through Plan changes, borrow the logics for chnagePlan alignement
+ // If we went through Plan changes, borrow the logics for changePlan alignement
case CHANGE:
return getTimedPhaseOnChange(subscription.getStartDate(),
subscription.getBundleStartDate(),
@@ -149,7 +149,7 @@ public class PlanAligner {
throw new EntitlementError(String.format("Unexpectd initial transition %s for current plan %s on subscription %s",
lastPlanTransition.getTransitionType(), subscription.getCurrentPlan(), subscription.getId()));
}
- } catch (Exception /*EntitlementUserApiException, CatalogApiException */ e) {
+ } catch (Exception /* EntitlementUserApiException, CatalogApiException */ e) {
throw new EntitlementError(String.format("Could not compute next phase change for subscription %s", subscription.getId()), e);
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
index d252278..ebee20e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
@@ -30,6 +30,7 @@ import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
+import com.ning.billing.entitlement.engine.addon.AddonUtils;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.clock.Clock;
@@ -41,14 +42,17 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
private final EntitlementDao dao;
private final CatalogService catalogService;
private final SubscriptionApiService apiService;
+ private final AddonUtils addonUtils;
@Inject
- public DefaultEntitlementUserApi(Clock clock, EntitlementDao dao, CatalogService catalogService, SubscriptionApiService apiService) {
+ public DefaultEntitlementUserApi(Clock clock, EntitlementDao dao, CatalogService catalogService,
+ SubscriptionApiService apiService, AddonUtils addonUtils) {
super();
this.clock = clock;
this.apiService = apiService;
this.dao = dao;
this.catalogService = catalogService;
+ this.addonUtils = addonUtils;
}
@Override
@@ -159,21 +163,14 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_AO_BP_NON_ACTIVE, targetAddOnPlan.getName());
}
- Product targetAddonProduct = targetAddOnPlan.getProduct();
- Product baseProduct = baseSubscription.getCurrentPlan().getProduct();
-
- Product [] includedAddOns = baseProduct.getIncluded();
- for (Product curInc : includedAddOns) {
- if (curInc.getName().equals(targetAddonProduct.getName())) {
- throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_AO_ALREADY_INCLUDED, targetAddOnPlan.getName(), baseProduct.getName());
- }
+ if (addonUtils.isAddonIncluded(baseSubscription, targetAddOnPlan)) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_AO_ALREADY_INCLUDED,
+ targetAddOnPlan.getName(), baseSubscription.getCurrentPlan().getProduct().getName());
}
- Product[] availableAddOns = baseProduct.getAvailable();
- for (Product curAv : availableAddOns) {
- if (curAv.getName().equals(targetAddonProduct.getName())) {
- return;
- }
+
+ if (!addonUtils.isAddonAvailable(baseSubscription, targetAddOnPlan)) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_AO_NOT_AVAILABLE,
+ targetAddOnPlan.getName(), baseSubscription.getCurrentPlan().getProduct().getName());
}
- throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_AO_NOT_AVAILABLE, targetAddOnPlan.getName(), baseProduct.getName());
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
index 8bdd584..8cc2573 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
@@ -54,6 +54,7 @@ public class SubscriptionBundleData implements SubscriptionBundle {
return accountId;
}
+
// STEPH do we need it ? and should we return that and when is that populated/updated?
@Override
public DateTime getStartDate() {
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 40132b8..8789537 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
@@ -18,6 +18,7 @@ package com.ning.billing.entitlement.api.user;
import com.ning.billing.ErrorCode;
import com.ning.billing.catalog.api.*;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
@@ -231,15 +232,6 @@ public class SubscriptionData implements Subscription {
return paidThroughDate;
}
- /*
- public DateTime getCurrentPlanStart() {
- return getInitialTransitionForCurrentPlan().getEffectiveTransitionTime();
- }
-
- public PlanPhase getInitialPhaseOnCurrentPlan() {
- return getInitialTransitionForCurrentPlan().getNextPhase();
- }
-*/
public SubscriptionTransitionData getInitialTransitionForCurrentPlan() {
if (transitions == null) {
throw new EntitlementError(String.format("No transitions for subscription %s", getId()));
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/addon/AddonUtils.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/addon/AddonUtils.java
new file mode 100644
index 0000000..66635c3
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/addon/AddonUtils.java
@@ -0,0 +1,63 @@
+/*
+ * 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.entitlement.engine.addon;
+
+import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.entitlement.api.user.Subscription;
+
+public class AddonUtils {
+
+
+ private final CatalogService catalogService;
+
+ @Inject
+ public AddonUtils(CatalogService catalogService) {
+ this.catalogService = catalogService;
+ }
+
+ public boolean isAddonAvailable(Subscription baseSubscription, Plan targetAddOnPlan) {
+
+ Product targetAddonProduct = targetAddOnPlan.getProduct();
+ Product baseProduct = baseSubscription.getCurrentPlan().getProduct();
+ Product[] availableAddOns = baseProduct.getAvailable();
+
+ for (Product curAv : availableAddOns) {
+ if (curAv.getName().equals(targetAddonProduct.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isAddonIncluded(Subscription baseSubscription, Plan targetAddOnPlan) {
+ Product targetAddonProduct = targetAddOnPlan.getProduct();
+ Product baseProduct = baseSubscription.getCurrentPlan().getProduct();
+
+ Product[] includedAddOns = baseProduct.getIncluded();
+ for (Product curAv : includedAddOns) {
+ if (curAv.getName().equals(targetAddonProduct.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index e6f61e7..f03bcbc 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -16,11 +16,17 @@
package com.ning.billing.entitlement.engine.core;
+import java.util.Iterator;
+import java.util.List;
+
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.config.EntitlementConfig;
import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.alignment.TimedPhase;
@@ -33,12 +39,18 @@ import com.ning.billing.entitlement.api.test.DefaultEntitlementTestApi;
import com.ning.billing.entitlement.api.test.EntitlementTestApi;
import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.engine.addon.AddonUtils;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEventData;
+import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventBuilder;
+import com.ning.billing.entitlement.events.user.ApiEventCancel;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.lifecycle.LifecycleHandlerType;
import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
@@ -64,6 +76,8 @@ public class Engine implements EventListener, EntitlementService {
private final EntitlementBillingApi billingApi;
private final EntitlementTestApi testApi;
private final EntitlementMigrationApi migrationApi;
+ private final CatalogService catalogService;
+ private final AddonUtils addonUtils;
private final EventBus eventBus;
private boolean startedNotificationThread;
@@ -72,7 +86,8 @@ public class Engine implements EventListener, EntitlementService {
public Engine(Clock clock, EntitlementDao dao, EventNotifier apiEventProcessor,
PlanAligner planAligner, EntitlementConfig config, DefaultEntitlementUserApi userApi,
DefaultEntitlementBillingApi billingApi, DefaultEntitlementTestApi testApi,
- DefaultEntitlementMigrationApi migrationApi, EventBus eventBus) {
+ DefaultEntitlementMigrationApi migrationApi, CatalogService catalogService,
+ AddonUtils addonUtils, EventBus eventBus) {
super();
this.clock = clock;
this.dao = dao;
@@ -82,6 +97,8 @@ public class Engine implements EventListener, EntitlementService {
this.testApi = testApi;
this.billingApi = billingApi;
this.migrationApi = migrationApi;
+ this.catalogService = catalogService;
+ this.addonUtils = addonUtils;
this.eventBus = eventBus;
this.startedNotificationThread = false;
@@ -138,8 +155,14 @@ public class Engine implements EventListener, EntitlementService {
log.warn("Failed to retrieve subscription for id %s", event.getSubscriptionId());
return;
}
+ //
+ // Do any internal processing on that event before we send the event to the bus
+ //
if (event.getType() == EventType.PHASE) {
- insertNextPhaseEvent(subscription);
+ onPhaseEvent(subscription);
+ } else if (event.getType() == EventType.API_USER &&
+ subscription.getCategory() == ProductCategory.BASE) {
+ onBasePlanEvent(subscription, event);
}
try {
eventBus.post(subscription.getTransitionFromEvent(event));
@@ -184,7 +207,7 @@ public class Engine implements EventListener, EntitlementService {
}
}
- private void insertNextPhaseEvent(SubscriptionData subscription) {
+ private void onPhaseEvent(SubscriptionData subscription) {
try {
DateTime now = clock.getUTCNow();
TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, now);
@@ -199,4 +222,32 @@ public class Engine implements EventListener, EntitlementService {
}
}
+ private void onBasePlanEvent(SubscriptionData baseSubscription, EntitlementEvent event) {
+
+ DateTime now = clock.getUTCNow();
+
+ List<Subscription> subscriptions = dao.getSubscriptions(baseSubscription.getId());
+ Iterator<Subscription> it = subscriptions.iterator();
+ while (it.hasNext()) {
+ SubscriptionData cur = (SubscriptionData) it.next();
+ if (cur.getState() == SubscriptionState.CANCELLED ||
+ cur.getCategory() != ProductCategory.ADD_ON) {
+ continue;
+ }
+ Plan addonCurrentPlan = cur.getCurrentPlan();
+ if (addonUtils.isAddonIncluded(baseSubscription, addonCurrentPlan) ||
+ ! addonUtils.isAddonAvailable(baseSubscription, addonCurrentPlan)) {
+ //
+ // Perform AO cancellation using the effectiveDate of the BP
+ //
+ EntitlementEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
+ .setSubscriptionId(cur.getId())
+ .setActiveVersion(cur.getActiveVersion())
+ .setProcessedDate(now)
+ .setEffectiveDate(event.getEffectiveDate())
+ .setRequestedDate(now));
+ dao.cancelSubscription(cur.getId(), cancelEvent);
+ }
+ }
+ }
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
index 016f005..a987fe6 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
@@ -243,6 +243,7 @@ public class EntitlementSqlDao implements EntitlementDao {
@Override
public Void inTransaction(EventSqlDao dao,
TransactionStatus status) throws Exception {
+ // STEPH what about future cancel events : seems like this is missing?
cancelNextChangeEventFromTransaction(subscriptionId, dao);
cancelNextPhaseEventFromTransaction(subscriptionId, dao);
dao.insertEvent(cancelEvent);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index ab04700..1098c15 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -30,6 +30,7 @@ import com.ning.billing.entitlement.api.test.EntitlementTestApi;
import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.SubscriptionApiService;
+import com.ning.billing.entitlement.engine.addon.AddonUtils;
import com.ning.billing.entitlement.engine.core.DefaultApiEventProcessor;
import com.ning.billing.entitlement.engine.core.Engine;
import com.ning.billing.entitlement.engine.core.EventNotifier;
@@ -66,6 +67,7 @@ public class EntitlementModule extends AbstractModule {
bind(EntitlementService.class).to(Engine.class).asEagerSingleton();
bind(Engine.class).asEagerSingleton();
bind(PlanAligner.class).asEagerSingleton();
+ bind(AddonUtils.class).asEagerSingleton();
bind(MigrationPlanAligner.class).asEagerSingleton();
bind(EntitlementTestApi.class).to(DefaultEntitlementTestApi.class).asEagerSingleton();
bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
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 a2f3532..a6536f4 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
@@ -40,7 +40,10 @@ import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.entitlement.api.user.SubscriptionTransition.SubscriptionTransitionType;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
+import com.ning.billing.util.clock.DefaultClock;
public class TestUserApiAddOn extends TestApiBase {
@@ -49,6 +52,76 @@ public class TestUserApiAddOn extends TestApiBase {
return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
}
+
+ @Test(enabled=true, groups={"sql"})
+ public void testCancelBPWthAddon() {
+ try {
+
+ String baseProduct = "Shotgun";
+ BillingPeriod baseTerm = BillingPeriod.MONTHLY;
+ String basePriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
+
+ // CREATE BP
+ SubscriptionData baseSubscription = createSubscription(baseProduct, baseTerm, basePriceList);
+
+ String aoProduct = "Telescopic-Scope";
+ BillingPeriod aoTerm = BillingPeriod.MONTHLY;
+ String aoPriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
+
+ DateTime beforeAOCreation = clock.getUTCNow();
+ SubscriptionData aoSubscription = createSubscription(aoProduct, aoTerm, aoPriceList);
+ DateTime afterAOCreation = clock.getUTCNow();
+
+ testListener.reset();
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+
+ // MOVE CLOCK AFTER TRIAL + AO DISCOUNT
+ Duration twoMonths = getDurationMonth(2);
+ clock.setDeltaFromReality(twoMonths, DAY_IN_MS);
+ assertTrue(testListener.isCompleted(5000));
+
+ // SET CTD TO CANCEL IN FUTURE
+ DateTime now = clock.getUTCNow();
+ Duration ctd = getDurationMonth(1);
+ DateTime newChargedThroughDate = DefaultClock.addDuration(now, ctd);
+ billingApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate);
+ baseSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(baseSubscription.getId());
+
+ // FUTURE CANCELLATION
+ baseSubscription.cancel(now, false);
+
+ // REFETCH AO SUBSCRIPTION AND CHECK THIS IS FUTURE CANCELLED
+ aoSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(aoSubscription.getId());
+ assertEquals(aoSubscription.getState(), SubscriptionState.ACTIVE);
+
+
+ /*
+ * STEPH not true because this will only happen when CANCEL event is being processed
+ * => isFutureCancelled is broken for AO
+ SubscriptionTransition aaPendingSubscription = aoSubscription.getPendingTransition();
+ assertNotNull(aaPendingSubscription);
+ assertEquals(aaPendingSubscription.getTransitionType(), SubscriptionTransitionType.CANCEL);
+ */
+
+ // MOVE AFTER CANCELLATION
+ testListener.reset();
+ testListener.pushExpectedEvent(NextEvent.CANCEL);
+ clock.addDeltaFromReality(ctd);
+ now = clock.getUTCNow();
+ assertTrue(testListener.isCompleted(5000));
+
+ // REFETCH AO SUBSCRIPTION AND CHECK THIS IS FUTURE CANCELLED
+ aoSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(aoSubscription.getId());
+ assertEquals(aoSubscription.getState(), SubscriptionState.CANCELLED);
+
+
+ } catch (Exception e) {
+ Assert.fail(e.getMessage());
+ }
+ }
+
+
@Test(enabled=true, groups={"sql"})
public void testAddonCreateWithBundleAlign() {
try {
@@ -118,7 +191,7 @@ public class TestUserApiAddOn extends TestApiBase {
Duration someTimeLater = getDurationDay(13);
clock.setDeltaFromReality(someTimeLater, DAY_IN_MS);
- // CREATE ADDON (ALIGN BUNDLE)
+ // CREATE ADDON
DateTime beforeAOCreation = clock.getUTCNow();
SubscriptionData aoSubscription = createSubscription(aoProduct, aoTerm, aoPriceList);
DateTime afterAOCreation = clock.getUTCNow();
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 fef6e3c..9917228 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
@@ -36,6 +36,7 @@ import java.util.UUID;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
public class TestUserApiError extends TestApiBase {
@@ -157,13 +158,21 @@ public class TestUserApiError extends TestApiBase {
public void testChangeSubscriptionFutureCancelled() {
try {
Subscription subscription = createSubscription("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
+ PlanPhase trialPhase = subscription.getCurrentPhase();
+
+ // MOVE TO NEXT PHASE
+ PlanPhase currentPhase = subscription.getCurrentPhase();
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ clock.setDeltaFromReality(currentPhase.getDuration(), DAY_IN_MS);
+ assertTrue(testListener.isCompleted(3000));
+
// SET CTD TO CANCEL IN FUTURE
- PlanPhase trialPhase = subscription.getCurrentPhase();
DateTime expectedPhaseTrialChange = DefaultClock.addDuration(subscription.getStartDate(), trialPhase.getDuration());
Duration ctd = getDurationMonth(1);
DateTime newChargedThroughDate = DefaultClock.addDuration(expectedPhaseTrialChange, ctd);
billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+
subscription = entitlementApi.getSubscriptionFromId(subscription.getId());
subscription.cancel(clock.getUTCNow(), false);