killbill-memoizeit

#219 - Updating methods to return the new SubscriptionBaseWithAddOns

11/9/2016 6:35:30 PM

Details

diff --git a/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java b/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java
index 4beaf36..7d2c57a 100644
--- a/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java
+++ b/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java
@@ -40,6 +40,7 @@ import org.killbill.billing.events.EffectiveSubscriptionInternalEvent;
 import org.killbill.billing.invoice.api.DryRunArguments;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
+import org.killbill.billing.subscription.api.user.SubscriptionBaseWithAddOns;
 import org.killbill.billing.util.entity.Pagination;
 
 public interface SubscriptionBaseInternalApi {
@@ -48,8 +49,8 @@ public interface SubscriptionBaseInternalApi {
     public SubscriptionBase createSubscription(UUID bundleId, PlanPhaseSpecifier spec, List<PlanPhasePriceOverride> overrides, DateTime requestedDateWithMs,
                                                final boolean isMigrated, InternalCallContext context) throws SubscriptionBaseApiException;
 
-    public List<SubscriptionBase> createBaseSubscriptionsWithAddOns(UUID accountId, Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifier,
-                                                                    InternalCallContext contextWithValidAccountRecordId) throws SubscriptionBaseApiException;
+    public List<SubscriptionBaseWithAddOns> createBaseSubscriptionsWithAddOns(UUID accountId, Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifier,
+                                                                              InternalCallContext contextWithValidAccountRecordId) throws SubscriptionBaseApiException;
 
     public void cancelBaseSubscriptions(Iterable<SubscriptionBase> subscriptions, BillingActionPolicy policy, InternalCallContext context) throws SubscriptionBaseApiException;
 
diff --git a/api/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseWithAddOns.java b/api/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseWithAddOns.java
new file mode 100644
index 0000000..6d586dd
--- /dev/null
+++ b/api/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseWithAddOns.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.subscription.api.user;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.subscription.api.SubscriptionBase;
+
+public interface SubscriptionBaseWithAddOns {
+
+    public UUID getBundleId();
+
+    public List<SubscriptionBase> getSubscriptionBaseList();
+
+    public DateTime getEffectiveDate();
+}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
index fb8f48a..4a0b360 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
@@ -57,6 +57,7 @@ import org.killbill.billing.subscription.api.transfer.SubscriptionBaseTransferAp
 import org.killbill.billing.subscription.api.transfer.SubscriptionBaseTransferApiException;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
+import org.killbill.billing.subscription.api.user.SubscriptionBaseWithAddOns;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.billing.util.callcontext.TenantContext;
@@ -190,14 +191,14 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
     }
 
     @Override
-    public List<Entitlement> createBaseEntitlementsWithAddOns(final UUID accountId, final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementSpecifiersWithAddOns, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
+    public List<Entitlement> createBaseEntitlementsWithAddOns(final UUID accountId, final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
-        logCreateEntitlementsWithAOs(log, baseEntitlementSpecifiersWithAddOns);
+        logCreateEntitlementsWithAOs(log, baseEntitlementWithAddOnsSpecifiers);
 
         final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CREATE_SHOPPING_CART_SUBSCRIPTIONS,
                                                                                accountId,
                                                                                null,
-                                                                               baseEntitlementSpecifiersWithAddOns,
+                                                                               baseEntitlementWithAddOnsSpecifiers,
                                                                                null,
                                                                                properties,
                                                                                callContext);
@@ -208,15 +209,20 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
                 final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext);
 
                 try {
-                    final List<SubscriptionBase> subscriptionsWithAddOns = subscriptionBaseInternalApi.createBaseSubscriptionsWithAddOns(accountId, baseEntitlementSpecifiersWithAddOns, contextWithValidAccountRecordId);
+                    final List<SubscriptionBaseWithAddOns> subscriptionsWithAddOns = subscriptionBaseInternalApi.createBaseSubscriptionsWithAddOns(accountId, baseEntitlementWithAddOnsSpecifiers, contextWithValidAccountRecordId);
                     final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
-                    for (final SubscriptionBase cur : subscriptionsWithAddOns) {
-                        final BlockingState blockingState = new DefaultBlockingState(cur.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_START, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false,
-                                                                                     dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers().iterator().next().getEntitlementEffectiveDate(), contextWithValidAccountRecordId));
-                        blockingStates.add(blockingState);
+                    final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = Lists.newArrayList(baseEntitlementWithAddOnsSpecifiers.iterator());
+                    for (final SubscriptionBaseWithAddOns cur : subscriptionsWithAddOns) {
+                        for (SubscriptionBase subscriptionBase : cur.getSubscriptionBaseList()) {
+                            final BlockingState blockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION,
+                                                                                         DefaultEntitlementApi.ENT_STATE_START,
+                                                                                         EntitlementService.ENTITLEMENT_SERVICE_NAME,
+                                                                                         false, false, false,
+                                                                                         dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifierList.get(subscriptionsWithAddOns.indexOf(cur)).getEntitlementEffectiveDate(), contextWithValidAccountRecordId));
+                            blockingStates.add(blockingState);
+                        }
+                        entitlementUtils.setBlockingStatesAndPostBlockingTransitionEvent(blockingStates, cur.getBundleId(), contextWithValidAccountRecordId);
                     }
-                    entitlementUtils.setBlockingStatesAndPostBlockingTransitionEvent(blockingStates, subscriptionsWithAddOns.get(0).getBundleId(), contextWithValidAccountRecordId);
-
                     return buildEntitlementList(accountId, subscriptionsWithAddOns, callContext);
                 } catch (final SubscriptionBaseApiException e) {
                     throw new EntitlementApiException(e);
@@ -226,13 +232,15 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
         return pluginExecution.executeWithPlugin(createBaseEntitlementsWithAddOns, pluginContext);
     }
 
-    private List<Entitlement> buildEntitlementList(final UUID accountId, final List<SubscriptionBase> subscriptionsWithAddOns, final CallContext callContext) throws EntitlementApiException {
+    private List<Entitlement> buildEntitlementList(final UUID accountId, final List<SubscriptionBaseWithAddOns> subscriptionsWithAddOns, final CallContext callContext) throws EntitlementApiException {
         List<Entitlement> result = new ArrayList<Entitlement>();
-        for (SubscriptionBase subscriptionWithAddOns : subscriptionsWithAddOns) {
-            Entitlement entitlement = new DefaultEntitlement(accountId, subscriptionWithAddOns.getId(), eventsStreamBuilder, entitlementApi, pluginExecution,
-                                                             blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService,
-                                                             entitlementUtils, dateHelper, clock, securityApi, internalCallContextFactory, callContext);
-            result.add(entitlement);
+        for (SubscriptionBaseWithAddOns subscriptionWithAddOns : subscriptionsWithAddOns) {
+            for (SubscriptionBase subscriptionBase : subscriptionWithAddOns.getSubscriptionBaseList()) {
+                Entitlement entitlement = new DefaultEntitlement(accountId, subscriptionBase.getId(), eventsStreamBuilder, entitlementApi, pluginExecution,
+                                                                 blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService,
+                                                                 entitlementUtils, dateHelper, clock, securityApi, internalCallContextFactory, callContext);
+                result.add(entitlement);
+            }
         }
         return result;
     }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java
index 40d5060..d1991cd 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java
@@ -32,6 +32,7 @@ import org.killbill.billing.catalog.api.PlanChangeResult;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
 import org.killbill.billing.catalog.api.PlanSpecifier;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
+import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseWithAddOns;
 import org.killbill.billing.subscription.api.user.SubscriptionAndAddOnsSpecifier;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
 import org.killbill.billing.subscription.api.user.SubscriptionBuilder;
@@ -46,7 +47,7 @@ public interface SubscriptionBaseApiService {
                                               CallContext context)
             throws SubscriptionBaseApiException;
 
-    public List<DefaultSubscriptionBase> createPlansWithAddOns(UUID accountId, Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, CallContext context)
+    public List<DefaultSubscriptionBaseWithAddOns> createPlansWithAddOns(UUID accountId, Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, CallContext context)
             throws SubscriptionBaseApiException;
 
     public boolean cancel(DefaultSubscriptionBase subscription, CallContext context)
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index 015d87d..ff22127 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -63,12 +63,14 @@ import org.killbill.billing.subscription.api.user.DefaultEffectiveSubscriptionEv
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseApiService;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
+import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseWithAddOns;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionStatusDryRun;
 import org.killbill.billing.subscription.api.user.SubscriptionAndAddOnsSpecifier;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseTransition;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseTransitionData;
+import org.killbill.billing.subscription.api.user.SubscriptionBaseWithAddOns;
 import org.killbill.billing.subscription.api.user.SubscriptionBuilder;
 import org.killbill.billing.subscription.api.user.SubscriptionSpecifier;
 import org.killbill.billing.subscription.engine.addon.AddonUtils;
@@ -254,7 +256,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
     }
 
     @Override
-    public List<SubscriptionBase> createBaseSubscriptionsWithAddOns(final UUID accountId, final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifier, final InternalCallContext context) throws SubscriptionBaseApiException {
+    public List<SubscriptionBaseWithAddOns> createBaseSubscriptionsWithAddOns(final UUID accountId, final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifier, final InternalCallContext context) throws SubscriptionBaseApiException {
         try {
             final Catalog catalog = catalogService.getFullCatalog(true, true, context);
             final CallContext callContext = internalCallContextFactory.createCallContext(context);
@@ -267,24 +269,25 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
 
                 final SubscriptionBaseBundle bundle = createBundleForAccount(accountId, entitlementWithAddOnsSpecifier.getExternalKey(), context);
 
-                final List<SubscriptionSpecifier> subscriptions = verifyAndBuildSubscriptionSpecifiers(bundle.getId(),
-                                                                                                       entitlementWithAddOnsSpecifier.getEntitlementSpecifier(),
-                                                                                                       entitlementWithAddOnsSpecifier.isMigrated(),
-                                                                                                       context,
-                                                                                                       now,
-                                                                                                       effectiveDate,
-                                                                                                       catalog,
-                                                                                                       callContext);
-
-                SubscriptionAndAddOnsSpecifier subscriptionAndAddOnsSpecifier = new SubscriptionAndAddOnsSpecifier();
-                subscriptionAndAddOnsSpecifier.setSubscriptionSpecifiers(subscriptions);
+                SubscriptionAndAddOnsSpecifier subscriptionAndAddOnsSpecifier = new SubscriptionAndAddOnsSpecifier(
+                        bundle.getId(),
+                        effectiveDate,
+                        verifyAndBuildSubscriptionSpecifiers(bundle.getId(),
+                                                             entitlementWithAddOnsSpecifier.getEntitlementSpecifier(),
+                                                             entitlementWithAddOnsSpecifier.isMigrated(),
+                                                             context,
+                                                             now,
+                                                             effectiveDate,
+                                                             catalog,
+                                                             callContext)
+                );
                 subscriptionAndAddOns.add(subscriptionAndAddOnsSpecifier);
             }
 
-            final List<DefaultSubscriptionBase> result = apiService.createPlansWithAddOns(accountId, subscriptionAndAddOns, callContext);
-            return ImmutableList.copyOf(Iterables.transform(result, new Function<DefaultSubscriptionBase, SubscriptionBase>() {
+            final List<DefaultSubscriptionBaseWithAddOns> result = apiService.createPlansWithAddOns(accountId, subscriptionAndAddOns, callContext);
+            return ImmutableList.copyOf(Iterables.transform(result, new Function<DefaultSubscriptionBaseWithAddOns, SubscriptionBaseWithAddOns>() {
                 @Override
-                public SubscriptionBase apply(final DefaultSubscriptionBase input) {
+                public SubscriptionBaseWithAddOns apply(final DefaultSubscriptionBaseWithAddOns input) {
                     return input;
                 }
             }));
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 8b5d0b6..0cd9ce2 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
@@ -70,6 +70,7 @@ import org.killbill.billing.util.callcontext.TenantContext;
 import org.killbill.clock.Clock;
 import org.killbill.clock.DefaultClock;
 
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -117,16 +118,27 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
     }
 
     @Override
-    public List<DefaultSubscriptionBase> createPlansWithAddOns(final UUID accountId, final Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, final CallContext context) throws SubscriptionBaseApiException {
+    public List<DefaultSubscriptionBaseWithAddOns> createPlansWithAddOns(final UUID accountId, final Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, final CallContext context) throws SubscriptionBaseApiException {
         Map<UUID, List<SubscriptionBaseEvent>> eventsMap = new HashMap<UUID, List<SubscriptionBaseEvent>>();
         List<List<DefaultSubscriptionBase>> subscriptionBaseAndAddOnsList = new ArrayList<List<DefaultSubscriptionBase>>();
-        List<DefaultSubscriptionBase> allSubscriptions = new ArrayList<DefaultSubscriptionBase>();
+        List<DefaultSubscriptionBaseWithAddOns> allSubscriptions = new ArrayList<DefaultSubscriptionBaseWithAddOns>();
 
         for (SubscriptionAndAddOnsSpecifier subscriptionAndAddOns : subscriptionsAndAddOns) {
             List<DefaultSubscriptionBase> subscriptionBaseList = new ArrayList<DefaultSubscriptionBase>();
             createEvents(subscriptionAndAddOns.getSubscriptionSpecifiers(), context, eventsMap, subscriptionBaseList);
+
             subscriptionBaseAndAddOnsList.add(subscriptionBaseList);
-            allSubscriptions.addAll(subscriptionBaseList);
+
+            DefaultSubscriptionBaseWithAddOns defaultSubscriptionBaseWithAddOns = new DefaultSubscriptionBaseWithAddOns(
+                    subscriptionAndAddOns.getBundleId(),
+                    ImmutableList.copyOf(Iterables.transform(subscriptionBaseList, new Function<DefaultSubscriptionBase, SubscriptionBase>() {
+                        @Override
+                        public SubscriptionBase apply(final DefaultSubscriptionBase input) {
+                            return input;
+                        }
+                    })),
+                    subscriptionAndAddOns.getEffectiveDate());
+            allSubscriptions.add(defaultSubscriptionBaseWithAddOns);
         }
 
         final InternalCallContext internalCallContext = createCallContextFromAccountId(accountId, context);
@@ -176,9 +188,9 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
     }
 
     private DefaultSubscriptionBase findBaseSubscription(final List<DefaultSubscriptionBase> subscriptionBaseList) {
-        return Iterables.tryFind(subscriptionBaseList, new Predicate<DefaultSubscriptionBase>() {
+        return Iterables.tryFind(subscriptionBaseList, new Predicate<SubscriptionBase>() {
             @Override
-            public boolean apply(final DefaultSubscriptionBase subscription) {
+            public boolean apply(final SubscriptionBase subscription) {
                 return ProductCategory.BASE.equals(subscription.getCategory());
             }
         }).orNull();
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseWithAddOns.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseWithAddOns.java
new file mode 100644
index 0000000..841bbb2
--- /dev/null
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseWithAddOns.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.subscription.api.user;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.subscription.api.SubscriptionBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultSubscriptionBaseWithAddOns implements SubscriptionBaseWithAddOns {
+
+    private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionBaseWithAddOns.class);
+
+    private final UUID bundleId;
+    private final List<SubscriptionBase> subscriptionBaseList;
+    private final DateTime effectiveDate;
+
+    public DefaultSubscriptionBaseWithAddOns(final UUID bundleId, final List<SubscriptionBase> subscriptionBaseList, final DateTime effectiveDate) {
+        this.bundleId = bundleId;
+        this.subscriptionBaseList = subscriptionBaseList;
+        this.effectiveDate = effectiveDate;
+    }
+
+    @Override
+    public UUID getBundleId() {
+        return bundleId;
+    }
+
+    @Override
+    public List<SubscriptionBase> getSubscriptionBaseList() {
+        return subscriptionBaseList;
+    }
+
+    public DateTime getEffectiveDate() {
+        return effectiveDate;
+    }
+}
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionAndAddOnsSpecifier.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionAndAddOnsSpecifier.java
index 9d9af7c..549335e 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionAndAddOnsSpecifier.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionAndAddOnsSpecifier.java
@@ -17,18 +17,34 @@
 package org.killbill.billing.subscription.api.user;
 
 import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
 
 public class SubscriptionAndAddOnsSpecifier {
 
+    private UUID bundleId;
+    private DateTime effectiveDate;
     private List<SubscriptionSpecifier> subscriptionSpecifiers;
 
     public SubscriptionAndAddOnsSpecifier() {
     }
 
-    public SubscriptionAndAddOnsSpecifier(final List<SubscriptionSpecifier> subscriptionSpecifiers) {
+    public SubscriptionAndAddOnsSpecifier(final UUID bundleId, final DateTime effectiveDate,
+                                          final List<SubscriptionSpecifier> subscriptionSpecifiers) {
+        this.bundleId = bundleId;
+        this.effectiveDate = effectiveDate;
         this.subscriptionSpecifiers = subscriptionSpecifiers;
     }
 
+    public UUID getBundleId() {
+        return bundleId;
+    }
+
+    public DateTime getEffectiveDate() {
+        return effectiveDate;
+    }
+
     public List<SubscriptionSpecifier> getSubscriptionSpecifiers() {
         return subscriptionSpecifiers;
     }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
index 9939d8d..81df1b3 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
@@ -54,6 +54,7 @@ import org.killbill.billing.subscription.api.user.DefaultEffectiveSubscriptionEv
 import org.killbill.billing.subscription.api.user.DefaultRequestedSubscriptionEvent;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
+import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseWithAddOns;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseTransitionData;
 import org.killbill.billing.subscription.api.user.SubscriptionBuilder;
@@ -513,27 +514,34 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
     }
 
     @Override
-    public void createSubscriptionsWithAddOns(final List<DefaultSubscriptionBase> subscriptions, final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, final InternalCallContext context) {
+    public void createSubscriptionsWithAddOns(final List<DefaultSubscriptionBaseWithAddOns> subscriptions, final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, final InternalCallContext context) {
         transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
                 final SubscriptionSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class);
                 final SubscriptionEventSqlDao eventsDaoFromSameTransaction = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
+                for (DefaultSubscriptionBaseWithAddOns subscription : subscriptions) {
+                    List<DefaultSubscriptionBase> currentSubscriptionBaseList = ImmutableList.copyOf(Iterables.transform(subscription.getSubscriptionBaseList(), new Function<SubscriptionBase, DefaultSubscriptionBase>() {
+                        @Override
+                        public DefaultSubscriptionBase apply(final SubscriptionBase input) {
+                            return (DefaultSubscriptionBase) input;
+                        }
+                    }));
+                    for (DefaultSubscriptionBase subscriptionBase : currentSubscriptionBaseList) {
+                        transactional.create(new SubscriptionModelDao(subscriptionBase), context);
 
-                for (DefaultSubscriptionBase subscription : subscriptions) {
-                    transactional.create(new SubscriptionModelDao(subscription), context);
-
-                    final List<SubscriptionBaseEvent> initialEvents = initialEventsMap.get(subscription.getId());
-                    for (final SubscriptionBaseEvent cur : initialEvents) {
-                        eventsDaoFromSameTransaction.create(new SubscriptionEventModelDao(cur), context);
+                        final List<SubscriptionBaseEvent> initialEvents = initialEventsMap.get(subscriptionBase.getId());
+                        for (final SubscriptionBaseEvent cur : initialEvents) {
+                            eventsDaoFromSameTransaction.create(new SubscriptionEventModelDao(cur), context);
 
-                        final boolean isBusEvent = cur.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 && (cur.getType() == EventType.API_USER);
-                        recordBusOrFutureNotificationFromTransaction(subscription, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, context);
+                            final boolean isBusEvent = cur.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 && (cur.getType() == EventType.API_USER);
+                            recordBusOrFutureNotificationFromTransaction(subscriptionBase, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, context);
 
-                    }
-                    // Notify the Bus of the latest requested change, if needed
-                    if (initialEvents.size() > 0) {
-                        notifyBusOfRequestedChange(entitySqlDaoWrapperFactory, subscription, initialEvents.get(initialEvents.size() - 1), SubscriptionBaseTransitionType.CREATE, context);
+                        }
+                        // Notify the Bus of the latest requested change, if needed
+                        if (initialEvents.size() > 0) {
+                            notifyBusOfRequestedChange(entitySqlDaoWrapperFactory, subscriptionBase, initialEvents.get(initialEvents.size() - 1), SubscriptionBaseTransitionType.CREATE, context);
+                        }
                     }
                 }
                 return null;
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
index b908c73..7c5743d 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
@@ -29,6 +29,7 @@ import org.killbill.billing.subscription.api.transfer.BundleTransferData;
 import org.killbill.billing.subscription.api.transfer.TransferCancelData;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
+import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseWithAddOns;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
 import org.killbill.billing.subscription.engine.dao.model.SubscriptionBundleModelDao;
 import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
@@ -81,7 +82,7 @@ public interface SubscriptionDao extends EntityDao<SubscriptionBundleModelDao, S
     // SubscriptionBase creation, cancellation, changePlanWithRequestedDate apis
     public void createSubscription(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> initialEvents, InternalCallContext context);
 
-    public void createSubscriptionsWithAddOns(List<DefaultSubscriptionBase> subscriptions, Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, InternalCallContext context);
+    public void createSubscriptionsWithAddOns(List<DefaultSubscriptionBaseWithAddOns> subscriptions, Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, InternalCallContext context);
 
     public void cancelSubscriptionsOnBasePlanEvent(DefaultSubscriptionBase subscription, SubscriptionBaseEvent event, List<DefaultSubscriptionBase> subscriptions, List<SubscriptionBaseEvent> cancelEvents, InternalCallContext context);
 
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
index d6af5ce..d2306f1 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
@@ -43,6 +43,7 @@ import org.killbill.billing.subscription.api.transfer.TransferCancelData;
 import org.killbill.billing.subscription.api.user.DefaultEffectiveSubscriptionEvent;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
+import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseWithAddOns;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseTransitionData;
 import org.killbill.billing.subscription.api.user.SubscriptionBuilder;
@@ -68,6 +69,9 @@ import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificatio
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.google.inject.Inject;
 
 public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBundleModelDao, SubscriptionBaseBundle, SubscriptionApiException> implements SubscriptionDao {
@@ -220,19 +224,27 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
         mockNonEntityDao.addTenantRecordIdMapping(updatedSubscription.getId(), context);
     }
 
-    public void createSubscriptionsWithAddOns(final List<DefaultSubscriptionBase> subscriptions,
+    public void createSubscriptionsWithAddOns(final List<DefaultSubscriptionBaseWithAddOns> subscriptions,
                                               final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap,
                                               final InternalCallContext context) {
         synchronized (events) {
-            for (DefaultSubscriptionBase subscription : subscriptions) {
-                final List<SubscriptionBaseEvent> initialEvents = initialEventsMap.get(subscription.getId());
-                events.addAll(initialEvents);
-                for (final SubscriptionBaseEvent cur : initialEvents) {
-                    recordFutureNotificationFromTransaction(null, cur.getEffectiveDate(), new SubscriptionNotificationKey(cur.getId()), context);
+            for (DefaultSubscriptionBaseWithAddOns subscription : subscriptions) {
+                List<DefaultSubscriptionBase> currentSubscriptionBaseList = ImmutableList.copyOf(Iterables.transform(subscription.getSubscriptionBaseList(), new Function<SubscriptionBase, DefaultSubscriptionBase>() {
+                    @Override
+                    public DefaultSubscriptionBase apply(final SubscriptionBase input) {
+                        return (DefaultSubscriptionBase) input;
+                    }
+                }));
+                for (DefaultSubscriptionBase subscriptionBase : currentSubscriptionBaseList) {
+                    final List<SubscriptionBaseEvent> initialEvents = initialEventsMap.get(subscriptionBase.getId());
+                    events.addAll(initialEvents);
+                    for (final SubscriptionBaseEvent cur : initialEvents) {
+                        recordFutureNotificationFromTransaction(null, cur.getEffectiveDate(), new SubscriptionNotificationKey(cur.getId()), context);
+                    }
+                    final SubscriptionBase updatedSubscription = buildSubscription(subscriptionBase, context);
+                    this.subscriptions.add(updatedSubscription);
+                    mockNonEntityDao.addTenantRecordIdMapping(updatedSubscription.getId(), context);
                 }
-                final SubscriptionBase updatedSubscription = buildSubscription(subscription, context);
-                this.subscriptions.add(updatedSubscription);
-                mockNonEntityDao.addTenantRecordIdMapping(updatedSubscription.getId(), context);
             }
         }
     }