killbill-memoizeit

analytics: store subscription_id in bst This will be useful

6/29/2012 6:24:41 PM

Details

diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
index 49d6a9d..feaac55 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
@@ -17,6 +17,7 @@
 package com.ning.billing.analytics;
 
 import java.util.List;
+import java.util.UUID;
 
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
@@ -131,12 +132,14 @@ public class BusinessSubscriptionTransitionRecorder {
             nextSubscription = new BusinessSubscription(transition.getNextPriceList(), transition.getNextPlan(), transition.getNextPhase(), currency, transition.getEffectiveTransitionTime(), transition.getNextState(), transition.getSubscriptionId(), transition.getBundleId(), catalogService.getFullCatalog());
         }
 
-        record(transition.getTotalOrdering(), externalKey, accountKey, transition.getRequestedTransitionTime(), event, prevSubscription, nextSubscription);
+        record(transition.getSubscriptionId(), transition.getTotalOrdering(), externalKey, accountKey, transition.getRequestedTransitionTime(), event, prevSubscription, nextSubscription);
     }
 
     // Public for internal reasons
-    public void record(final Long totalOrdering, final String externalKey, final String accountKey, final DateTime requestedDateTime, final BusinessSubscriptionEvent event, final BusinessSubscription prevSubscription, final BusinessSubscription nextSubscription) {
+    public void record(final UUID subscriptionId, final Long totalOrdering, final String externalKey, final String accountKey, final DateTime requestedDateTime,
+                       final BusinessSubscriptionEvent event, final BusinessSubscription prevSubscription, final BusinessSubscription nextSubscription) {
         final BusinessSubscriptionTransition transition = new BusinessSubscriptionTransition(
+                subscriptionId,
                 totalOrdering,
                 externalKey,
                 accountKey,
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
index 9e5b507..e533661 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
@@ -39,6 +39,7 @@ public @interface BusinessSubscriptionTransitionBinder {
         public Binder build(final Annotation annotation) {
             return new Binder<BusinessSubscriptionTransitionBinder, BusinessSubscriptionTransition>() {
                 public void bind(final SQLStatement q, final BusinessSubscriptionTransitionBinder bind, final BusinessSubscriptionTransition arg) {
+                    q.bind("subscription_id", arg.getSubscriptionId().toString());
                     q.bind("total_ordering", arg.getTotalOrdering());
                     q.bind("external_key", arg.getExternalKey());
                     q.bind("account_key", arg.getAccountKey());
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
index c5bdf96..e5c442b 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
@@ -37,20 +37,20 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
     @Override
     public BusinessSubscriptionTransition map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
         BusinessSubscription prev = new BusinessSubscription(
-                r.getString(6), // productName
-                r.getString(7), // productType
-                r.getString(8) == null ? null : ProductCategory.valueOf(r.getString(8)), // productCategory
-                r.getString(9), // slug
-                r.getString(10),  // phase
-                r.getString(11),  // billing period
-                BigDecimal.valueOf(r.getDouble(12)), // price
-                r.getString(13), // priceList
-                BigDecimal.valueOf(r.getDouble(14)), // mrr
-                r.getString(15), // currency
-                r.getLong(16) == 0 ? null : new DateTime(r.getLong(16), DateTimeZone.UTC), // startDate
-                r.getString(17) == null ? null : SubscriptionState.valueOf(r.getString(17)), // state
-                r.getString(18) == null ? null : UUID.fromString(r.getString(18)), // subscriptionId
-                r.getString(19) == null ? null : UUID.fromString(r.getString(19)) //bundleId
+                r.getString(7), // productName
+                r.getString(8), // productType
+                r.getString(9) == null ? null : ProductCategory.valueOf(r.getString(9)), // productCategory
+                r.getString(10), // slug
+                r.getString(11),  // phase
+                r.getString(12),  // billing period
+                BigDecimal.valueOf(r.getDouble(13)), // price
+                r.getString(14), // priceList
+                BigDecimal.valueOf(r.getDouble(15)), // mrr
+                r.getString(16), // currency
+                r.getLong(17) == 0 ? null : new DateTime(r.getLong(17), DateTimeZone.UTC), // startDate
+                r.getString(18) == null ? null : SubscriptionState.valueOf(r.getString(18)), // state
+                r.getString(19) == null ? null : UUID.fromString(r.getString(19)), // subscriptionId
+                r.getString(20) == null ? null : UUID.fromString(r.getString(20)) //bundleId
         );
 
         // Avoid creating a dummy subscriptions with all null fields
@@ -59,20 +59,20 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
         }
 
         BusinessSubscription next = new BusinessSubscription(
-                r.getString(20), // productName
-                r.getString(21), // productType
-                r.getString(22) == null ? null : ProductCategory.valueOf(r.getString(22)), // productCategory
-                r.getString(23), // slug8
-                r.getString(24),  // phase
-                r.getString(25),  // billing period
-                BigDecimal.valueOf(r.getDouble(26)), // price
-                r.getString(27), // priceList
-                BigDecimal.valueOf(r.getDouble(28)), // mrr
-                r.getString(29), // currency
-                r.getLong(30) == 0 ? null : new DateTime(r.getLong(30), DateTimeZone.UTC), // startDate
-                r.getString(31) == null ? null : SubscriptionState.valueOf(r.getString(31)), // state
-                r.getString(32) == null ? null : UUID.fromString(r.getString(32)), // subscriptionId
-                r.getString(33) == null ? null : UUID.fromString(r.getString(33)) //bundleId
+                r.getString(21), // productName
+                r.getString(22), // productType
+                r.getString(23) == null ? null : ProductCategory.valueOf(r.getString(23)), // productCategory
+                r.getString(24), // slug8
+                r.getString(25),  // phase
+                r.getString(26),  // billing period
+                BigDecimal.valueOf(r.getDouble(27)), // price
+                r.getString(28), // priceList
+                BigDecimal.valueOf(r.getDouble(29)), // mrr
+                r.getString(30), // currency
+                r.getLong(31) == 0 ? null : new DateTime(r.getLong(31), DateTimeZone.UTC), // startDate
+                r.getString(32) == null ? null : SubscriptionState.valueOf(r.getString(32)), // state
+                r.getString(33) == null ? null : UUID.fromString(r.getString(33)), // subscriptionId
+                r.getString(34) == null ? null : UUID.fromString(r.getString(34)) //bundleId
         );
 
         // Avoid creating a dummy subscriptions with all null fields
@@ -80,13 +80,14 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
             next = null;
         }
 
-        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf(r.getString(5));
+        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf(r.getString(6));
 
         return new BusinessSubscriptionTransition(
-                r.getLong(1),
-                r.getString(2),
+                UUID.fromString(r.getString(1)),
+                r.getLong(2),
                 r.getString(3),
-                new DateTime(r.getLong(4), DateTimeZone.UTC),
+                r.getString(4),
+                new DateTime(r.getLong(5), DateTimeZone.UTC),
                 event,
                 prev,
                 next
diff --git a/analytics/src/main/java/com/ning/billing/analytics/model/BusinessSubscriptionTransition.java b/analytics/src/main/java/com/ning/billing/analytics/model/BusinessSubscriptionTransition.java
index 3618b7d..2102416 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/model/BusinessSubscriptionTransition.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/model/BusinessSubscriptionTransition.java
@@ -16,6 +16,8 @@
 
 package com.ning.billing.analytics.model;
 
+import java.util.UUID;
+
 import org.joda.time.DateTime;
 
 /**
@@ -24,6 +26,7 @@ import org.joda.time.DateTime;
  * The key is unique identifier that ties sets of subscriptions together.
  */
 public class BusinessSubscriptionTransition {
+    private final UUID subscriptionId;
     private final long totalOrdering;
     private final String externalKey;
     private final String accountKey;
@@ -32,7 +35,11 @@ public class BusinessSubscriptionTransition {
     private final BusinessSubscription previousSubscription;
     private final BusinessSubscription nextSubscription;
 
-    public BusinessSubscriptionTransition(final Long totalOrdering, final String externalKey, final String accountKey, final DateTime requestedTimestamp, final BusinessSubscriptionEvent event, final BusinessSubscription previousSubscription, final BusinessSubscription nextSubscription) {
+    public BusinessSubscriptionTransition(final UUID subscriptionId, final Long totalOrdering, final String externalKey, final String accountKey, final DateTime requestedTimestamp,
+                                          final BusinessSubscriptionEvent event, final BusinessSubscription previousSubscription, final BusinessSubscription nextSubscription) {
+        if (subscriptionId == null) {
+            throw new IllegalArgumentException("An event must have a subscription id");
+        }
         if (totalOrdering == null) {
             throw new IllegalArgumentException("An event must have a total ordering");
         }
@@ -49,6 +56,7 @@ public class BusinessSubscriptionTransition {
             throw new IllegalArgumentException("No event specified");
         }
 
+        this.subscriptionId = subscriptionId;
         this.totalOrdering = totalOrdering;
         this.externalKey = externalKey;
         this.accountKey = accountKey;
@@ -58,6 +66,10 @@ public class BusinessSubscriptionTransition {
         this.nextSubscription = nextSubscription;
     }
 
+    public UUID getSubscriptionId() {
+        return subscriptionId;
+    }
+
     public long getTotalOrdering() {
         return totalOrdering;
     }
@@ -91,6 +103,7 @@ public class BusinessSubscriptionTransition {
         final StringBuilder sb = new StringBuilder();
         sb.append("BusinessSubscriptionTransition");
         sb.append("{accountKey='").append(accountKey).append('\'');
+        sb.append(", subscriptionId=").append(subscriptionId);
         sb.append(", totalOrdering=").append(totalOrdering);
         sb.append(", key='").append(externalKey).append('\'');
         sb.append(", requestedTimestamp=").append(requestedTimestamp);
@@ -115,6 +128,9 @@ public class BusinessSubscriptionTransition {
         if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
             return false;
         }
+        if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null) {
+            return false;
+        }
         if (event != null ? !event.equals(that.event) : that.event != null) {
             return false;
         }
@@ -142,6 +158,7 @@ public class BusinessSubscriptionTransition {
         int result = (int) (totalOrdering ^ (totalOrdering >>> 32));
         result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
         result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
+        result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
         result = 31 * result + (requestedTimestamp != null ? requestedTimestamp.hashCode() : 0);
         result = 31 * result + (event != null ? event.hashCode() : 0);
         result = 31 * result + (previousSubscription != null ? previousSubscription.hashCode() : 0);
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg
index c80b6b5..ca971e0 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg
+++ b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg
@@ -2,7 +2,8 @@ group BusinessSubscriptionTransition;
 
 getTransitions(external_key) ::= <<
   select
-    total_ordering
+    subscription_id
+  , total_ordering
   , external_key
   , account_key
   , requested_timestamp
@@ -43,7 +44,8 @@ getTransitions(external_key) ::= <<
 
 createTransition() ::= <<
   insert ignore into bst(
-    total_ordering
+    subscription_id
+  , total_ordering
   , external_key
   , account_key
   , requested_timestamp
@@ -77,7 +79,8 @@ createTransition() ::= <<
   , next_subscription_id
   , next_bundle_id
   ) values (
-    :total_ordering
+    :subscription_id
+  , :total_ordering
   , :external_key
   , :account_key
   , :requested_timestamp
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql b/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
index 43aaad8..19261bc 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
+++ b/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
@@ -1,6 +1,7 @@
 drop table if exists bst;
 create table bst (
-  total_ordering bigint default 0
+  subscription_id char(36) not null
+, total_ordering bigint default 0
 , external_key varchar(50) not null comment 'Bundle external key'
 , account_key varchar(50) not null comment 'Account external key'
 , requested_timestamp bigint not null
diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index ad54c53..da023c9 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -201,6 +201,7 @@ public class TestAnalyticsService extends TestWithEmbeddedDB {
                 null,
                 true), null);
         expectedTransition = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 TOTAL_ORDERING,
                 EXTERNAL_KEY,
                 ACCOUNT_KEY,
diff --git a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
index 5d6b3a6..6089dd2 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
@@ -52,6 +52,7 @@ import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.Subscription;
 
 public class TestAnalyticsDao extends TestWithEmbeddedDB {
+    private static final UUID SUBSCRIPTION_ID = UUID.randomUUID();
     private static final Long TOTAL_ORDERING = 1L;
     private static final String EXTERNAL_KEY = "23456";
     private static final String ACCOUNT_KEY = "pierre-143343-vcc";
@@ -85,7 +86,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
         final BusinessSubscription nextSubscription = new BusinessSubscription(null, plan.getName(), phase.getName(), Currency.USD, new DateTime(DateTimeZone.UTC), Subscription.SubscriptionState.CANCELLED, UUID.randomUUID(), UUID.randomUUID(), catalog);
         final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(plan.getName(), catalog, requestedTimestamp, requestedTimestamp);
 
-        transition = new BusinessSubscriptionTransition(TOTAL_ORDERING, EXTERNAL_KEY, ACCOUNT_KEY, requestedTimestamp, event, prevSubscription, nextSubscription);
+        transition = new BusinessSubscriptionTransition(SUBSCRIPTION_ID, TOTAL_ORDERING, EXTERNAL_KEY, ACCOUNT_KEY, requestedTimestamp, event, prevSubscription, nextSubscription);
 
         final IDBI dbi = helper.getDBI();
         businessSubscriptionTransitionSqlDao = dbi.onDemand(BusinessSubscriptionTransitionSqlDao.class);
@@ -115,6 +116,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
     @Test(groups = "slow")
     public void testHandleDuplicatedEvents() {
         final BusinessSubscriptionTransition transitionWithNullPrev = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 transition.getTotalOrdering(),
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -136,6 +138,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
 
         // Try now to store a look-alike transition (same fields except UUID) - we should store it this time
         final BusinessSubscriptionTransition secondTransitionWithNullPrev = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 12L,
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -154,6 +157,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
     @Test(groups = "slow")
     public void testTransitionsWithNullPrevSubscription() {
         final BusinessSubscriptionTransition transitionWithNullPrev = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 transition.getTotalOrdering(),
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -172,6 +176,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
     @Test(groups = "slow")
     public void testTransitionsWithNullNextSubscription() {
         final BusinessSubscriptionTransition transitionWithNullNext = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 transition.getTotalOrdering(),
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -191,6 +196,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
     public void testTransitionsWithNullFieldsInSubscription() {
         final BusinessSubscription subscriptionWithNullFields = new BusinessSubscription(null, plan.getName(), phase.getName(), Currency.USD, null, null, null, null, catalog);
         final BusinessSubscriptionTransition transitionWithNullFields = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 transition.getTotalOrdering(),
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -210,6 +216,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
     public void testTransitionsWithNullPlanAndPhase() throws Exception {
         final BusinessSubscription subscriptionWithNullPlanAndPhase = new BusinessSubscription(null, null, null, Currency.USD, null, null, null, null, catalog);
         final BusinessSubscriptionTransition transitionWithNullPlanAndPhase = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 transition.getTotalOrdering(),
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -222,6 +229,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
 
         final List<BusinessSubscriptionTransition> transitions = businessSubscriptionTransitionSqlDao.getTransitions(EXTERNAL_KEY);
         Assert.assertEquals(transitions.size(), 1);
+        Assert.assertEquals(transitions.get(0).getSubscriptionId(), transition.getSubscriptionId());
         Assert.assertEquals(transitions.get(0).getExternalKey(), transition.getExternalKey());
         Assert.assertEquals(transitions.get(0).getRequestedTimestamp(), transition.getRequestedTimestamp());
         Assert.assertEquals(transitions.get(0).getEvent(), transition.getEvent());
@@ -233,6 +241,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
     public void testTransitionsWithNullPlan() throws Exception {
         final BusinessSubscription subscriptionWithNullPlan = new BusinessSubscription(null, null, phase.getName(), Currency.USD, null, null, null, null, catalog);
         final BusinessSubscriptionTransition transitionWithNullPlan = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 transition.getTotalOrdering(),
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -253,6 +262,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
     public void testTransitionsWithNullPhase() throws Exception {
         final BusinessSubscription subscriptionWithNullPhase = new BusinessSubscription(null, plan.getName(), null, Currency.USD, null, null, null, null, catalog);
         final BusinessSubscriptionTransition transitionWithNullPhase = new BusinessSubscriptionTransition(
+                transition.getSubscriptionId(),
                 transition.getTotalOrdering(),
                 transition.getExternalKey(),
                 transition.getAccountKey(),
@@ -265,6 +275,7 @@ public class TestAnalyticsDao extends TestWithEmbeddedDB {
 
         final List<BusinessSubscriptionTransition> transitions = businessSubscriptionTransitionSqlDao.getTransitions(EXTERNAL_KEY);
         Assert.assertEquals(transitions.size(), 1);
+        Assert.assertEquals(transitions.get(0).getSubscriptionId(), transition.getSubscriptionId());
         Assert.assertEquals(transitions.get(0).getExternalKey(), transition.getExternalKey());
         Assert.assertEquals(transitions.get(0).getRequestedTimestamp(), transition.getRequestedTimestamp());
         Assert.assertEquals(transitions.get(0).getEvent(), transition.getEvent());
diff --git a/analytics/src/test/java/com/ning/billing/analytics/model/TestBusinessSubscriptionTransition.java b/analytics/src/test/java/com/ning/billing/analytics/model/TestBusinessSubscriptionTransition.java
index 4c401a6..55bcc53 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/model/TestBusinessSubscriptionTransition.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/model/TestBusinessSubscriptionTransition.java
@@ -16,6 +16,8 @@
 
 package com.ning.billing.analytics.model;
 
+import java.util.UUID;
+
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.mockito.Mockito;
@@ -29,9 +31,6 @@ import com.ning.billing.analytics.MockPhase;
 import com.ning.billing.analytics.MockPlan;
 import com.ning.billing.analytics.MockProduct;
 import com.ning.billing.analytics.MockSubscription;
-import com.ning.billing.analytics.model.BusinessSubscription;
-import com.ning.billing.analytics.model.BusinessSubscriptionEvent;
-import com.ning.billing.analytics.model.BusinessSubscriptionTransition;
 import com.ning.billing.catalog.api.Catalog;
 import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.api.PhaseType;
@@ -48,6 +47,7 @@ public class TestBusinessSubscriptionTransition extends AnalyticsTestSuite {
     private BusinessSubscription nextSubscription;
     private BusinessSubscriptionEvent event;
     private DateTime requestedTimestamp;
+    private UUID subscriptionId;
     private Long totalOrdering;
     private String externalKey;
     private String accountKey;
@@ -74,10 +74,11 @@ public class TestBusinessSubscriptionTransition extends AnalyticsTestSuite {
         nextSubscription = new BusinessSubscription(nextISubscription, USD, catalog);
         event = BusinessSubscriptionEvent.subscriptionCancelled(prevISubscription.getCurrentPlan().getName(), catalog, now, now);
         requestedTimestamp = new DateTime(DateTimeZone.UTC);
+        subscriptionId = UUID.randomUUID();
         totalOrdering = 12L;
         externalKey = "1234";
         accountKey = "pierre-1234";
-        transition = new BusinessSubscriptionTransition(totalOrdering, externalKey, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+        transition = new BusinessSubscriptionTransition(subscriptionId, totalOrdering, externalKey, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
     }
 
     @Test(groups = "fast")
@@ -96,47 +97,54 @@ public class TestBusinessSubscriptionTransition extends AnalyticsTestSuite {
 
         BusinessSubscriptionTransition otherTransition;
 
-        otherTransition = new BusinessSubscriptionTransition(totalOrdering, externalKey, accountKey, new DateTime(), event, prevSubscription, nextSubscription);
+        otherTransition = new BusinessSubscriptionTransition(subscriptionId, totalOrdering, externalKey, accountKey, new DateTime(), event, prevSubscription, nextSubscription);
         Assert.assertTrue(!transition.equals(otherTransition));
 
-        otherTransition = new BusinessSubscriptionTransition(totalOrdering, "12345", accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+        otherTransition = new BusinessSubscriptionTransition(subscriptionId, totalOrdering, "12345", accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
         Assert.assertTrue(!transition.equals(otherTransition));
 
-        otherTransition = new BusinessSubscriptionTransition(totalOrdering, externalKey, accountKey, requestedTimestamp, event, prevSubscription, prevSubscription);
+        otherTransition = new BusinessSubscriptionTransition(subscriptionId, totalOrdering, externalKey, accountKey, requestedTimestamp, event, prevSubscription, prevSubscription);
         Assert.assertTrue(!transition.equals(otherTransition));
 
-        otherTransition = new BusinessSubscriptionTransition(totalOrdering, externalKey, accountKey, requestedTimestamp, event, nextSubscription, nextSubscription);
+        otherTransition = new BusinessSubscriptionTransition(subscriptionId, totalOrdering, externalKey, accountKey, requestedTimestamp, event, nextSubscription, nextSubscription);
         Assert.assertTrue(!transition.equals(otherTransition));
 
-        otherTransition = new BusinessSubscriptionTransition(totalOrdering, externalKey, accountKey, requestedTimestamp, event, nextSubscription, prevSubscription);
+        otherTransition = new BusinessSubscriptionTransition(subscriptionId, totalOrdering, externalKey, accountKey, requestedTimestamp, event, nextSubscription, prevSubscription);
         Assert.assertTrue(!transition.equals(otherTransition));
     }
 
     @Test(groups = "fast")
     public void testRejectInvalidTransitions() throws Exception {
         try {
-            new BusinessSubscriptionTransition(null, externalKey, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+            new BusinessSubscriptionTransition(null, totalOrdering, externalKey, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+            Assert.fail();
+        } catch (IllegalArgumentException e) {
+            Assert.assertTrue(true);
+        }
+
+        try {
+            new BusinessSubscriptionTransition(subscriptionId, null, externalKey, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
             Assert.fail();
         } catch (IllegalArgumentException e) {
             Assert.assertTrue(true);
         }
 
         try {
-            new BusinessSubscriptionTransition(totalOrdering, null, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+            new BusinessSubscriptionTransition(subscriptionId, totalOrdering, null, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
             Assert.fail();
         } catch (IllegalArgumentException e) {
             Assert.assertTrue(true);
         }
 
         try {
-            new BusinessSubscriptionTransition(totalOrdering, externalKey, accountKey, null, event, prevSubscription, nextSubscription);
+            new BusinessSubscriptionTransition(subscriptionId, totalOrdering, externalKey, accountKey, null, event, prevSubscription, nextSubscription);
             Assert.fail();
         } catch (IllegalArgumentException e) {
             Assert.assertTrue(true);
         }
 
         try {
-            new BusinessSubscriptionTransition(totalOrdering, externalKey, accountKey, requestedTimestamp, null, prevSubscription, nextSubscription);
+            new BusinessSubscriptionTransition(subscriptionId, totalOrdering, externalKey, accountKey, requestedTimestamp, null, prevSubscription, nextSubscription);
             Assert.fail();
         } catch (IllegalArgumentException e) {
             Assert.assertTrue(true);
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
index d43e0dc..9547957 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -148,6 +148,7 @@ public class TestAnalyticsListener extends AnalyticsTestSuite {
             @Nullable final BusinessSubscription previousSubscription,
             @Nullable final Subscription.SubscriptionState nextState) {
         return new BusinessSubscriptionTransition(
+                subscriptionId,
                 totalOrdering,
                 EXTERNAL_KEY,
                 ACCOUNT_KEY,
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransitionRecorder.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransitionRecorder.java
index 75c3ebc..b74d4f1 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransitionRecorder.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransitionRecorder.java
@@ -59,13 +59,14 @@ public class TestBusinessSubscriptionTransitionRecorder extends AnalyticsTestSui
                                                                                    UUID.randomUUID(),
                                                                                    UUID.randomUUID(),
                                                                                    catalogService.getFullCatalog());
-        sqlDao.createTransition(new BusinessSubscriptionTransition(10L,
-                                                                externalKey.toString(),
-                                                                UUID.randomUUID().toString(),
-                                                                new DateTime(DateTimeZone.UTC),
-                                                                BusinessSubscriptionEvent.valueOf("ADD_MISC"),
-                                                                null,
-                                                                nextPrevSubscription));
+        sqlDao.createTransition(new BusinessSubscriptionTransition(UUID.randomUUID(),
+                                                                   10L,
+                                                                   externalKey.toString(),
+                                                                   UUID.randomUUID().toString(),
+                                                                   new DateTime(DateTimeZone.UTC),
+                                                                   BusinessSubscriptionEvent.valueOf("ADD_MISC"),
+                                                                   null,
+                                                                   nextPrevSubscription));
 
         // Setup the entitlement API
         final SubscriptionBundle bundle = Mockito.mock(SubscriptionBundle.class);
@@ -84,6 +85,7 @@ public class TestBusinessSubscriptionTransitionRecorder extends AnalyticsTestSui
         // Create an new subscription event
         final EffectiveSubscriptionEvent eventEffective = Mockito.mock(EffectiveSubscriptionEvent.class);
         Mockito.when(eventEffective.getId()).thenReturn(UUID.randomUUID());
+        Mockito.when(eventEffective.getSubscriptionId()).thenReturn(UUID.randomUUID());
         Mockito.when(eventEffective.getRequestedTransitionTime()).thenReturn(new DateTime(DateTimeZone.UTC));
         Mockito.when(eventEffective.getNextPlan()).thenReturn(UUID.randomUUID().toString());
         Mockito.when(eventEffective.getEffectiveTransitionTime()).thenReturn(new DateTime(DateTimeZone.UTC));