killbill-memoizeit

Changes

Details

diff --git a/api/src/main/java/com/ning/billing/subscription/api/user/SubscriptionBaseBundle.java b/api/src/main/java/com/ning/billing/subscription/api/user/SubscriptionBaseBundle.java
index 074b5b5..e6281d4 100644
--- a/api/src/main/java/com/ning/billing/subscription/api/user/SubscriptionBaseBundle.java
+++ b/api/src/main/java/com/ning/billing/subscription/api/user/SubscriptionBaseBundle.java
@@ -18,6 +18,8 @@ package com.ning.billing.subscription.api.user;
 
 import java.util.UUID;
 
+import org.joda.time.DateTime;
+
 import com.ning.billing.entitlement.api.Blockable;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.util.entity.Entity;
@@ -27,4 +29,6 @@ public interface SubscriptionBaseBundle extends Blockable, Entity {
     public UUID getAccountId();
 
     public String getExternalKey();
+
+    public DateTime getOriginalCreatedDate();
 }
diff --git a/subscription/src/main/java/com/ning/billing/subscription/api/migration/DefaultSubscriptionBaseMigrationApi.java b/subscription/src/main/java/com/ning/billing/subscription/api/migration/DefaultSubscriptionBaseMigrationApi.java
index 3319348..5d655ac 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/api/migration/DefaultSubscriptionBaseMigrationApi.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/api/migration/DefaultSubscriptionBaseMigrationApi.java
@@ -89,7 +89,7 @@ public class DefaultSubscriptionBaseMigrationApi extends SubscriptionApiBase imp
 
         for (final BundleMigration curBundle : toBeMigrated.getBundles()) {
 
-            final DefaultSubscriptionBaseBundle bundleData = new DefaultSubscriptionBaseBundle(curBundle.getBundleKey(), accountId, clock.getUTCNow());
+            final DefaultSubscriptionBaseBundle bundleData = new DefaultSubscriptionBaseBundle(curBundle.getBundleKey(), accountId, now, now, now, now);
             final List<SubscriptionMigrationData> bundleSubscriptionData = new LinkedList<AccountMigrationData.SubscriptionMigrationData>();
 
             final List<SubscriptionMigration> sortedSubscriptions = Lists.newArrayList(curBundle.getSubscriptions());
diff --git a/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index 969bd76..dc0be3d 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -155,17 +155,22 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
 
     @Override
     public SubscriptionBaseBundle createBundleForAccount(final UUID accountId, final String bundleKey, final InternalCallContext context) throws SubscriptionBaseApiException {
-        final SubscriptionBaseBundle result = getActiveBundleForKeyNotException(bundleKey, context);
+
+        final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(bundleKey, context);
+        final SubscriptionBaseBundle result = getActiveBundleForKeyNotException(existingBundles, dao, clock, context);
         if (result != null) {
             throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_ACTIVE_BUNDLE_KEY_EXISTS, bundleKey);
         }
-        final DefaultSubscriptionBaseBundle bundle = new DefaultSubscriptionBaseBundle(bundleKey, accountId, clock.getUTCNow());
+        final DateTime now = clock.getUTCNow();
+        final DateTime originalCreatedDate = existingBundles.size() > 0 ? existingBundles.get(0).getCreatedDate() : now;
+        final DefaultSubscriptionBaseBundle bundle = new DefaultSubscriptionBaseBundle(bundleKey, accountId, now, originalCreatedDate, now, now);
         return dao.createSubscriptionBundle(bundle, context);
     }
 
     @Override
     public SubscriptionBaseBundle getBundleForAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) throws SubscriptionBaseApiException {
-        final SubscriptionBaseBundle result = dao.getSubscriptionBundleFromAccountAndKey(accountId, bundleKey, context);
+        final List<SubscriptionBaseBundle> bundlesForAccountAndKey = dao.getSubscriptionBundleFromAccountAndKey(accountId, bundleKey, context);
+        final SubscriptionBaseBundle result = getActiveBundleForKeyNotException(bundlesForAccountAndKey, dao, clock, context);
         if (result == null) {
             throw new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, bundleKey);
         }
@@ -185,16 +190,16 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
 
     @Override
     public SubscriptionBaseBundle getActiveBundleForKey(final String bundleKey, final InternalTenantContext context) throws SubscriptionBaseApiException  {
-        final SubscriptionBaseBundle result =  getActiveBundleForKeyNotException(bundleKey, context);
+        final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(bundleKey, context);
+
+        final SubscriptionBaseBundle result =  getActiveBundleForKeyNotException(existingBundles, dao, clock, context);
         if (result == null) {
             throw new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, bundleKey);
         }
         return result;
     }
 
-    private SubscriptionBaseBundle getActiveBundleForKeyNotException(final String bundleKey, final InternalTenantContext context)  {
-
-        final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(bundleKey, context);
+    public static SubscriptionBaseBundle getActiveBundleForKeyNotException(final List<SubscriptionBaseBundle> existingBundles, final SubscriptionDao dao, final Clock clock, final InternalTenantContext context)  {
         for (SubscriptionBaseBundle cur : existingBundles) {
             final List<SubscriptionBase> subscriptions = dao.getSubscriptions(cur.getId(), context);
             for (SubscriptionBase s : subscriptions) {
diff --git a/subscription/src/main/java/com/ning/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java b/subscription/src/main/java/com/ning/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
index c9b2098..ef55dbe 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
@@ -98,7 +98,8 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
     @Override
     public BundleBaseTimeline getBundleTimeline(final UUID accountId, final String bundleName, final TenantContext context)
             throws SubscriptionBaseRepairException {
-        final SubscriptionBaseBundle bundle = dao.getSubscriptionBundleFromAccountAndKey(accountId, bundleName, internalCallContextFactory.createInternalTenantContext(context));
+        final List<SubscriptionBaseBundle> bundles = dao.getSubscriptionBundleFromAccountAndKey(accountId, bundleName, internalCallContextFactory.createInternalTenantContext(context));
+        final SubscriptionBaseBundle bundle = bundles.size() > 0 ? bundles.get(bundles.size() - 1) : null;
         return getBundleTimelineInternal(bundle, bundleName + " [accountId= " + accountId.toString() + "]", context);
     }
 
diff --git a/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java b/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
index 25b6f2f..c06eb67 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
@@ -31,9 +31,11 @@ import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.Entitlement.EntitlementState;
 import com.ning.billing.subscription.api.SubscriptionApiBase;
+import com.ning.billing.subscription.api.SubscriptionBase;
 import com.ning.billing.subscription.api.SubscriptionBaseApiService;
 import com.ning.billing.subscription.api.migration.AccountMigrationData.BundleMigrationData;
 import com.ning.billing.subscription.api.migration.AccountMigrationData.SubscriptionMigrationData;
+import com.ning.billing.subscription.api.svcs.DefaultSubscriptionInternalApi;
 import com.ning.billing.subscription.api.timeline.BundleBaseTimeline;
 import com.ning.billing.subscription.api.timeline.SubscriptionBaseTimelineApi;
 import com.ning.billing.subscription.api.user.DefaultSubscriptionBase;
@@ -57,6 +59,7 @@ import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.clock.Clock;
+import com.ning.billing.util.callcontext.InternalTenantContext;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
@@ -201,7 +204,8 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
                 throw new SubscriptionBaseTransferApiException(ErrorCode.SUB_TRANSFER_INVALID_EFF_DATE, effectiveTransferDate);
             }
 
-            final SubscriptionBaseBundle bundle = dao.getSubscriptionBundleFromAccountAndKey(sourceAccountId, bundleKey, fromInternalCallContext);
+            final List<SubscriptionBaseBundle> bundlesForAccountAndKey = dao.getSubscriptionBundleFromAccountAndKey(sourceAccountId, bundleKey, fromInternalCallContext);
+            final SubscriptionBaseBundle bundle = DefaultSubscriptionInternalApi.getActiveBundleForKeyNotException(bundlesForAccountAndKey, dao, clock, fromInternalCallContext);
             if (bundle == null) {
                 throw new SubscriptionBaseTransferApiException(ErrorCode.SUB_CREATE_NO_BUNDLE, bundleKey);
             }
@@ -209,7 +213,8 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
             // Get the bundle timeline for the old account
             final BundleBaseTimeline bundleBaseTimeline = timelineApi.getBundleTimeline(bundle, context);
 
-            final DefaultSubscriptionBaseBundle subscriptionBundleData = new DefaultSubscriptionBaseBundle(bundleKey, destAccountId, effectiveTransferDate);
+            final DefaultSubscriptionBaseBundle subscriptionBundleData = new DefaultSubscriptionBaseBundle(bundleKey, destAccountId, effectiveTransferDate,
+                                                                                                           bundle.getOriginalCreatedDate(), clock.getUTCNow(), clock.getUTCNow());
             final List<SubscriptionMigrationData> subscriptionMigrationDataList = new LinkedList<SubscriptionMigrationData>();
 
             final List<TransferCancelData> transferCancelDataList = new LinkedList<TransferCancelData>();
@@ -276,4 +281,5 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
             throw new SubscriptionBaseTransferApiException(e);
         }
     }
+
 }
diff --git a/subscription/src/main/java/com/ning/billing/subscription/api/user/DefaultSubscriptionBaseBundle.java b/subscription/src/main/java/com/ning/billing/subscription/api/user/DefaultSubscriptionBaseBundle.java
index 581901d..1786123 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/api/user/DefaultSubscriptionBaseBundle.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/api/user/DefaultSubscriptionBaseBundle.java
@@ -28,18 +28,20 @@ public class DefaultSubscriptionBaseBundle extends EntityBase implements Subscri
     private final String key;
     private final UUID accountId;
     private final DateTime lastSysUpdateDate;
+    private final DateTime originalCreatedDate;
 
-    public DefaultSubscriptionBaseBundle(final String name, final UUID accountId, final DateTime startDate) {
-        this(UUID.randomUUID(), name, accountId, startDate);
+    public DefaultSubscriptionBaseBundle(final String name, final UUID accountId, final DateTime startDate, final DateTime originalCreatedDate,
+                                         final DateTime createdDate, final DateTime updatedDate) {
+        this(UUID.randomUUID(), name, accountId, startDate, originalCreatedDate, createdDate, updatedDate);
     }
 
-
-    public DefaultSubscriptionBaseBundle(final UUID id, final String key, final UUID accountId, final DateTime lastSysUpdate) {
-        // TODO add column in bundles table
-        super(id, null, null);
+    public DefaultSubscriptionBaseBundle(final UUID id, final String key, final UUID accountId, final DateTime lastSysUpdate, final DateTime originalCreatedDate,
+                                         final DateTime createdDate, final DateTime updatedDate) {
+        super(id, createdDate, updatedDate);
         this.key = key;
         this.accountId = accountId;
         this.lastSysUpdateDate = lastSysUpdate;
+        this.originalCreatedDate = originalCreatedDate;
     }
 
     @Override
@@ -48,6 +50,11 @@ public class DefaultSubscriptionBaseBundle extends EntityBase implements Subscri
     }
 
     @Override
+    public DateTime getOriginalCreatedDate() {
+        return originalCreatedDate;
+    }
+
+    @Override
     public UUID getAccountId() {
         return accountId;
     }
@@ -91,6 +98,9 @@ public class DefaultSubscriptionBaseBundle extends EntityBase implements Subscri
         if (lastSysUpdateDate != null ? !lastSysUpdateDate.equals(that.lastSysUpdateDate) : that.lastSysUpdateDate != null) {
             return false;
         }
+        if (originalCreatedDate != null ? !originalCreatedDate.equals(that.originalCreatedDate) : that.originalCreatedDate != null) {
+            return false;
+        }
         return true;
     }
 
@@ -100,6 +110,7 @@ public class DefaultSubscriptionBaseBundle extends EntityBase implements Subscri
         result = 31 * result + (key != null ? key.hashCode() : 0);
         result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
         result = 31 * result + (lastSysUpdateDate != null ? lastSysUpdateDate.hashCode() : 0);
+        result = 31 * result + (originalCreatedDate != null ? originalCreatedDate.hashCode() : 0);
         return result;
     }
 }
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java
index cb63bbc..8f6cc52 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java
@@ -43,7 +43,7 @@ public interface BundleSqlDao extends EntitySqlDao<SubscriptionBundleModelDao, S
                                         @BindBean final InternalCallContext context);
 
     @SqlQuery
-    public SubscriptionBundleModelDao getBundleFromAccountAndKey(@Bind("accountId") String accountId,
+    public List<SubscriptionBundleModelDao> getBundleFromAccountAndKey(@Bind("accountId") String accountId,
                                                                  @Bind("externalKey") String externalKey,
                                                                  @BindBean final InternalTenantContext context);
 
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java
index 42a2521..62f31c4 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java
@@ -118,12 +118,17 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
     }
 
     @Override
-    public SubscriptionBaseBundle getSubscriptionBundleFromAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
-        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<SubscriptionBaseBundle>() {
+    public List<SubscriptionBaseBundle> getSubscriptionBundleFromAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
+        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<SubscriptionBaseBundle>>() {
             @Override
-            public SubscriptionBaseBundle inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
-                final SubscriptionBundleModelDao bundle = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getBundleFromAccountAndKey(accountId.toString(), bundleKey, context);
-                return SubscriptionBundleModelDao.toSubscriptionbundle(bundle);
+            public List<SubscriptionBaseBundle> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+                final List<SubscriptionBundleModelDao> models = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getBundleFromAccountAndKey(accountId.toString(), bundleKey, context);
+                return new ArrayList<SubscriptionBaseBundle>(Collections2.transform(models, new Function<SubscriptionBundleModelDao, SubscriptionBaseBundle>() {
+                    @Override
+                    public SubscriptionBaseBundle apply(@Nullable final SubscriptionBundleModelDao input) {
+                        return SubscriptionBundleModelDao.toSubscriptionbundle(input);
+                    }
+                }));
             }
         });
     }
@@ -180,7 +185,8 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
 
                 final SubscriptionBundleModelDao model = new SubscriptionBundleModelDao(bundle);
                 entitySqlDaoWrapperFactory.become(BundleSqlDao.class).create(model, context);
-                return bundle;
+                final SubscriptionBundleModelDao result = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getById(bundle.getId().toString(), context);
+                return SubscriptionBundleModelDao.toSubscriptionbundle(result);
             }
         });
     }
@@ -286,6 +292,7 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
         return result;
     }
 
+    /*
     @Override
     public List<SubscriptionBase> getSubscriptionsForAccountAndKey(final UUID accountId,
                                                                final String bundleKey, final InternalTenantContext context) {
@@ -300,6 +307,7 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
             }
         });
     }
+    */
 
     @Override
     public void updateChargedThroughDate(final DefaultSubscriptionBase subscription, final InternalCallContext context) {
@@ -982,8 +990,8 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
 
         final DefaultSubscriptionBaseBundle bundleData = bundleTransferData.getData();
 
-        final SubscriptionBundleModelDao existingBundleModel = transBundleDao.getBundleFromAccountAndKey(bundleData.getAccountId().toString(), bundleData.getExternalKey(), context);
-        if (existingBundleModel != null) {
+        final List<SubscriptionBundleModelDao> existingBundleModels = transBundleDao.getBundleFromAccountAndKey(bundleData.getAccountId().toString(), bundleData.getExternalKey(), context);
+        if (existingBundleModels.size() != 0) {
             log.error(String.format("Attempted to create a bundle for account %s and key %s that already existed, skip...", bundleData.getAccountId().toString(), bundleData.getExternalKey()));
             return;
         }
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/model/SubscriptionBundleModelDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/model/SubscriptionBundleModelDao.java
index e480be9..0808b9f 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/model/SubscriptionBundleModelDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/model/SubscriptionBundleModelDao.java
@@ -31,19 +31,21 @@ public class SubscriptionBundleModelDao extends EntityBase implements EntityMode
     private String externalKey;
     private UUID accountId;
     private DateTime lastSysUpdateDate;
+    private DateTime originalCreatedDate;
 
     public SubscriptionBundleModelDao() { /* For the DAO mapper */ }
 
     public SubscriptionBundleModelDao(final UUID id, final String key, final UUID accountId, final DateTime lastSysUpdateDate,
-                                      final DateTime createdDate, final DateTime updateDate) {
+                                      final DateTime createdDate, DateTime originalCreatedDate, final DateTime updateDate) {
         super(id, createdDate, updateDate);
         this.externalKey = key;
         this.accountId = accountId;
         this.lastSysUpdateDate = lastSysUpdateDate;
+        this.originalCreatedDate = originalCreatedDate;
     }
 
     public SubscriptionBundleModelDao(final DefaultSubscriptionBaseBundle input) {
-        this(input.getId(), input.getExternalKey(), input.getAccountId(), input.getLastSysUpdateDate(), input.getCreatedDate(), input.getUpdatedDate());
+        this(input.getId(), input.getExternalKey(), input.getAccountId(), input.getLastSysUpdateDate(), input.getCreatedDate(), input.getOriginalCreatedDate(), input.getUpdatedDate());
     }
 
     public String getExternalKey() {
@@ -58,11 +60,15 @@ public class SubscriptionBundleModelDao extends EntityBase implements EntityMode
         return lastSysUpdateDate;
     }
 
+    public DateTime getOriginalCreatedDate() {
+        return originalCreatedDate;
+    }
+
     public static SubscriptionBaseBundle toSubscriptionbundle(final SubscriptionBundleModelDao src) {
         if (src == null) {
             return null;
         }
-        return new DefaultSubscriptionBaseBundle(src.getId(), src.getExternalKey(), src.getAccountId(), src.getLastSysUpdateDate());
+        return new DefaultSubscriptionBaseBundle(src.getId(), src.getExternalKey(), src.getAccountId(), src.getLastSysUpdateDate(), src.getOriginalCreatedDate(), src.getCreatedDate(), src.getUpdatedDate());
     }
 
     @Override
@@ -99,6 +105,9 @@ public class SubscriptionBundleModelDao extends EntityBase implements EntityMode
         if (lastSysUpdateDate != null ? !lastSysUpdateDate.equals(that.lastSysUpdateDate) : that.lastSysUpdateDate != null) {
             return false;
         }
+        if (originalCreatedDate != null ? !originalCreatedDate.equals(that.originalCreatedDate) : that.originalCreatedDate != null) {
+            return false;
+        }
 
         return true;
     }
@@ -109,6 +118,7 @@ public class SubscriptionBundleModelDao extends EntityBase implements EntityMode
         result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
         result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
         result = 31 * result + (lastSysUpdateDate != null ? lastSysUpdateDate.hashCode() : 0);
+        result = 31 * result + (originalCreatedDate != null ? originalCreatedDate.hashCode() : 0);
         return result;
     }
 
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java
index 3bee1ea..733047c 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java
@@ -224,11 +224,6 @@ public class RepairSubscriptionDao implements SubscriptionDao, RepairSubscriptio
     }
 
     @Override
-    public SubscriptionBaseBundle getSubscriptionBundleFromAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
-        throw new SubscriptionBaseError(NOT_IMPLEMENTED);
-    }
-
-    @Override
     public SubscriptionBaseBundle getSubscriptionBundleFromId(final UUID bundleId, final InternalTenantContext context) {
         throw new SubscriptionBaseError(NOT_IMPLEMENTED);
     }
@@ -259,12 +254,6 @@ public class RepairSubscriptionDao implements SubscriptionDao, RepairSubscriptio
     }
 
     @Override
-    public List<SubscriptionBase> getSubscriptionsForAccountAndKey(final UUID accountId,
-                                                               final String bundleKey, final InternalTenantContext context) {
-        throw new SubscriptionBaseError(NOT_IMPLEMENTED);
-    }
-
-    @Override
     public void updateChargedThroughDate(final DefaultSubscriptionBase subscription, final InternalCallContext context) {
         throw new SubscriptionBaseError(NOT_IMPLEMENTED);
     }
@@ -315,4 +304,9 @@ public class RepairSubscriptionDao implements SubscriptionDao, RepairSubscriptio
     public List<SubscriptionBaseBundle> getSubscriptionBundlesForKey(final String bundleKey, final InternalTenantContext context) {
         throw new SubscriptionBaseError(NOT_IMPLEMENTED);
     }
+
+    @Override
+    public List<SubscriptionBaseBundle> getSubscriptionBundleFromAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
+        throw new SubscriptionBaseError(NOT_IMPLEMENTED);
+    }
 }
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java
index cd93a2e..63711d9 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java
@@ -39,7 +39,7 @@ public interface SubscriptionDao {
 
     public List<SubscriptionBaseBundle> getSubscriptionBundlesForKey(String bundleKey, InternalTenantContext context);
 
-    public SubscriptionBaseBundle getSubscriptionBundleFromAccountAndKey(UUID accountId, String bundleKey, InternalTenantContext context);
+    public List<SubscriptionBaseBundle> getSubscriptionBundleFromAccountAndKey(UUID accountId, String bundleKey, InternalTenantContext context);
 
     public SubscriptionBaseBundle getSubscriptionBundleFromId(UUID bundleId, InternalTenantContext context);
 
@@ -57,7 +57,7 @@ public interface SubscriptionDao {
 
     public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(InternalTenantContext context);
 
-    public List<SubscriptionBase> getSubscriptionsForAccountAndKey(UUID accountId, String bundleKey, InternalTenantContext context);
+    //public List<SubscriptionBase> getSubscriptionsForAccountAndKey(UUID accountId, String bundleKey, InternalTenantContext context);
 
     // Update
     public void updateChargedThroughDate(DefaultSubscriptionBase subscription, InternalCallContext context);
diff --git a/subscription/src/main/resources/com/ning/billing/subscription/ddl.sql b/subscription/src/main/resources/com/ning/billing/subscription/ddl.sql
index 0e4c617..0dafa01 100644
--- a/subscription/src/main/resources/com/ning/billing/subscription/ddl.sql
+++ b/subscription/src/main/resources/com/ning/billing/subscription/ddl.sql
@@ -57,6 +57,7 @@ CREATE TABLE bundles (
     external_key varchar(64) NOT NULL,
     account_id char(36) NOT NULL,
     last_sys_update_date datetime,
+    original_created_date datetime NOT NULL,
     created_by varchar(50) NOT NULL,
     created_date datetime NOT NULL,
     updated_by varchar(50) NOT NULL,
diff --git a/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg b/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg
index 2ef637e..ddac7a5 100644
--- a/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg
+++ b/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg
@@ -7,6 +7,7 @@ tableFields(prefix) ::= <<
   <prefix>external_key
 , <prefix>account_id
 , <prefix>last_sys_update_date
+, <prefix>original_created_date
 , <prefix>created_by
 , <prefix>created_date
 , <prefix>updated_by
@@ -17,6 +18,7 @@ tableValues() ::= <<
   :externalKey
 , :accountId
 , :lastSysUpdateDate
+, :originalCreatedDate
 , :createdBy
 , :createdDate
 , :updatedBy
@@ -40,6 +42,7 @@ from bundles
 where
 external_key = :externalKey
 <AND_CHECK_TENANT()>
+order by record_id asc
 ;
 >>
 
@@ -50,6 +53,7 @@ where
 external_key = :externalKey
 and account_id = :accountId
 <AND_CHECK_TENANT()>
+order by record_id asc
 ;
 >>
 
@@ -59,5 +63,6 @@ from bundles
 where
 account_id = :accountId
 <AND_CHECK_TENANT()>
+order by record_id asc
 ;
 >>
diff --git a/subscription/src/test/java/com/ning/billing/subscription/api/transfer/TestTransfer.java b/subscription/src/test/java/com/ning/billing/subscription/api/transfer/TestTransfer.java
index 941533e..44f8256 100644
--- a/subscription/src/test/java/com/ning/billing/subscription/api/transfer/TestTransfer.java
+++ b/subscription/src/test/java/com/ning/billing/subscription/api/transfer/TestTransfer.java
@@ -41,6 +41,7 @@ import com.ning.billing.subscription.api.SubscriptionBaseTransitionType;
 import com.ning.billing.subscription.api.SubscriptionBase;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
@@ -69,6 +70,8 @@ public class TestTransfer extends SubscriptionTestSuiteWithEmbeddedDB {
             assertEquals(bundles.size(), 1);
             final SubscriptionBaseBundle bundle = bundles.get(0);
 
+            final DateTime bundleCreatedDate = bundle.getCreatedDate();
+
             final List<SubscriptionBase> subscriptions = subscriptionInternalApi.getSubscriptionsForBundle(bundle.getId(), internalCallContext);
             assertEquals(subscriptions.size(), 1);
             final SubscriptionBase subscription = subscriptions.get(0);
@@ -102,6 +105,10 @@ public class TestTransfer extends SubscriptionTestSuiteWithEmbeddedDB {
             assertEquals(subscriptionInternalApi.getBillingTransitions(oldBaseSubscription, internalCallContext).size(), 0);
             //assertEquals(subscriptionInternalApi.getBillingTransitions(oldBaseSubscription, internalCallContext).get(0).getTransitionType(), SubscriptionBaseTransitionType.CANCEL);
 
+            final SubscriptionBaseBundle newBundle = subscriptionInternalApi.getActiveBundleForKey(bundle.getExternalKey(), internalCallContext);
+            assertNotEquals(newBundle.getId(), bundle.getId());
+            assertEquals(newBundle.getOriginalCreatedDate().compareTo(bundleCreatedDate), 0);
+
         } catch (SubscriptionBaseMigrationApiException e) {
             Assert.fail("", e);
         }
diff --git a/subscription/src/test/java/com/ning/billing/subscription/api/user/TestUserApiCreate.java b/subscription/src/test/java/com/ning/billing/subscription/api/user/TestUserApiCreate.java
index 58a0b61..c2b5dc8 100644
--- a/subscription/src/test/java/com/ning/billing/subscription/api/user/TestUserApiCreate.java
+++ b/subscription/src/test/java/com/ning/billing/subscription/api/user/TestUserApiCreate.java
@@ -64,6 +64,7 @@ public class TestUserApiCreate extends SubscriptionTestSuiteWithEmbeddedDB {
 
             try {
                 final SubscriptionBaseBundle newBundle = subscriptionInternalApi.createBundleForAccount(bundle.getAccountId(), DefaultSubscriptionTestInitializer.DEFAULT_BUNDLE_KEY, internalCallContext);
+
                 Assert.fail("Unexpected success to create a bundle");
             } catch (SubscriptionBaseApiException e) {
                 Assert.assertEquals(e.getCode(), ErrorCode.SUB_CREATE_ACTIVE_BUNDLE_KEY_EXISTS.getCode());
@@ -73,9 +74,10 @@ public class TestUserApiCreate extends SubscriptionTestSuiteWithEmbeddedDB {
 
             final SubscriptionBaseBundle newBundle = subscriptionInternalApi.createBundleForAccount(bundle.getAccountId(), DefaultSubscriptionTestInitializer.DEFAULT_BUNDLE_KEY, internalCallContext);
             assertNotNull(newBundle);
+            assertEquals(newBundle.getOriginalCreatedDate().compareTo(bundle.getCreatedDate()), 0);
 
             final DefaultSubscriptionBase newSubscription = (DefaultSubscriptionBase) subscriptionInternalApi.createSubscription(newBundle.getId(),
-                                                                                                                              testUtil.getProductSpecifier(productName, planSetName, term, null), requestedDate, internalCallContext);
+                                                                                                                                 testUtil.getProductSpecifier(productName, planSetName, term, null), requestedDate, internalCallContext);
             assertNotNull(newSubscription);
 
 
diff --git a/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java b/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
index e4b2eeb..c0d47e2 100644
--- a/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
+++ b/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
@@ -125,13 +125,14 @@ public class MockSubscriptionDaoMemory implements SubscriptionDao {
     }
 
     @Override
-    public SubscriptionBaseBundle getSubscriptionBundleFromAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
+    public List<SubscriptionBaseBundle> getSubscriptionBundleFromAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
+        final List<SubscriptionBaseBundle> results = new ArrayList<SubscriptionBaseBundle>();
         for (final SubscriptionBaseBundle cur : bundles) {
             if (cur.getExternalKey().equals(bundleKey) && cur.getAccountId().equals(accountId)) {
-                return cur;
+                results.add(cur);
             }
         }
-        return null;
+        return results;
     }
 
     @Override
@@ -155,6 +156,7 @@ public class MockSubscriptionDaoMemory implements SubscriptionDao {
         throw new UnsupportedOperationException();
     }
 
+    /*
     @Override
     public List<SubscriptionBase> getSubscriptionsForAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
 
@@ -165,6 +167,7 @@ public class MockSubscriptionDaoMemory implements SubscriptionDao {
         }
         return Collections.emptyList();
     }
+    */
 
     @Override
     public void createSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> initialEvents,