killbill-memoizeit

subscription: Add ability to specify a target PhaseType when

2/3/2017 10:04:08 PM

Details

diff --git a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
index 7e6deb9..d7a2d9b 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
@@ -24,6 +24,7 @@ import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanPhase;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.catalog.api.PlanSpecifier;
 import org.killbill.billing.catalog.api.Product;
@@ -74,7 +75,8 @@ public class StandaloneCatalogWithPriceOverride extends StandaloneCatalog implem
         final Plan defaultPlan = super.createOrFindCurrentPlan(spec, null);
         if (overrides == null ||
             overrides.getOverrides() == null ||
-            overrides.getOverrides().isEmpty()) {
+            overrides.getOverrides().isEmpty() ||
+            isOverrideUsedForPlanAlignmentTargetPhaseType(overrides)) {
             return defaultPlan;
         }
 
@@ -82,6 +84,21 @@ public class StandaloneCatalogWithPriceOverride extends StandaloneCatalog implem
         return priceOverride.getOrCreateOverriddenPlan(this, defaultPlan, CatalogDateHelper.toUTCDateTime(getEffectiveDate()), overrides.getOverrides(), internalCallContext);
     }
 
+    // This is a hack used to specify a target PhaseType when making a changePlan operation. Undocumented feature
+    private boolean isOverrideUsedForPlanAlignmentTargetPhaseType(final PlanPhasePriceOverridesWithCallContext overrides) {
+        if (overrides.getOverrides().size() != 1) {
+            return false;
+        }
+
+        final PlanPhasePriceOverride override = overrides.getOverrides().get(0);
+        return override.getCurrency() == null &&
+               override.getFixedPrice() == null &&
+               override.getRecurringPrice() == null &&
+               override.getPhaseName() == null &&
+               override.getPlanPhaseSpecifier() != null &&
+               override.getPlanPhaseSpecifier().getPhaseType() != null;
+    }
+
     @Override
     public DefaultPlan findCurrentPlan(final String planName) throws CatalogApiException {
         final Matcher m = DefaultPriceOverride.CUSTOM_PLAN_NAME_PATTERN.matcher(planName);
diff --git a/catalog/src/test/resources/catalogTest.xml b/catalog/src/test/resources/catalogTest.xml
index 8f28d1c..78e4449 100644
--- a/catalog/src/test/resources/catalogTest.xml
+++ b/catalog/src/test/resources/catalogTest.xml
@@ -211,6 +211,32 @@
                 </recurring>
             </finalPhase>
         </plan>
+
+        <plan name="pistol-monthly-notrial">
+            <product>Pistol</product>
+            <finalPhase type="EVERGREEN">
+                <duration>
+                    <unit>UNLIMITED</unit>
+                </duration>
+                <recurring>
+                    <billingPeriod>MONTHLY</billingPeriod>
+                    <recurringPrice>
+                        <price>
+                            <currency>USD</currency>
+                            <value>19.95</value>
+                        </price>
+                        <price>
+                            <currency>EUR</currency>
+                            <value>19.95</value>
+                        </price>
+                        <price>
+                            <currency>GBP</currency>
+                            <value>19.95</value>
+                        </price>
+                    </recurringPrice>
+                </recurring>
+            </finalPhase>
+        </plan>
         <plan name="blowdart-monthly">
             <product>Blowdart</product>
             <initialPhases>
@@ -382,6 +408,46 @@
                 </recurring>
             </finalPhase>
         </plan>
+
+        <plan name="pistol-monthly-fixedterm">
+            <product>Pistol</product>
+            <initialPhases>
+                <phase type="TRIAL">
+                    <duration>
+                        <unit>DAYS</unit>
+                        <number>30</number>
+                    </duration>
+                    <fixed>
+                        <fixedPrice>
+                        </fixedPrice>
+                    </fixed>
+                </phase>
+            </initialPhases>
+            <finalPhase type="FIXEDTERM">
+                <duration>
+                    <unit>MONTHS</unit>
+                    <number>12</number>
+                </duration>
+                <recurring>
+                    <billingPeriod>MONTHLY</billingPeriod>
+                    <recurringPrice>
+                        <price>
+                            <currency>GBP</currency>
+                            <value>29.95</value>
+                        </price>
+                        <price>
+                            <currency>EUR</currency>
+                            <value>29.95</value>
+                        </price>
+                        <price>
+                            <currency>USD</currency>
+                            <value>29.95</value>
+                        </price>
+                    </recurringPrice>
+                </recurring>
+            </finalPhase>
+        </plan>
+
         <plan name="shotgun-monthly">
             <product>Shotgun</product>
             <initialPhases>
@@ -665,6 +731,56 @@
                 </recurring>
             </finalPhase>
         </plan>
+        <plan name="pistol-annual-gunclub-discount-notrial">
+            <product>Pistol</product>
+            <initialPhases>
+                <phase type="DISCOUNT">
+                    <duration>
+                        <unit>MONTHS</unit>
+                        <number>6</number>
+                    </duration>
+                    <recurring>
+                        <billingPeriod>MONTHLY</billingPeriod>
+                        <recurringPrice>
+                            <price>
+                                <currency>USD</currency>
+                                <value>9.95</value>
+                            </price>
+                            <price>
+                                <currency>EUR</currency>
+                                <value>9.95</value>
+                            </price>
+                            <price>
+                                <currency>GBP</currency>
+                                <value>9.95</value>
+                            </price>
+                        </recurringPrice>
+                    </recurring>
+                </phase>
+            </initialPhases>
+            <finalPhase type="EVERGREEN">
+                <duration>
+                    <unit>UNLIMITED</unit>
+                </duration>
+                <recurring>
+                    <billingPeriod>ANNUAL</billingPeriod>
+                    <recurringPrice>
+                        <price>
+                            <currency>USD</currency>
+                            <value>199.95</value>
+                        </price>
+                        <price>
+                            <currency>EUR</currency>
+                            <value>199.95</value>
+                        </price>
+                        <price>
+                            <currency>GBP</currency>
+                            <value>199.95</value>
+                        </price>
+                    </recurringPrice>
+                </recurring>
+            </finalPhase>
+        </plan>
         <plan name="shotgun-annual-gunclub-discount">
             <product>Shotgun</product>
             <initialPhases>
@@ -1188,17 +1304,19 @@
                 <plan>holster-monthly-regular</plan>
                 <plan>refurbish-maintenance</plan>
                 <plan>bullets-usage-in-arrear</plan>
+                <plan>holster-monthly-special</plan>
             </plans>
         </defaultPriceList>
         <childPriceList name="gunclubDiscount">
             <plans>
-                <plan>pistol-monthly</plan>
-                <plan>shotgun-monthly</plan>
-                <plan>assault-rifle-monthly</plan>
                 <plan>pistol-annual-gunclub-discount</plan>
                 <plan>shotgun-annual-gunclub-discount</plan>
                 <plan>assault-rifle-annual-gunclub-discount</plan>
-                <plan>holster-monthly-special</plan>
+            </plans>
+        </childPriceList>
+        <childPriceList name="gunclubDiscountNoTrial">
+            <plans>
+                <plan>pistol-annual-gunclub-discount-notrial</plan>
             </plans>
         </childPriceList>
         <childPriceList name="rescue">
@@ -1206,9 +1324,16 @@
                 <plan>assault-rifle-annual-rescue</plan>
             </plans>
         </childPriceList>
+        <childPriceList name="fixedTerm">
+            <plans>
+                <plan>pistol-monthly-fixedterm</plan>
+            </plans>
+        </childPriceList>
         <childPriceList name="notrial">
             <plans>
                 <plan>blowdart-monthly-notrial</plan>
+                <plan>pistol-monthly-notrial</plan>
+
             </plans>
         </childPriceList>
     </priceLists>
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PhasePriceOverrideJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PhasePriceOverrideJson.java
index 06de8a8..730fff2 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PhasePriceOverrideJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PhasePriceOverrideJson.java
@@ -143,7 +143,8 @@ public class PhasePriceOverrideJson {
                     final PlanPhaseSpecifier planPhaseSpecifier = spec.getPlanName() != null ?
                                                                   new PlanPhaseSpecifier(spec.getPlanName(), phaseType) :
                                                                   new PlanPhaseSpecifier(spec.getProductName(), spec.getBillingPeriod(), spec.getPriceListName(), phaseType);
-                    return new DefaultPlanPhasePriceOverride(planPhaseSpecifier, currency, input.getFixedPrice(), input.getRecurringPrice());
+                    final Currency resolvedCurrency = input.getFixedPrice() != null || input.getRecurringPrice() != null ? currency : null;
+                    return new DefaultPlanPhasePriceOverride(planPhaseSpecifier, resolvedCurrency, input.getFixedPrice(), input.getRecurringPrice());
                 }
             }
         }));
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
index 25ce0f3..1485fb4 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
@@ -105,7 +105,7 @@ public class TestCatalog extends TestJaxrsBase {
         Assert.assertEquals(catalogsJson.get(0).getEffectiveDate(), Date.valueOf("2011-01-01"));
         Assert.assertEquals(catalogsJson.get(0).getCurrencies().size(), 3);
         Assert.assertEquals(catalogsJson.get(0).getProducts().size(), 11);
-        Assert.assertEquals(catalogsJson.get(0).getPriceLists().size(), 4);
+        Assert.assertEquals(catalogsJson.get(0).getPriceLists().size(), 6);
 
         for (final Product productJson : catalogsJson.get(0).getProducts()) {
             if (!"BASE".equals(productJson.getType())) {
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java b/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java
index cff670f..3b52dc5 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java
@@ -104,18 +104,18 @@ public class PlanAligner extends BaseAligner {
      * @param subscription  the subscription in change (only start date, bundle start date, current phase, plan and pricelist
      *                      are looked at)
      * @param plan          the current Plan
-     * @param priceList     the priceList on which we should change that subscription.
      * @param effectiveDate the effective change date (driven by the catalog policy, i.e. when the change occurs)
+     * @param newPlanInitialPhaseType the phase on which to start when switching to new plan
      * @return the current phase
      * @throws CatalogApiException         for catalog errors
      * @throws org.killbill.billing.subscription.api.user.SubscriptionBaseApiException for subscription errors
      */
     public TimedPhase getCurrentTimedPhaseOnChange(final DefaultSubscriptionBase subscription,
                                                    final Plan plan,
-                                                   final String priceList,
                                                    final DateTime effectiveDate,
+                                                   final PhaseType newPlanInitialPhaseType,
                                                    final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
-        return getTimedPhaseOnChange(subscription, plan, effectiveDate, WhichPhase.CURRENT, context);
+        return getTimedPhaseOnChange(subscription, plan, effectiveDate, newPlanInitialPhaseType, WhichPhase.CURRENT, context);
     }
 
     /**
@@ -124,18 +124,18 @@ public class PlanAligner extends BaseAligner {
      * @param subscription  the subscription in change (only start date, bundle start date, current phase, plan and pricelist
      *                      are looked at)
      * @param plan          the current Plan
-     * @param priceList     the priceList on which we should change that subscription.
      * @param effectiveDate the effective change date (driven by the catalog policy, i.e. when the change occurs)
+     * @param newPlanInitialPhaseType the phase on which to start when switching to new plan
      * @return the next phase
      * @throws CatalogApiException         for catalog errors
      * @throws org.killbill.billing.subscription.api.user.SubscriptionBaseApiException for subscription errors
      */
     public TimedPhase getNextTimedPhaseOnChange(final DefaultSubscriptionBase subscription,
                                                 final Plan plan,
-                                                final String priceList,
                                                 final DateTime effectiveDate,
+                                                final PhaseType newPlanInitialPhaseType,
                                                 final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
-        return getTimedPhaseOnChange(subscription, plan, effectiveDate, WhichPhase.NEXT, context);
+        return getTimedPhaseOnChange(subscription, plan, effectiveDate, newPlanInitialPhaseType, WhichPhase.NEXT, context);
     }
 
     /**
@@ -176,6 +176,7 @@ public class PlanAligner extends BaseAligner {
                                                  effectiveDate,
                                                  pendingOrLastPlanTransition.getEffectiveTransitionTime(),
                                                  subscription.getAllTransitions().get(0).getNextPhase().getPhaseType(),
+                                                 null,
                                                  WhichPhase.NEXT,
                                                  context);
                 default:
@@ -217,6 +218,7 @@ public class PlanAligner extends BaseAligner {
     private TimedPhase getTimedPhaseOnChange(final DefaultSubscriptionBase subscription,
                                              final Plan nextPlan,
                                              final DateTime effectiveDate,
+                                             final PhaseType newPlanInitialPhaseType,
                                              final WhichPhase which,
                                              final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
         return getTimedPhaseOnChange(subscription.getAlignStartDate(),
@@ -228,6 +230,7 @@ public class PlanAligner extends BaseAligner {
                                      // This method is only called while doing the change, hence we want to pass the change effective date
                                      effectiveDate,
                                      subscription.getAllTransitions().get(0).getNextPhase().getPhaseType(),
+                                     newPlanInitialPhaseType,
                                      which,
                                      context);
     }
@@ -240,6 +243,7 @@ public class PlanAligner extends BaseAligner {
                                              final DateTime effectiveDate,
                                              final DateTime lastOrCurrentChangeEffectiveDate,
                                              final PhaseType originalInitialPhase,
+                                             @Nullable final PhaseType newPlanInitialPhaseType,
                                              final WhichPhase which,
                                              final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
         final Catalog catalog = catalogService.getFullCatalog(true, true, context);
@@ -253,15 +257,17 @@ public class PlanAligner extends BaseAligner {
         switch (alignment) {
             case START_OF_SUBSCRIPTION:
                 planStartDate = subscriptionStartDate;
-                initialPhase = isPlanContainPhaseType(nextPlan, originalInitialPhase) ? originalInitialPhase : null;
+                initialPhase = newPlanInitialPhaseType != null ? newPlanInitialPhaseType :
+                               (isPlanContainPhaseType(nextPlan, originalInitialPhase) ? originalInitialPhase : null);
                 break;
             case START_OF_BUNDLE:
                 planStartDate = bundleStartDate;
-                initialPhase = isPlanContainPhaseType(nextPlan, originalInitialPhase) ? originalInitialPhase : null;
+                initialPhase =  newPlanInitialPhaseType != null ? newPlanInitialPhaseType :
+                                (isPlanContainPhaseType(nextPlan, originalInitialPhase) ? originalInitialPhase : null);
                 break;
             case CHANGE_OF_PLAN:
                 planStartDate = lastOrCurrentChangeEffectiveDate;
-                initialPhase = null;
+                initialPhase = newPlanInitialPhaseType;
                 break;
             case CHANGE_OF_PRICELIST:
                 throw new SubscriptionBaseError(String.format("Not implemented yet %s", alignment));
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
index 554c3c9..c7d3e41 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
@@ -33,9 +33,6 @@ import org.joda.time.DateTimeZone;
 import org.joda.time.ReadableInstant;
 import org.killbill.billing.ErrorCode;
 import org.killbill.billing.ObjectType;
-import org.killbill.billing.account.api.AccountApiException;
-import org.killbill.billing.account.api.AccountInternalApi;
-import org.killbill.billing.account.api.ImmutableAccountInternalApi;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.BillingActionPolicy;
@@ -115,6 +112,11 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
         final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
 
         try {
+
+            if (subscription.getAlignStartDate().compareTo(effectiveDate) != 0) {
+                throw new RuntimeException("Subscription id = " + subscription.getId() + ", alignStartDate = " + subscription.getAlignStartDate() + ", effectiveDate = " + effectiveDate);
+            }
+
             final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscription.getBundleId(), subscription.getId(), subscription.getAlignStartDate(), subscription.getBundleStartDate(),
                                                                            plan, initialPhase, realPriceList, effectiveDate, processedDate, internalCallContext);
             dao.createSubscription(subscription, events, internalCallContext);
@@ -437,6 +439,17 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
         final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, context);
         final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).createOrFindPlan(spec, overridesWithContext, effectiveDate, subscription.getStartDate());
 
+        final PhaseType initialPhaseType;
+        if (overrides != null &&
+            overrides.size() == 1 &&
+            overrides.get(0).getPlanPhaseSpecifier() != null &&
+            overrides.get(0).getCurrency() == null) {
+            initialPhaseType = overrides.get(0).getPlanPhaseSpecifier().getPhaseType();
+        } else {
+            initialPhaseType = null;
+        }
+
+
         if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(newPlan.getProduct().getCategory().toString())) {
             if (newPlan.getPlansAllowedInBundle() != -1
                 && newPlan.getPlansAllowedInBundle() > 0
@@ -453,7 +466,7 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
 
         final List<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
         final List<SubscriptionBaseEvent> addOnCancelEvents = new ArrayList<SubscriptionBaseEvent>();
-        final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPlan.getPriceListName(), effectiveDate, true, addOnSubscriptionsToBeCancelled, addOnCancelEvents, internalCallContext);
+        final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPlan.getPriceListName(), effectiveDate, true, addOnSubscriptionsToBeCancelled, addOnCancelEvents, initialPhaseType, internalCallContext);
 
         dao.changePlan(subscription, changeEvents, addOnSubscriptionsToBeCancelled, addOnCancelEvents, internalCallContext);
 
@@ -497,7 +510,7 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
         final Collection<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
         final Collection<SubscriptionBaseEvent> addOnCancelEvents = new ArrayList<SubscriptionBaseEvent>();
 
-        final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPriceList, effectiveDate, addCancellationAddOnForEventsIfRequired, addOnSubscriptionsToBeCancelled, addOnCancelEvents, internalTenantContext);
+        final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPriceList, effectiveDate, addCancellationAddOnForEventsIfRequired, addOnSubscriptionsToBeCancelled, addOnCancelEvents, null, internalTenantContext);
         changeEvents.addAll(addOnCancelEvents);
         return changeEvents;
     }
@@ -507,8 +520,9 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
                                                               final boolean addCancellationAddOnForEventsIfRequired,
                                                               final Collection<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled,
                                                               final Collection<SubscriptionBaseEvent> addOnCancelEvents,
+                                                              final PhaseType initialPhaseType,
                                                               final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
-        final TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, newPriceList, effectiveDate, internalTenantContext);
+        final TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, internalTenantContext);
 
         final SubscriptionBaseEvent changeEvent = new ApiEventChange(new ApiEventBuilder()
                                                                              .setSubscriptionId(subscription.getId())
@@ -518,7 +532,7 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
                                                                              .setEffectiveDate(effectiveDate)
                                                                              .setFromDisk(true));
 
-        final TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, newPriceList, effectiveDate, internalTenantContext);
+        final TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, internalTenantContext);
         final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
                                           PhaseEventData.createNextPhaseEvent(subscription.getId(),
                                                                               nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) :
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java b/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java
index 3dd19b6..8ab38a0 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java
@@ -33,7 +33,6 @@ import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
 import org.killbill.billing.subscription.events.user.ApiEventBase;
 import org.killbill.billing.subscription.events.user.ApiEventBuilder;
 import org.killbill.billing.subscription.events.user.ApiEventType;
-import org.killbill.billing.subscription.exceptions.SubscriptionBaseError;
 import org.killbill.clock.DefaultClock;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
@@ -60,7 +59,12 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
     public void testCreationBundleAlignment() throws Exception {
         final String productName = "pistol-monthly";
         final PhaseType initialPhase = PhaseType.TRIAL;
-        final DefaultSubscriptionBase defaultSubscriptionBase = createSubscriptionStartedInThePast(productName, initialPhase);
+
+        final DateTime now = clock.getUTCNow();
+        final DateTime bundleStartDate = now.minusHours(10);
+        final DateTime alignStartDate = bundleStartDate.plusHours(5);
+
+        final DefaultSubscriptionBase defaultSubscriptionBase = createSubscriptionStartedInThePast(bundleStartDate, alignStartDate, productName, initialPhase);
 
         // Make the creation effective now, after the bundle and the subscription started
         final DateTime effectiveDate = clock.getUTCNow();
@@ -97,7 +101,12 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
     public void testCreationSubscriptionAlignment() throws Exception {
         final String productName = "laser-scope-monthly";
         final PhaseType initialPhase = PhaseType.DISCOUNT;
-        final DefaultSubscriptionBase defaultSubscriptionBase = createSubscriptionStartedInThePast(productName, initialPhase);
+
+        final DateTime now = clock.getUTCNow();
+        final DateTime bundleStartDate = now.minusHours(10);
+        final DateTime alignStartDate = bundleStartDate.plusHours(5);
+
+        final DefaultSubscriptionBase defaultSubscriptionBase = createSubscriptionStartedInThePast(bundleStartDate, alignStartDate, productName, initialPhase);
 
         // Look now, after the bundle and the subscription started
         final DateTime effectiveDate = clock.getUTCNow();
@@ -130,11 +139,11 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
         Assert.assertNull(newPhase);
     }
 
-    private DefaultSubscriptionBase createSubscriptionStartedInThePast(final String productName, final PhaseType phaseType) throws CatalogApiException {
+    private DefaultSubscriptionBase createSubscriptionStartedInThePast(final DateTime bundleStartDate, final DateTime alignStartDate, final String productName, final PhaseType phaseType) throws CatalogApiException {
         final SubscriptionBuilder builder = new SubscriptionBuilder();
-        builder.setBundleStartDate(clock.getUTCNow().minusHours(10));
+        builder.setBundleStartDate(bundleStartDate);
         // Make sure to set the dates apart
-        builder.setAlignStartDate(new DateTime(builder.getBundleStartDate().plusHours(5)));
+        builder.setAlignStartDate(new DateTime(alignStartDate));
 
         // Create the transitions
         final DefaultSubscriptionBase defaultSubscriptionBase = new DefaultSubscriptionBase(builder, null, clock);
@@ -205,7 +214,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
         // The date is used for different catalog versions - we don't care here
         final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(newProductName, clock.getUTCNow());
 
-        return planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, priceList, effectiveChangeDate, internalCallContext);
+        return planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
     }
 
     private TimedPhase[] getTimedPhasesOnCreate(final String productName,