killbill-aplcache
Changes
entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java 66(+38 -28)
Details
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
index 7a1f9a9..26248e7 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
@@ -18,20 +18,15 @@ package com.ning.billing.entitlement.api.migration;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import org.joda.time.DateTime;
+import com.google.common.collect.Lists;
import com.google.inject.Inject;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.CatalogService;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.alignment.MigrationPlanAligner;
import com.ning.billing.entitlement.alignment.TimedMigration;
@@ -52,7 +47,6 @@ import com.ning.billing.entitlement.events.user.ApiEventChange;
import com.ning.billing.entitlement.events.user.ApiEventMigrate;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.clock.Clock;
-import com.ning.billing.util.clock.DefaultClock;
public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
@@ -60,19 +54,16 @@ public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
private final EntitlementDao dao;
private final MigrationPlanAligner migrationAligner;
private final SubscriptionFactory factory;
- private final CatalogService catalogService;
private final Clock clock;
@Inject
public DefaultEntitlementMigrationApi(MigrationPlanAligner migrationAligner,
SubscriptionFactory factory,
- CatalogService catalogService,
EntitlementDao dao,
Clock clock) {
this.dao = dao;
this.migrationAligner = migrationAligner;
this.factory = factory;
- this.catalogService = catalogService;
this.clock = clock;
}
@@ -101,20 +92,39 @@ public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
SubscriptionBundleData bundleData = new SubscriptionBundleData(curBundle.getBundleKey(), accountId);
List<SubscriptionMigrationData> bundleSubscriptionData = new LinkedList<AccountMigrationData.SubscriptionMigrationData>();
- for (EntitlementSubscriptionMigration curSub : curBundle.getSubscriptions()) {
+
+ List<EntitlementSubscriptionMigration> sortedSubscriptions = Lists.newArrayList(curBundle.getSubscriptions());
+ // Make sure we have first mpp or legacy, then addon and for each category order by CED
+ Collections.sort(sortedSubscriptions, new Comparator<EntitlementSubscriptionMigration>() {
+ @Override
+ public int compare(EntitlementSubscriptionMigration o1,
+ EntitlementSubscriptionMigration o2) {
+ if (o1.getCategory().equals(o2.getCategory())) {
+ return o1.getSubscriptionCases()[0].getEffectiveDate().compareTo(o2.getSubscriptionCases()[0].getEffectiveDate());
+ } else {
+ if (o1.getCategory().equals("mpp")) {
+ return -1;
+ } else if (o2.getCategory().equals("mpp")) {
+ return 1;
+ } else if (o1.getCategory().equals("legacy")) {
+ return -1;
+ } else if (o2.getCategory().equals("legacy")) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+ });
+
+ DateTime bundleStartDate = null;
+ for (EntitlementSubscriptionMigration curSub : sortedSubscriptions) {
SubscriptionMigrationData data = null;
- switch (curSub.getCategory()) {
- case BASE:
- data = createBaseSubscriptionMigrationData(bundleData.getId(), curSub.getCategory(), curSub.getSubscriptionCases(), now);
- break;
- case ADD_ON:
- // Not implemented yet
- break;
- case STANDALONE:
- data = createStandaloneSubscriptionMigrationData(bundleData.getId(), curSub.getCategory(), curSub.getSubscriptionCases(), now);
- break;
- default:
- throw new EntitlementMigrationApiException(String.format("Unkown product type ", curSub.getCategory()));
+ if (bundleStartDate == null) {
+ data = createInitialSubscription(bundleData.getId(), curSub.getCategory(), curSub.getSubscriptionCases(), now);
+ bundleStartDate = data.getInitialEvents().get(0).getEffectiveDate();
+ } else {
+ data = createSubscriptionMigrationDataWithBundleDate(bundleData.getId(), curSub.getCategory(), curSub.getSubscriptionCases(), now, bundleStartDate);
}
if (data != null) {
bundleSubscriptionData.add(data);
@@ -127,7 +137,7 @@ public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
return accountMigrationData;
}
- private SubscriptionMigrationData createBaseSubscriptionMigrationData(UUID bundleId, ProductCategory productCategory,
+ private SubscriptionMigrationData createInitialSubscription(UUID bundleId, ProductCategory productCategory,
EntitlementSubscriptionMigrationCase [] input, DateTime now)
throws EntitlementMigrationApiException {
@@ -144,8 +154,8 @@ public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
return new SubscriptionMigrationData(subscriptionData, toEvents(subscriptionData, now, events));
}
- private SubscriptionMigrationData createStandaloneSubscriptionMigrationData(UUID bundleId, ProductCategory productCategory,
- EntitlementSubscriptionMigrationCase [] input, DateTime now)
+ private SubscriptionMigrationData createSubscriptionMigrationDataWithBundleDate(UUID bundleId, ProductCategory productCategory,
+ EntitlementSubscriptionMigrationCase [] input, DateTime now, DateTime bundleStartDate)
throws EntitlementMigrationApiException {
TimedMigration [] events = migrationAligner.getEventsMigration(input, now);
DateTime migrationStartDate= events[0].getEventTime();
@@ -154,7 +164,7 @@ public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
.setId(UUID.randomUUID())
.setBundleId(bundleId)
.setCategory(productCategory)
- .setBundleStartDate(migrationStartDate)
+ .setBundleStartDate(bundleStartDate)
.setStartDate(migrationStartDate),
emptyEvents);
return new SubscriptionMigrationData(subscriptionData, toEvents(subscriptionData, now, events));
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 7ef459d..acd64ea 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
@@ -29,6 +29,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.testng.Assert;
+import com.google.common.collect.Lists;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Duration;
import com.ning.billing.catalog.api.PhaseType;
@@ -78,6 +79,48 @@ public abstract class TestMigration extends TestApiBase {
}
+ public void testPlanWithAddOn() {
+ try {
+ DateTime beforeMigration = clock.getUTCNow();
+ final DateTime initalAddonStart = clock.getUTCNow().minusMonths(1).plusDays(7);
+ EntitlementAccountMigration toBeMigrated = createAccountWithRegularBasePlanAndAddons(initalAddonStart);
+ DateTime afterMigration = clock.getUTCNow();
+
+ testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
+ migrationApi.migrate(toBeMigrated);
+ assertTrue(testListener.isCompleted(5000));
+
+ List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
+ assertEquals(bundles.size(), 1);
+ SubscriptionBundle bundle = bundles.get(0);
+
+ List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(bundle.getId());
+ assertEquals(subscriptions.size(), 2);
+
+ Subscription baseSubscription = (subscriptions.get(0).getCurrentPlan().getProduct().getCategory() == ProductCategory.BASE) ?
+ subscriptions.get(0) : subscriptions.get(1);
+ assertDateWithin(baseSubscription.getStartDate(), beforeMigration, afterMigration);
+ assertEquals(baseSubscription.getEndDate(), null);
+ assertEquals(baseSubscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(baseSubscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
+ assertEquals(baseSubscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(baseSubscription.getCurrentPlan().getName(), "assault-rifle-annual");
+
+ Subscription aoSubscription = (subscriptions.get(0).getCurrentPlan().getProduct().getCategory() == ProductCategory.ADD_ON) ?
+ subscriptions.get(0) : subscriptions.get(1);
+ assertEquals(aoSubscription.getStartDate(), initalAddonStart);
+ assertEquals(aoSubscription.getEndDate(), null);
+ assertEquals(aoSubscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(aoSubscription.getCurrentPhase().getPhaseType(), PhaseType.DISCOUNT);
+ assertEquals(aoSubscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(aoSubscription.getCurrentPlan().getName(), "telescopic-scope-monthly");
+
+ } catch (EntitlementMigrationApiException e) {
+ Assert.fail("", e);
+ }
+ }
+
+
public void testSingleBasePlanFutureCancelled() {
try {
@@ -212,7 +255,7 @@ public abstract class TestMigration extends TestApiBase {
}
- private EntitlementAccountMigration createAccountWithSingleBasePlan(final List<EntitlementSubscriptionMigrationCase> cases) {
+ private EntitlementAccountMigration createAccountWithSingleBasePlan(final List<List<EntitlementSubscriptionMigrationCase>> cases) {
return new EntitlementAccountMigration() {
@@ -225,18 +268,24 @@ public abstract class TestMigration extends TestApiBase {
@Override
public EntitlementSubscriptionMigration[] getSubscriptions() {
- EntitlementSubscriptionMigration subscription = new EntitlementSubscriptionMigration() {
- @Override
- public EntitlementSubscriptionMigrationCase[] getSubscriptionCases() {
- return cases.toArray(new EntitlementSubscriptionMigrationCase[cases.size()]);
- }
- @Override
- public ProductCategory getCategory() {
- return ProductCategory.BASE;
- }
- };
- EntitlementSubscriptionMigration[] result = new EntitlementSubscriptionMigration[1];
- result[0] = subscription;
+
+ EntitlementSubscriptionMigration[] result = new EntitlementSubscriptionMigration[cases.size()];
+
+ for (int i = 0; i < cases.size(); i++) {
+
+ final List<EntitlementSubscriptionMigrationCase> curCases = cases.get(i);
+ EntitlementSubscriptionMigration subscription = new EntitlementSubscriptionMigration() {
+ @Override
+ public EntitlementSubscriptionMigrationCase[] getSubscriptionCases() {
+ return curCases.toArray(new EntitlementSubscriptionMigrationCase[curCases.size()]);
+ }
+ @Override
+ public ProductCategory getCategory() {
+ return ProductCategory.BASE;
+ }
+ };
+ result[i] = subscription;
+ }
return result;
}
@Override
@@ -255,6 +304,61 @@ public abstract class TestMigration extends TestApiBase {
};
}
+ private EntitlementAccountMigration createAccountWithRegularBasePlanAndAddons(final DateTime initalAddonStart) {
+
+ List<EntitlementSubscriptionMigrationCase> cases = new LinkedList<EntitlementSubscriptionMigrationCase>();
+ cases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return clock.getUTCNow().minusMonths(3);
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return null;
+ }
+ });
+
+ List<EntitlementSubscriptionMigrationCase> firstAddOnCases = new LinkedList<EntitlementSubscriptionMigrationCase>();
+
+ firstAddOnCases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.DISCOUNT);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return initalAddonStart;
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return initalAddonStart.plusMonths(1);
+ }
+ });
+ firstAddOnCases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return initalAddonStart.plusMonths(1);
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return null;
+ }
+ });
+
+ List<List<EntitlementSubscriptionMigrationCase>> input = new ArrayList<List<EntitlementSubscriptionMigrationCase>>();
+ input.add(cases);
+ input.add(firstAddOnCases);
+ return createAccountWithSingleBasePlan(input);
+ }
+
private EntitlementAccountMigration createAccountWithRegularBasePlan() {
List<EntitlementSubscriptionMigrationCase> cases = new LinkedList<EntitlementSubscriptionMigrationCase>();
cases.add(new EntitlementSubscriptionMigrationCase() {
@@ -271,7 +375,9 @@ public abstract class TestMigration extends TestApiBase {
return null;
}
});
- return createAccountWithSingleBasePlan(cases);
+ List<List<EntitlementSubscriptionMigrationCase>> input = new ArrayList<List<EntitlementSubscriptionMigrationCase>>();
+ input.add(cases);
+ return createAccountWithSingleBasePlan(input);
}
private EntitlementAccountMigration createAccountWithRegularBasePlanFutreCancelled() {
@@ -291,7 +397,9 @@ public abstract class TestMigration extends TestApiBase {
return effectiveDate.plusYears(1);
}
});
- return createAccountWithSingleBasePlan(cases);
+ List<List<EntitlementSubscriptionMigrationCase>> input = new ArrayList<List<EntitlementSubscriptionMigrationCase>>();
+ input.add(cases);
+ return createAccountWithSingleBasePlan(input);
}
@@ -325,7 +433,9 @@ public abstract class TestMigration extends TestApiBase {
return null;
}
});
- return createAccountWithSingleBasePlan(cases);
+ List<List<EntitlementSubscriptionMigrationCase>> input = new ArrayList<List<EntitlementSubscriptionMigrationCase>>();
+ input.add(cases);
+ return createAccountWithSingleBasePlan(input);
}
private EntitlementAccountMigration createAccountFuturePendingChange() {
@@ -359,7 +469,9 @@ public abstract class TestMigration extends TestApiBase {
return null;
}
});
- return createAccountWithSingleBasePlan(cases);
+ List<List<EntitlementSubscriptionMigrationCase>> input = new ArrayList<List<EntitlementSubscriptionMigrationCase>>();
+ input.add(cases);
+ return createAccountWithSingleBasePlan(input);
}
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java
index b3eb168..b7e83bc 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java
@@ -38,6 +38,12 @@ public class TestMigrationSql extends TestMigration {
@Override
@Test(enabled=true, groups="sql")
+ public void testPlanWithAddOn() {
+ super.testPlanWithAddOn();
+ }
+
+ @Override
+ @Test(enabled=true, groups="sql")
public void testSingleBasePlanFutureCancelled() {
super.testSingleBasePlanFutureCancelled();
}