killbill-memoizeit
Changes
entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java 22(+11 -11)
entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java 25(+13 -12)
Details
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java
index 4fef890..b3f5277 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java
@@ -224,17 +224,17 @@ public class DefaultEntitlementTransferApi implements EntitlementTransferApi {
effectiveTransferDate.isBefore(oldSubscription.getChargedThroughDate()) ?
oldSubscription.getChargedThroughDate() : effectiveTransferDate;
- final EntitlementEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
- .setSubscriptionId(cur.getId())
- .setActiveVersion(cur.getActiveVersion())
- .setProcessedDate(clock.getUTCNow())
- .setEffectiveDate(effectiveCancelDate)
- .setRequestedDate(effectiveTransferDate)
- .setUserToken(context.getUserToken())
- .setFromDisk(true));
-
- TransferCancelData cancelData = new TransferCancelData(oldSubscription, cancelEvent);
- transferCancelDataList.add(cancelData);
+ final EntitlementEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
+ .setSubscriptionId(cur.getId())
+ .setActiveVersion(cur.getActiveVersion())
+ .setProcessedDate(clock.getUTCNow())
+ .setEffectiveDate(effectiveCancelDate)
+ .setRequestedDate(effectiveTransferDate)
+ .setUserToken(context.getUserToken())
+ .setFromDisk(true));
+
+ TransferCancelData cancelData = new TransferCancelData(oldSubscription, cancelEvent);
+ transferCancelDataList.add(cancelData);
}
// We Align with the original subscription
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
index d2cd173..eb31743 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
@@ -405,8 +405,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
@Override
public Void inTransaction(final EntitlementEventSqlDao transactional, final TransactionStatus status) throws Exception {
final UUID subscriptionId = subscription.getId();
- cancelNextChangeEventFromTransaction(subscriptionId, transactional, context);
- cancelNextPhaseEventFromTransaction(subscriptionId, transactional, context);
+ cancelFutureEventsFromTransaction(subscriptionId, transactional, context);
final List<EntityAudit> eventAudits = new ArrayList<EntityAudit>();
for (final EntitlementEvent cur : changeEvents) {
@@ -432,9 +431,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
private void cancelSubscriptionFromTransaction(final SubscriptionData subscription, final EntitlementEvent cancelEvent, final EntitlementEventSqlDao transactional, final CallContext context, final int seqId) {
final UUID subscriptionId = subscription.getId();
- cancelNextCancelEventFromTransaction(subscriptionId, transactional, context);
- cancelNextChangeEventFromTransaction(subscriptionId, transactional, context);
- cancelNextPhaseEventFromTransaction(subscriptionId, transactional, context);
+ cancelFutureEventsFromTransaction(subscriptionId, transactional, context);
transactional.insertEvent(cancelEvent, context);
final String cancelEventId = cancelEvent.getId().toString();
@@ -456,12 +453,13 @@ public class AuditedEntitlementDao implements EntitlementDao {
cancelFutureEventFromTransaction(subscriptionId, dao, EventType.PHASE, null, context);
}
- private void cancelNextChangeEventFromTransaction(final UUID subscriptionId, final EntitlementEventSqlDao dao, final CallContext context) {
- cancelFutureEventFromTransaction(subscriptionId, dao, EventType.API_USER, ApiEventType.CHANGE, context);
- }
- private void cancelNextCancelEventFromTransaction(final UUID subscriptionId, final EntitlementEventSqlDao dao, final CallContext context) {
- cancelFutureEventFromTransaction(subscriptionId, dao, EventType.API_USER, ApiEventType.CANCEL, context);
+ private void cancelFutureEventsFromTransaction(final UUID subscriptionId, final EntitlementEventSqlDao dao, final CallContext context) {
+ final Date now = clock.getUTCNow().toDate();
+ final List<EntitlementEvent> events = dao.getFutureActiveEventForSubscription(subscriptionId.toString(), now);
+ for (final EntitlementEvent cur : events) {
+ unactivateEventFromTransaction(cur, dao, context);
+ }
}
private void cancelFutureEventFromTransaction(final UUID subscriptionId, final EntitlementEventSqlDao dao, final EventType type,
@@ -479,9 +477,12 @@ public class AuditedEntitlementDao implements EntitlementDao {
futureEvent = cur;
}
}
+ unactivateEventFromTransaction(futureEvent, dao, context);
+ }
- if (futureEvent != null) {
- final String eventId = futureEvent.getId().toString();
+ private void unactivateEventFromTransaction(final EntitlementEvent event, final EntitlementEventSqlDao dao, final CallContext context) {
+ if (event != null) {
+ final String eventId = event.getId().toString();
dao.unactiveEvent(eventId, context);
final Long recordId = dao.getRecordId(eventId);
final EntityAudit audit = new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.UPDATE);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
index a15cd77..2d2a451 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
@@ -50,7 +50,7 @@ public abstract class TestMigration extends TestApiBase {
try {
final DateTime startDate = clock.getUTCNow().minusMonths(2);
final DateTime beforeMigration = clock.getUTCNow();
- final EntitlementAccountMigration toBeMigrated = createAccountWithRegularBasePlan(startDate);
+ final EntitlementAccountMigration toBeMigrated = createAccountForMigrationWithRegularBasePlan(startDate);
final DateTime afterMigration = clock.getUTCNow();
testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
@@ -83,7 +83,7 @@ public abstract class TestMigration extends TestApiBase {
final DateTime beforeMigration = clock.getUTCNow();
final DateTime initalBPStart = clock.getUTCNow().minusMonths(3);
final DateTime initalAddonStart = clock.getUTCNow().minusMonths(1).plusDays(7);
- final EntitlementAccountMigration toBeMigrated = createAccountWithRegularBasePlanAndAddons(initalBPStart, initalAddonStart);
+ final EntitlementAccountMigration toBeMigrated = createAccountForMigrationWithRegularBasePlanAndAddons(initalBPStart, initalAddonStart);
final DateTime afterMigration = clock.getUTCNow();
testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
@@ -111,7 +111,7 @@ public abstract class TestMigration extends TestApiBase {
final Subscription aoSubscription = (subscriptions.get(0).getCurrentPlan().getProduct().getCategory() == ProductCategory.ADD_ON) ?
subscriptions.get(0) : subscriptions.get(1);
// initalAddonStart.plusMonths(1).minusMonths(1) may be different from initalAddonStart, depending on exact date
- // e.g : March 31 + 1 month => April 30 and April 30 - 1 month = March 30 which is != March 31 !!!!
+ // e.g : March 31 + 1 month => April 30 and April 30 - 1 month = March 30 which is != March 31 !!!!
assertEquals(aoSubscription.getStartDate(), initalAddonStart.plusMonths(1).minusMonths(1));
assertEquals(aoSubscription.getEndDate(), null);
assertEquals(aoSubscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
@@ -131,7 +131,7 @@ public abstract class TestMigration extends TestApiBase {
try {
final DateTime startDate = clock.getUTCNow().minusMonths(1);
final DateTime beforeMigration = clock.getUTCNow();
- final EntitlementAccountMigration toBeMigrated = createAccountWithRegularBasePlanFutreCancelled(startDate);
+ final EntitlementAccountMigration toBeMigrated = createAccountForMigrationWithRegularBasePlanFutreCancelled(startDate);
final DateTime afterMigration = clock.getUTCNow();
testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
@@ -177,7 +177,7 @@ public abstract class TestMigration extends TestApiBase {
public void testSingleBasePlanWithPendingPhase() {
try {
final DateTime trialDate = clock.getUTCNow().minusDays(10);
- final EntitlementAccountMigration toBeMigrated = createAccountFuturePendingPhase(trialDate);
+ final EntitlementAccountMigration toBeMigrated = createAccountForMigrationFuturePendingPhase(trialDate);
testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
migrationApi.migrate(toBeMigrated, context);
@@ -223,7 +223,7 @@ public abstract class TestMigration extends TestApiBase {
public void testSingleBasePlanWithPendingChange() {
try {
final DateTime beforeMigration = clock.getUTCNow();
- final EntitlementAccountMigration toBeMigrated = createAccountFuturePendingChange();
+ final EntitlementAccountMigration toBeMigrated = createAccountForMigrationFuturePendingChange();
final DateTime afterMigration = clock.getUTCNow();
testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
@@ -264,179 +264,4 @@ public abstract class TestMigration extends TestApiBase {
Assert.fail("", e);
}
}
-
- private EntitlementAccountMigration createAccountTest(final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> cases) {
- return new EntitlementAccountMigration() {
- private final UUID accountId = UUID.randomUUID();
-
- @Override
- public EntitlementBundleMigration[] getBundles() {
- final List<EntitlementBundleMigration> bundles = new ArrayList<EntitlementBundleMigration>();
- final EntitlementBundleMigration bundle0 = new EntitlementBundleMigration() {
- @Override
- public EntitlementSubscriptionMigration[] getSubscriptions() {
- final EntitlementSubscriptionMigration[] result = new EntitlementSubscriptionMigration[cases.size()];
-
- for (int i = 0; i < cases.size(); i++) {
- final List<EntitlementSubscriptionMigrationCaseWithCTD> curCases = cases.get(i);
- final EntitlementSubscriptionMigration subscription = new EntitlementSubscriptionMigration() {
- @Override
- public EntitlementSubscriptionMigrationCaseWithCTD[] getSubscriptionCases() {
- return curCases.toArray(new EntitlementSubscriptionMigrationCaseWithCTD[curCases.size()]);
- }
-
- @Override
- public ProductCategory getCategory() {
- return curCases.get(0).getPlanPhaseSpecifier().getProductCategory();
- }
-
- @Override
- public DateTime getChargedThroughDate() {
- for (final EntitlementSubscriptionMigrationCaseWithCTD cur : curCases) {
- if (cur.getChargedThroughDate() != null) {
- return cur.getChargedThroughDate();
- }
- }
- return null;
- }
- };
- result[i] = subscription;
- }
- return result;
- }
-
- @Override
- public String getBundleKey() {
- return "12345";
- }
- };
- bundles.add(bundle0);
- return bundles.toArray(new EntitlementBundleMigration[bundles.size()]);
- }
-
- @Override
- public UUID getAccountKey() {
- return accountId;
- }
- };
- }
-
- private EntitlementAccountMigration createAccountWithRegularBasePlanAndAddons(final DateTime initialBPstart, final DateTime initalAddonStart) {
-
- final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
- cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
- initialBPstart,
- null,
- initialBPstart.plusYears(1)));
-
- final List<EntitlementSubscriptionMigrationCaseWithCTD> firstAddOnCases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
- firstAddOnCases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.DISCOUNT),
- initalAddonStart,
- initalAddonStart.plusMonths(1),
- initalAddonStart.plusMonths(1)));
- firstAddOnCases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
- initalAddonStart.plusMonths(1),
- null,
- null));
-
- final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
- input.add(cases);
- input.add(firstAddOnCases);
- return createAccountTest(input);
- }
-
- private EntitlementAccountMigration createAccountWithRegularBasePlan(final DateTime startDate) {
- final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
- cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
- startDate,
- null,
- startDate.plusYears(1)));
- final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
- input.add(cases);
- return createAccountTest(input);
- }
-
- private EntitlementAccountMigration createAccountWithRegularBasePlanFutreCancelled(final DateTime startDate) {
- final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
- cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
- startDate,
- startDate.plusYears(1),
- startDate.plusYears(1)));
- final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
- input.add(cases);
- return createAccountTest(input);
- }
-
- private EntitlementAccountMigration createAccountFuturePendingPhase(final DateTime trialDate) {
- final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
- cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.TRIAL),
- trialDate,
- trialDate.plusDays(30),
- trialDate.plusDays(30)));
- cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
- trialDate.plusDays(30),
- null,
- null));
- final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
- input.add(cases);
- return createAccountTest(input);
- }
-
- private EntitlementAccountMigration createAccountFuturePendingChange() {
- final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
- final DateTime effectiveDate = clock.getUTCNow().minusDays(10);
- cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
- effectiveDate,
- effectiveDate.plusMonths(1),
- effectiveDate.plusMonths(1)));
- cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
- new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
- effectiveDate.plusMonths(1).plusDays(1),
- null,
- null));
- final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
- input.add(cases);
- return createAccountTest(input);
- }
-
- public static class EntitlementSubscriptionMigrationCaseWithCTD implements EntitlementSubscriptionMigrationCase {
- private final PlanPhaseSpecifier pps;
- private final DateTime effDt;
- private final DateTime cancelDt;
- private final DateTime ctd;
-
- public EntitlementSubscriptionMigrationCaseWithCTD(final PlanPhaseSpecifier pps, final DateTime effDt, final DateTime cancelDt, final DateTime ctd) {
- this.pps = pps;
- this.cancelDt = cancelDt;
- this.effDt = effDt;
- this.ctd = ctd;
- }
-
- @Override
- public PlanPhaseSpecifier getPlanPhaseSpecifier() {
- return pps;
- }
-
- @Override
- public DateTime getEffectiveDate() {
- return effDt;
- }
-
- @Override
- public DateTime getCancelledDate() {
- return cancelDt;
- }
-
- public DateTime getChargedThroughDate() {
- return ctd;
- }
- }
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
index 88b24b1..eb52dec 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
@@ -19,6 +19,8 @@ package com.ning.billing.entitlement.api;
import javax.annotation.Nullable;
import java.io.IOException;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@@ -49,6 +51,7 @@ import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.Duration;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.config.EntitlementConfig;
@@ -56,9 +59,12 @@ import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
import com.ning.billing.entitlement.api.billing.ChargeThruApi;
import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementAccountMigration;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementBundleMigration;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementSubscriptionMigration;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementSubscriptionMigrationCase;
import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
import com.ning.billing.entitlement.api.transfer.EntitlementTransferApi;
-import com.ning.billing.entitlement.api.transfer.EntitlementTransferApiException;
import com.ning.billing.entitlement.api.user.EffectiveSubscriptionEvent;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
@@ -400,4 +406,184 @@ public abstract class TestApiBase extends EntitlementTestSuiteWithEmbeddedDB imp
log.debug("Transition " + cur);
}
}
+
+
+ /**************************************************************
+ Utilities for migration tests
+ ***************************************************************/
+
+ protected EntitlementAccountMigration createAccountForMigrationTest(final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> cases) {
+ return new EntitlementAccountMigration() {
+ private final UUID accountId = UUID.randomUUID();
+
+ @Override
+ public EntitlementBundleMigration[] getBundles() {
+ final List<EntitlementBundleMigration> bundles = new ArrayList<EntitlementBundleMigration>();
+ final EntitlementBundleMigration bundle0 = new EntitlementBundleMigration() {
+ @Override
+ public EntitlementSubscriptionMigration[] getSubscriptions() {
+ final EntitlementSubscriptionMigration[] result = new EntitlementSubscriptionMigration[cases.size()];
+
+ for (int i = 0; i < cases.size(); i++) {
+ final List<EntitlementSubscriptionMigrationCaseWithCTD> curCases = cases.get(i);
+ final EntitlementSubscriptionMigration subscription = new EntitlementSubscriptionMigration() {
+ @Override
+ public EntitlementSubscriptionMigrationCaseWithCTD[] getSubscriptionCases() {
+ return curCases.toArray(new EntitlementSubscriptionMigrationCaseWithCTD[curCases.size()]);
+ }
+
+ @Override
+ public ProductCategory getCategory() {
+ return curCases.get(0).getPlanPhaseSpecifier().getProductCategory();
+ }
+
+ @Override
+ public DateTime getChargedThroughDate() {
+ for (final EntitlementSubscriptionMigrationCaseWithCTD cur : curCases) {
+ if (cur.getChargedThroughDate() != null) {
+ return cur.getChargedThroughDate();
+ }
+ }
+ return null;
+ }
+ };
+ result[i] = subscription;
+ }
+ return result;
+ }
+
+ @Override
+ public String getBundleKey() {
+ return "12345";
+ }
+ };
+ bundles.add(bundle0);
+ return bundles.toArray(new EntitlementBundleMigration[bundles.size()]);
+ }
+
+ @Override
+ public UUID getAccountKey() {
+ return accountId;
+ }
+ };
+ }
+
+ protected EntitlementAccountMigration createAccountForMigrationWithRegularBasePlanAndAddons(final DateTime initialBPstart, final DateTime initalAddonStart) {
+
+ final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
+ cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
+ initialBPstart,
+ null,
+ initialBPstart.plusYears(1)));
+
+ final List<EntitlementSubscriptionMigrationCaseWithCTD> firstAddOnCases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
+ firstAddOnCases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.DISCOUNT),
+ initalAddonStart,
+ initalAddonStart.plusMonths(1),
+ initalAddonStart.plusMonths(1)));
+ firstAddOnCases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
+ initalAddonStart.plusMonths(1),
+ null,
+ null));
+
+ final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
+ input.add(cases);
+ input.add(firstAddOnCases);
+ return createAccountForMigrationTest(input);
+ }
+
+ protected EntitlementAccountMigration createAccountForMigrationWithRegularBasePlan(final DateTime startDate) {
+ final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
+ cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
+ startDate,
+ null,
+ startDate.plusYears(1)));
+ final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
+ input.add(cases);
+ return createAccountForMigrationTest(input);
+ }
+
+ protected EntitlementAccountMigration createAccountForMigrationWithRegularBasePlanFutreCancelled(final DateTime startDate) {
+ final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
+ cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
+ startDate,
+ startDate.plusYears(1),
+ startDate.plusYears(1)));
+ final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
+ input.add(cases);
+ return createAccountForMigrationTest(input);
+ }
+
+ protected EntitlementAccountMigration createAccountForMigrationFuturePendingPhase(final DateTime trialDate) {
+ final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
+ cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.TRIAL),
+ trialDate,
+ trialDate.plusDays(30),
+ trialDate.plusDays(30)));
+ cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
+ trialDate.plusDays(30),
+ null,
+ null));
+ final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
+ input.add(cases);
+ return createAccountForMigrationTest(input);
+ }
+
+ protected EntitlementAccountMigration createAccountForMigrationFuturePendingChange() {
+ final List<EntitlementSubscriptionMigrationCaseWithCTD> cases = new LinkedList<EntitlementSubscriptionMigrationCaseWithCTD>();
+ final DateTime effectiveDate = clock.getUTCNow().minusDays(10);
+ cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
+ effectiveDate,
+ effectiveDate.plusMonths(1),
+ effectiveDate.plusMonths(1)));
+ cases.add(new EntitlementSubscriptionMigrationCaseWithCTD(
+ new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN),
+ effectiveDate.plusMonths(1).plusDays(1),
+ null,
+ null));
+ final List<List<EntitlementSubscriptionMigrationCaseWithCTD>> input = new ArrayList<List<EntitlementSubscriptionMigrationCaseWithCTD>>();
+ input.add(cases);
+ return createAccountForMigrationTest(input);
+ }
+
+ public static class EntitlementSubscriptionMigrationCaseWithCTD implements EntitlementSubscriptionMigrationCase {
+ private final PlanPhaseSpecifier pps;
+ private final DateTime effDt;
+ private final DateTime cancelDt;
+ private final DateTime ctd;
+
+ public EntitlementSubscriptionMigrationCaseWithCTD(final PlanPhaseSpecifier pps, final DateTime effDt, final DateTime cancelDt, final DateTime ctd) {
+ this.pps = pps;
+ this.cancelDt = cancelDt;
+ this.effDt = effDt;
+ this.ctd = ctd;
+ }
+
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifier() {
+ return pps;
+ }
+
+ @Override
+ public DateTime getEffectiveDate() {
+ return effDt;
+ }
+
+ @Override
+ public DateTime getCancelledDate() {
+ return cancelDt;
+ }
+
+ public DateTime getChargedThroughDate() {
+ return ctd;
+ }
+ }
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java
index 6074c5e..146db74 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java
@@ -38,7 +38,10 @@ import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.Product;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
import com.ning.billing.entitlement.api.TestApiBase;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApiException;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementAccountMigration;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.api.user.SubscriptionData;
@@ -55,6 +58,67 @@ public class TestTransfer extends TestApiBase {
return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
}
+
+
+ @Test(groups = "slow")
+ public void testTransferMigratedSubscriptionWithCTDInFuture() throws Exception {
+
+ final UUID newAccountId = UUID.randomUUID();
+
+ try {
+ final DateTime startDate = clock.getUTCNow().minusMonths(2);
+ final DateTime beforeMigration = clock.getUTCNow();
+ final EntitlementAccountMigration toBeMigrated = createAccountForMigrationWithRegularBasePlan(startDate);
+ final DateTime afterMigration = clock.getUTCNow();
+
+ testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
+ migrationApi.migrate(toBeMigrated, context);
+ assertTrue(testListener.isCompleted(5000));
+
+ final List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
+ assertEquals(bundles.size(), 1);
+ final SubscriptionBundle bundle = bundles.get(0);
+
+ final List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(bundle.getId());
+ assertEquals(subscriptions.size(), 1);
+ final Subscription subscription = subscriptions.get(0);
+ assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
+ assertEquals(subscription.getEndDate(), null);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
+ assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-annual");
+ assertEquals(subscription.getChargedThroughDate(), startDate.plusYears(1));
+ // WE should see MIGRATE_ENTITLEMENT and then MIGRATE_BILLING in the future
+ assertEquals(subscription.getBillingTransitions().size(), 1);
+ assertEquals(subscription.getBillingTransitions().get(0).getTransitionType(), SubscriptionTransitionType.MIGRATE_BILLING);
+ assertTrue(subscription.getBillingTransitions().get(0).getEffectiveTransitionTime().compareTo(clock.getUTCNow()) > 0);
+ assertListenerStatus();
+
+
+ // MOVE A LITTLE, STILL IN TRIAL
+ clock.addDays(20);
+
+ final DateTime transferRequestedDate = clock.getUTCNow();
+
+ testListener.pushExpectedEvent(NextEvent.TRANSFER);
+ testListener.pushExpectedEvent(NextEvent.CANCEL);
+ transferApi.transferBundle(bundle.getAccountId(), newAccountId, bundle.getKey(), transferRequestedDate, false, true, context);
+ assertTrue(testListener.isCompleted(3000));
+
+ final Subscription oldBaseSubscription = entitlementApi.getBaseSubscription(bundle.getId());
+ assertTrue(oldBaseSubscription.getState() == SubscriptionState.CANCELLED);
+ // The MIGRATE_BILLING event should have been invalidated
+ assertEquals(oldBaseSubscription.getBillingTransitions().size(), 1);
+ assertEquals(oldBaseSubscription.getBillingTransitions().get(0).getTransitionType(), SubscriptionTransitionType.CANCEL);
+
+ } catch (EntitlementMigrationApiException e) {
+ Assert.fail("", e);
+ }
+
+
+ }
+
@Test(groups = "slow")
public void testTransferBPInTrialWithNoCTD() throws Exception {