killbill-memoizeit

auditing for entitlements

4/6/2012 6:46:35 PM

Changes

Details

diff --git a/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
index 92b316a..3a51bcc 100644
--- a/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
+++ b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
@@ -90,20 +90,11 @@ public abstract class AccountDaoTestBase {
             @Override
             public Void inTransaction(Handle h, TransactionStatus status) throws Exception {
                 h.execute("truncate table accounts");
-                h.execute("truncate table entitlement_events");
-                h.execute("truncate table subscriptions");
-                h.execute("truncate table bundles");
                 h.execute("truncate table notifications");
                 h.execute("truncate table claimed_notifications");
-                h.execute("truncate table invoices");
-                h.execute("truncate table fixed_invoice_items");
-                h.execute("truncate table recurring_invoice_items");
                 h.execute("truncate table tag_definitions");
                 h.execute("truncate table tags");
                 h.execute("truncate table custom_fields");
-                h.execute("truncate table invoice_payments");
-                h.execute("truncate table payment_attempts");
-                h.execute("truncate table payments");
                 return 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 84cc7eb..2a6f448 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
@@ -196,7 +196,7 @@ public class TestAnalyticsService {
     }
 
     private void createSubscriptionTransitionEvent(final Account account) throws EntitlementUserApiException {
-        final SubscriptionBundle bundle = entitlementApi.createBundleForAccount(account.getId(), KEY);
+        final SubscriptionBundle bundle = entitlementApi.createBundleForAccount(account.getId(), KEY, context);
 
         // Verify we correctly initialized the account subsystem
         Assert.assertNotNull(bundle);
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
index 3901426..99e435f 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -53,13 +53,13 @@ public class MockSubscription implements Subscription
     }
 
     @Override
-    public void cancel(DateTime requestedDate, boolean eot)
+    public void cancel(DateTime requestedDate, boolean eot, CallContext context)
     {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public void changePlan(final String productName, final BillingPeriod term, final String planSet, DateTime requestedDate)
+    public void changePlan(final String productName, final BillingPeriod term, final String planSet, DateTime requestedDate, CallContext context)
     {
         throw new UnsupportedOperationException();
     }
@@ -112,7 +112,7 @@ public class MockSubscription implements Subscription
 
 
     @Override
-    public void uncancel() throws EntitlementUserApiException
+    public void uncancel(CallContext context) throws EntitlementUserApiException
     {
         throw new UnsupportedOperationException();
     }
@@ -154,7 +154,7 @@ public class MockSubscription implements Subscription
     }
 
     @Override
-    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
             throws EntitlementUserApiException {
         throw new UnsupportedOperationException();
     }
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 910bdc0..7254a5d 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -54,7 +54,7 @@ public class TestAnalyticsListener
     @BeforeMethod(alwaysRun = true)
     public void setUp() throws Exception
     {
-        final BusinessSubscriptionTransitionRecorder recorder = new BusinessSubscriptionTransitionRecorder(dao, new MockIEntitlementUserApi(bundleUUID, KEY), new MockIAccountUserApi(ACCOUNT_KEY, CURRENCY));
+        final BusinessSubscriptionTransitionRecorder recorder = new BusinessSubscriptionTransitionRecorder(dao, new MockEntitlementUserApi(bundleUUID, KEY), new MockIAccountUserApi(ACCOUNT_KEY, CURRENCY));
         listener = new AnalyticsListener(recorder, null);
     }
 
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
index 6dc3e94..0d87399 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
@@ -19,6 +19,7 @@ package com.ning.billing.entitlement.api.billing;
 import java.util.SortedSet;
 import java.util.UUID;
 
+import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
@@ -36,8 +37,9 @@ public interface EntitlementBillingApi {
 
     public UUID getAccountIdFromSubscriptionId(UUID subscriptionId);
 
-    public void setChargedThroughDate(UUID subscriptionId, DateTime ctd);
+    public void setChargedThroughDate(UUID subscriptionId, DateTime ctd, CallContext context);
 
-    public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId, DateTime ctd);
+    public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId,
+                                                     DateTime ctd, CallContext context);
 
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.java b/api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.java
index 1b1e6ff..09ac359 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.java
@@ -18,6 +18,7 @@ package com.ning.billing.entitlement.api.migration;
 
 import java.util.UUID;
 
+import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
@@ -61,6 +62,6 @@ public interface EntitlementMigrationApi {
      * @throws EntitlementMigrationApiException an entitlement api exception
      *
      */
-    public void migrate(EntitlementAccountMigration toBeMigrated)
+    public void migrate(EntitlementAccountMigration toBeMigrated, CallContext context)
         throws EntitlementMigrationApiException;
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
index 1867cfe..205f256 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
@@ -18,6 +18,8 @@ package com.ning.billing.entitlement.api.user;
 
 import java.util.List;
 import java.util.UUID;
+
+import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 
@@ -36,10 +38,10 @@ public interface EntitlementUserApi {
 
     public List<Subscription> getSubscriptionsForKey(String bundleKey);
 
-    public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleKey)
+    public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleKey, CallContext context)
         throws EntitlementUserApiException;
 
-    public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec, DateTime requestedDate)
+    public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
         throws EntitlementUserApiException;
 
     public DateTime getNextBillingDate(UUID account);
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index dcfe2df..0854e2f 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -22,6 +22,7 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 
+import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.entity.ExtendedEntity;
 import org.joda.time.DateTime;
 
@@ -30,16 +31,16 @@ import java.util.UUID;
 
 public interface Subscription extends ExtendedEntity {
 
-    public void cancel(DateTime requestedDate, boolean eot)
+    public void cancel(DateTime requestedDate, boolean eot, CallContext context)
     throws EntitlementUserApiException;
 
-    public void uncancel()
+    public void uncancel(CallContext context)
     throws EntitlementUserApiException;
 
-    public void changePlan(String productName, BillingPeriod term, String planSet, DateTime requestedDate)
+    public void changePlan(String productName, BillingPeriod term, String planSet, DateTime requestedDate, CallContext context)
         throws EntitlementUserApiException;
 
-    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
         throws EntitlementUserApiException;
 
     public enum SubscriptionState {
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
index 1d81006..0b509e3 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
@@ -314,7 +314,7 @@ public class TestIntegration {
 
         // set clock to the initial start date
         clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
-        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever2");
+        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever2", context);
 
         String productName = "Shotgun";
         BillingPeriod term = BillingPeriod.MONTHLY;
@@ -326,7 +326,7 @@ public class TestIntegration {
         busHandler.pushExpectedEvent(NextEvent.CREATE);
         busHandler.pushExpectedEvent(NextEvent.INVOICE);
         SubscriptionData subscription = (SubscriptionData) entitlementUserApi.createSubscription(bundle.getId(),
-                new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null);
+                new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null, context);
         assertNotNull(subscription);
         assertTrue(busHandler.isCompleted(DELAY));
 
@@ -349,7 +349,7 @@ public class TestIntegration {
         assertTrue(busHandler.isCompleted(DELAY));
 
         subscription = (SubscriptionData) entitlementUserApi.getSubscriptionFromId(subscription.getId());
-        subscription.cancel(clock.getUTCNow(), false);
+        subscription.cancel(clock.getUTCNow(), false, context);
 
         // MOVE AFTER CANCEL DATE AND EXPECT EVENT : NextEvent.CANCEL
         busHandler.pushExpectedEvent(NextEvent.CANCEL);
@@ -365,7 +365,7 @@ public class TestIntegration {
         busHandler.pushExpectedEvent(NextEvent.CREATE);
         busHandler.pushExpectedEvent(NextEvent.INVOICE);
         busHandler.pushExpectedEvent(NextEvent.PAYMENT);
-        subscription.recreate(new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), endDate);
+        subscription.recreate(new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), endDate, context);
         assertTrue(busHandler.isCompleted(DELAY));
 
 
@@ -380,7 +380,7 @@ public class TestIntegration {
 
         // set clock to the initial start date
         clock.setDeltaFromReality(initialCreationDate.getMillis() - clock.getUTCNow().getMillis());
-        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever");
+        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever", context);
 
         String productName = "Shotgun";
         BillingPeriod term = BillingPeriod.MONTHLY;
@@ -392,7 +392,7 @@ public class TestIntegration {
         busHandler.pushExpectedEvent(NextEvent.CREATE);
         busHandler.pushExpectedEvent(NextEvent.INVOICE);
         SubscriptionData subscription = (SubscriptionData) entitlementUserApi.createSubscription(bundle.getId(),
-                new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null);
+                new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null, context);
         assertNotNull(subscription);
 
         assertTrue(busHandler.isCompleted(DELAY));
@@ -415,7 +415,7 @@ public class TestIntegration {
         BillingPeriod newTerm = BillingPeriod.MONTHLY;
         String newPlanSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
         String newProductName = "Assault-Rifle";
-        subscription.changePlan(newProductName, newTerm, newPlanSetName, clock.getUTCNow());
+        subscription.changePlan(newProductName, newTerm, newPlanSetName, clock.getUTCNow(), context);
 
         assertTrue(busHandler.isCompleted(DELAY));
 
@@ -490,7 +490,7 @@ public class TestIntegration {
         newPlanSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
         newProductName = "Pistol";
         subscription = (SubscriptionData) entitlementUserApi.getSubscriptionFromId(subscription.getId());
-        subscription.changePlan(newProductName, newTerm, newPlanSetName, clock.getUTCNow());
+        subscription.changePlan(newProductName, newTerm, newPlanSetName, clock.getUTCNow(), context);
 
         //
         // MOVE TIME AFTER CTD AND EXPECT BOTH EVENTS : NextEvent.CHANGE NextEvent.INVOICE
@@ -538,7 +538,7 @@ public class TestIntegration {
         // FINALLY CANCEL SUBSCRIPTION EOT
         //
         subscription = (SubscriptionData) entitlementUserApi.getSubscriptionFromId(subscription.getId());
-        subscription.cancel(clock.getUTCNow(), false);
+        subscription.cancel(clock.getUTCNow(), false, context);
 
         // MOVE AFTER CANCEL DATE AND EXPECT EVENT : NextEvent.CANCEL
         busHandler.pushExpectedEvent(NextEvent.CANCEL);
@@ -569,7 +569,7 @@ public class TestIntegration {
         Account account = accountUserApi.createAccount(getAccountData(3), null, null, context);
         assertNotNull(account);
 
-        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever");
+        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever", context);
 
         String productName = "Shotgun";
         BillingPeriod term = BillingPeriod.MONTHLY;
@@ -578,7 +578,7 @@ public class TestIntegration {
         busHandler.pushExpectedEvent(NextEvent.CREATE);
         busHandler.pushExpectedEvent(NextEvent.INVOICE);
         SubscriptionData subscription = (SubscriptionData) entitlementUserApi.createSubscription(bundle.getId(),
-                new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null);
+                new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null, context);
         assertNotNull(subscription);
 
         assertTrue(busHandler.isCompleted(DELAY));
@@ -588,7 +588,7 @@ public class TestIntegration {
         BillingPeriod newTerm = BillingPeriod.MONTHLY;
         String newPlanSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
         String newProductName = "Assault-Rifle";
-        subscription.changePlan(newProductName, newTerm, newPlanSetName, clock.getUTCNow());
+        subscription.changePlan(newProductName, newTerm, newPlanSetName, clock.getUTCNow(), context);
 
         assertTrue(busHandler.isCompleted(DELAY));
 
@@ -611,10 +611,10 @@ public class TestIntegration {
 
         busHandler.pushExpectedEvent(NextEvent.CREATE);
         busHandler.pushExpectedEvent(NextEvent.INVOICE);
-        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(accountId, "testKey");
+        SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(accountId, "testKey", context);
         SubscriptionData subscription = (SubscriptionData) entitlementUserApi.createSubscription(bundle.getId(),
                                         new PlanPhaseSpecifier(productName, ProductCategory.BASE,
-                                        BillingPeriod.MONTHLY, planSetName, PhaseType.TRIAL), null);
+                                        BillingPeriod.MONTHLY, planSetName, PhaseType.TRIAL), null, context);
         assertTrue(busHandler.isCompleted(DELAY));
         List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(accountId);
         assertNotNull(invoices);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
index a00f11f..5d2d871 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
@@ -23,6 +23,8 @@ import java.util.TreeSet;
 import java.util.UUID;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.audit.dao.AuditSqlDao;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallOrigin;
 import com.ning.billing.util.callcontext.UserType;
@@ -65,6 +67,7 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
     private final EntitlementDao entitlementDao;
     private final AccountUserApi accountApi;
     private final CatalogService catalogService;
+    private static final String SUBSCRIPTION_TABLE_NAME = "subscriptions";
 
     @Inject
     public DefaultEntitlementBillingApi(final CallContextFactory factory, final EntitlementDao dao, final AccountUserApi accountApi, final CatalogService catalogService) {
@@ -181,18 +184,19 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
 
 
     @Override
-    public void setChargedThroughDate(final UUID subscriptionId, final DateTime ctd) {
+    public void setChargedThroughDate(final UUID subscriptionId, final DateTime ctd, CallContext context) {
         SubscriptionData subscription = (SubscriptionData) entitlementDao.getSubscriptionFromId(subscriptionId);
 
         SubscriptionBuilder builder = new SubscriptionBuilder(subscription)
             .setChargedThroughDate(ctd)
             .setPaidThroughDate(subscription.getPaidThroughDate());
 
-        entitlementDao.updateSubscription(new SubscriptionData(builder));
+        entitlementDao.updateSubscription(new SubscriptionData(builder), context);
     }
 
     @Override
-    public void setChargedThroughDateFromTransaction(final Transmogrifier transactionalDao, final UUID subscriptionId, final DateTime ctd) {
+    public void setChargedThroughDateFromTransaction(final Transmogrifier transactionalDao, final UUID subscriptionId,
+                                                     final DateTime ctd, final CallContext context) {
         SubscriptionSqlDao subscriptionSqlDao = transactionalDao.become(SubscriptionSqlDao.class);
         SubscriptionData subscription = (SubscriptionData) subscriptionSqlDao.getSubscriptionFromId(subscriptionId.toString());
 
@@ -204,7 +208,9 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
             DateTime chargedThroughDate = subscription.getChargedThroughDate();
             if (chargedThroughDate == null || chargedThroughDate.isBefore(ctd)) {
                 subscriptionSqlDao.updateSubscription(subscriptionId.toString(), subscription.getActiveVersion(),
-                                                      ctd.toDate(), paidThroughDate);
+                                                      ctd.toDate(), paidThroughDate, context);
+                AuditSqlDao auditSqlDao = transactionalDao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(SUBSCRIPTION_TABLE_NAME, subscriptionId.toString(), ChangeType.UPDATE, context);
             }
         }
     }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
index 4325f02..d0fb35b 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
@@ -23,6 +23,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
+import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 
 import com.google.common.collect.Lists;
@@ -52,8 +53,6 @@ import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.clock.Clock;
 
 public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
-
-
     private final EntitlementDao dao;
     private final MigrationPlanAligner migrationAligner;
     private final SubscriptionFactory factory;
@@ -71,10 +70,10 @@ public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
     }
 
     @Override
-    public void migrate(EntitlementAccountMigration toBeMigrated)
+    public void migrate(EntitlementAccountMigration toBeMigrated, CallContext context)
     throws EntitlementMigrationApiException {
         AccountMigrationData accountMigrationData = createAccountMigrationData(toBeMigrated);
-        dao.migrate(toBeMigrated.getAccountKey(), accountMigrationData);
+        dao.migrate(toBeMigrated.getAccountKey(), accountMigrationData, context);
     }
 
     private AccountMigrationData createAccountMigrationData(EntitlementAccountMigration toBeMigrated)
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
index baf45f1..2c6d302 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.UUID;
 
 import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
@@ -87,14 +88,15 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
     }
 
     @Override
-    public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleName)
+    public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleName, CallContext context)
     throws EntitlementUserApiException {
         SubscriptionBundleData bundle = new SubscriptionBundleData(bundleName, accountId);
-        return dao.createSubscriptionBundle(bundle);
+        return dao.createSubscriptionBundle(bundle, context);
     }
 
     @Override
-    public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec, DateTime requestedDate) throws EntitlementUserApiException {
+    public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec, DateTime requestedDate,
+                                           CallContext context) throws EntitlementUserApiException {
         try {
             String realPriceList = (spec.getPriceListName() == null) ? PriceListSet.DEFAULT_PRICELIST_NAME : spec.getPriceListName();
             DateTime now = clock.getUTCNow();
@@ -127,7 +129,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
                         throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_BP_EXISTS, bundleId);
                     } else {
                         // If we do create on an existing CANCELLED BP, this is equivalent to call recreate on that Subscription.
-                        baseSubscription.recreate(spec, requestedDate);
+                        baseSubscription.recreate(spec, requestedDate, context);
                         return baseSubscription;
                     }
                 }
@@ -158,7 +160,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
                 .setCategory(plan.getProduct().getCategory())
                 .setBundleStartDate(bundleStartDate)
                 .setStartDate(effectiveDate),
-            plan, spec.getPhaseType(), realPriceList, requestedDate, effectiveDate, now);
+            plan, spec.getPhaseType(), realPriceList, requestedDate, effectiveDate, now, context);
 
             return subscription;
         } catch (CatalogApiException e) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
index 8291e34..39efb09 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
@@ -53,15 +53,16 @@ public class SubscriptionApiService {
     }
 
     public SubscriptionData createPlan(SubscriptionBuilder builder, Plan plan, PhaseType initialPhase,
-            String realPriceList, DateTime requestedDate, DateTime effectiveDate, DateTime processedDate)
+            String realPriceList, DateTime requestedDate, DateTime effectiveDate, DateTime processedDate,
+            CallContext context)
         throws EntitlementUserApiException {
 
         SubscriptionData subscription = new SubscriptionData(builder, this, clock);
-        createFromSubscription(subscription, plan, initialPhase, realPriceList, requestedDate, effectiveDate, processedDate, false);
+        createFromSubscription(subscription, plan, initialPhase, realPriceList, requestedDate, effectiveDate, processedDate, false, context);
         return subscription;
     }
 
-    public void recreatePlan(SubscriptionData subscription, PlanPhaseSpecifier spec, DateTime requestedDate)
+    public void recreatePlan(SubscriptionData subscription, PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
         throws EntitlementUserApiException {
 
         SubscriptionState currentState = subscription.getState();
@@ -84,15 +85,15 @@ public class SubscriptionApiService {
             DateTime effectiveDate = requestedDate;
             DateTime processedDate = now;
 
-            createFromSubscription(subscription, plan, spec.getPhaseType(), realPriceList, requestedDate, effectiveDate, processedDate, true);
+            createFromSubscription(subscription, plan, spec.getPhaseType(), realPriceList, requestedDate, effectiveDate, processedDate, true, context);
         } catch (CatalogApiException e) {
             throw new EntitlementUserApiException(e);
         }
     }
 
-
     private void createFromSubscription(SubscriptionData subscription, Plan plan, PhaseType initialPhase,
-            String realPriceList, DateTime requestedDate, DateTime effectiveDate, DateTime processedDate, boolean reCreate)
+            String realPriceList, DateTime requestedDate, DateTime effectiveDate, DateTime processedDate,
+            boolean reCreate, CallContext context)
         throws EntitlementUserApiException {
 
         try {
@@ -120,9 +121,9 @@ public class SubscriptionApiService {
                 events.add(nextPhaseEvent);
             }
             if (reCreate) {
-                dao.recreateSubscription(subscription.getId(), events);
+                dao.recreateSubscription(subscription.getId(), events, context);
             } else {
-                dao.createSubscription(subscription, events);
+                dao.createSubscription(subscription, events, context);
             }
             subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
         } catch (CatalogApiException e) {
@@ -130,10 +131,7 @@ public class SubscriptionApiService {
         }
     }
 
-
-
-
-    public void cancel(SubscriptionData subscription, DateTime requestedDate, boolean eot)
+    public void cancel(SubscriptionData subscription, DateTime requestedDate, boolean eot, CallContext context)
         throws EntitlementUserApiException {
 
         try {
@@ -165,7 +163,7 @@ public class SubscriptionApiService {
             .setRequestedDate(requestedDate)
             .setFromDisk(true));
 
-            dao.cancelSubscription(subscription.getId(), cancelEvent);
+            dao.cancelSubscription(subscription.getId(), cancelEvent, context);
             subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
         } catch (CatalogApiException e) {
             throw new EntitlementUserApiException(e);
@@ -173,7 +171,7 @@ public class SubscriptionApiService {
     }
 
 
-    public void uncancel(SubscriptionData subscription)
+    public void uncancel(SubscriptionData subscription, CallContext context)
         throws EntitlementUserApiException {
 
         if (!subscription.isSubscriptionFutureCancelled()) {
@@ -199,13 +197,12 @@ public class SubscriptionApiService {
         if (nextPhaseEvent != null) {
             uncancelEvents.add(nextPhaseEvent);
         }
-        dao.uncancelSubscription(subscription.getId(), uncancelEvents);
+        dao.uncancelSubscription(subscription.getId(), uncancelEvents, context);
         subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
     }
 
-
     public void changePlan(SubscriptionData subscription, String productName, BillingPeriod term,
-            String priceList, DateTime requestedDate)
+            String priceList, DateTime requestedDate, CallContext context)
         throws EntitlementUserApiException {
 
         try {
@@ -272,7 +269,7 @@ public class SubscriptionApiService {
                         changeEvents.add(nextPhaseEvent);
                     }
                     changeEvents.add(changeEvent);
-                    dao.changePlan(subscription.getId(), changeEvents);
+                    dao.changePlan(subscription.getId(), changeEvents, context);
                     subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
         } catch (CatalogApiException e) {
             throw new EntitlementUserApiException(e);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index 91f663b..a67c502 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -104,7 +104,7 @@ public class SubscriptionData extends ExtendedEntityBase implements Subscription
     }
 
     @Override
-    public void saveFieldValue(String fieldName, String fieldValue, CallContext context) {
+    public void saveFieldValue(String fieldName, @Nullable String fieldValue, CallContext context) {
         super.setFieldValue(fieldName, fieldValue);
         apiService.commitCustomFields(this, context);
     }
@@ -164,25 +164,25 @@ public class SubscriptionData extends ExtendedEntityBase implements Subscription
 
 
     @Override
-    public void cancel(DateTime requestedDate, boolean eot) throws EntitlementUserApiException  {
-        apiService.cancel(this, requestedDate, eot);
+    public void cancel(DateTime requestedDate, boolean eot, CallContext context) throws EntitlementUserApiException  {
+        apiService.cancel(this, requestedDate, eot, context);
     }
 
     @Override
-    public void uncancel() throws EntitlementUserApiException {
-        apiService.uncancel(this);
+    public void uncancel(CallContext context) throws EntitlementUserApiException {
+        apiService.uncancel(this, context);
     }
 
     @Override
     public void changePlan(String productName, BillingPeriod term,
-            String priceList, DateTime requestedDate) throws EntitlementUserApiException {
-        apiService.changePlan(this, productName, term, priceList, requestedDate);
+            String priceList, DateTime requestedDate, CallContext context) throws EntitlementUserApiException {
+        apiService.changePlan(this, productName, term, priceList, requestedDate, context);
     }
 
     @Override
-    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
             throws EntitlementUserApiException {
-        apiService.recreatePlan(this, spec, requestedDate);
+        apiService.recreatePlan(this, spec, requestedDate, context);
     }
 
     public List<SubscriptionTransition> getBillingTransitions() {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 55ea2cf..2547a29 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -23,6 +23,10 @@ import java.util.List;
 import java.util.UUID;
 
 
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.UserType;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -84,7 +88,7 @@ public class Engine implements EventListener, EntitlementService {
 
     private final EntitlementConfig config;
     private final NotificationQueueService notificationQueueService;
-
+    private final CallContextFactory factory;
     private NotificationQueue subscriptionEventQueue;
 
     @Inject
@@ -92,7 +96,8 @@ public class Engine implements EventListener, EntitlementService {
             EntitlementConfig config, DefaultEntitlementUserApi userApi,
             DefaultEntitlementBillingApi billingApi,
             DefaultEntitlementMigrationApi migrationApi, AddonUtils addonUtils, Bus eventBus,
-            NotificationQueueService notificationQueueService) {
+            NotificationQueueService notificationQueueService,
+            CallContextFactory factory) {
         super();
         this.clock = clock;
         this.dao = dao;
@@ -104,6 +109,7 @@ public class Engine implements EventListener, EntitlementService {
         this.config = config;
         this.eventBus = eventBus;
         this.notificationQueueService = notificationQueueService;
+        this.factory = factory;
     }
 
     @Override
@@ -124,7 +130,8 @@ public class Engine implements EventListener, EntitlementService {
                     if (event == null) {
                         log.warn("Failed to extract event for notification key {}", notificationKey);
                     } else {
-                        processEventReady(event);
+                        final CallContext context = factory.createCallContext("SubscriptionEventQueue", CallOrigin.INTERNAL, UserType.SYSTEM);
+                        processEventReady(event, context);
                     }
                 }
             },
@@ -181,7 +188,7 @@ public class Engine implements EventListener, EntitlementService {
 
 
     @Override
-    public void processEventReady(EntitlementEvent event) {
+    public void processEventReady(EntitlementEvent event, CallContext context) {
         if (!event.isActive()) {
             return;
         }
@@ -194,10 +201,10 @@ public class Engine implements EventListener, EntitlementService {
         // Do any internal processing on that event before we send the event to the bus
         //
         if (event.getType() == EventType.PHASE) {
-            onPhaseEvent(subscription);
+            onPhaseEvent(subscription, context);
         } else if (event.getType() == EventType.API_USER &&
                 subscription.getCategory() == ProductCategory.BASE) {
-            onBasePlanEvent(subscription, (ApiEvent) event);
+            onBasePlanEvent(subscription, (ApiEvent) event, context);
         }
         try {
             eventBus.post(subscription.getTransitionFromEvent(event));
@@ -207,7 +214,7 @@ public class Engine implements EventListener, EntitlementService {
     }
 
 
-    private void onPhaseEvent(SubscriptionData subscription) {
+    private void onPhaseEvent(SubscriptionData subscription, CallContext context) {
         try {
             DateTime now = clock.getUTCNow();
             TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, now, now);
@@ -215,14 +222,14 @@ public class Engine implements EventListener, EntitlementService {
                     PhaseEventData.createNextPhaseEvent(nextTimedPhase.getPhase().getName(), subscription, now, nextTimedPhase.getStartPhase()) :
                         null;
             if (nextPhaseEvent != null) {
-                dao.createNextPhaseEvent(subscription.getId(), nextPhaseEvent);
+                dao.createNextPhaseEvent(subscription.getId(), nextPhaseEvent, context);
             }
         } catch (EntitlementError e) {
             log.error(String.format("Failed to insert next phase for subscription %s", subscription.getId()), e);
         }
     }
 
-    private void onBasePlanEvent(SubscriptionData baseSubscription, ApiEvent event) {
+    private void onBasePlanEvent(SubscriptionData baseSubscription, ApiEvent event, CallContext context) {
 
         DateTime now = clock.getUTCNow();
 
@@ -252,7 +259,7 @@ public class Engine implements EventListener, EntitlementService {
                 .setEffectiveDate(event.getEffectiveDate())
                 .setRequestedDate(now)
                 .setFromDisk(true));
-                dao.cancelSubscription(cur.getId(), cancelEvent);
+                dao.cancelSubscription(cur.getId(), cancelEvent, context);
             }
         }
     }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/EventListener.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/EventListener.java
index e9962d8..f6b13f9 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/EventListener.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/EventListener.java
@@ -17,11 +17,11 @@
 package com.ning.billing.entitlement.engine.core;
 
 import com.ning.billing.entitlement.events.EntitlementEvent;
-
+import com.ning.billing.util.callcontext.CallContext;
 
 
 public interface EventListener {
 
-    public void processEventReady(EntitlementEvent event);
+    public void processEventReady(EntitlementEvent event, CallContext context);
 
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
index 9a4865d..a69024c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
@@ -36,7 +36,7 @@ public interface EntitlementDao {
 
     public SubscriptionBundle getSubscriptionBundleFromId(UUID bundleId);
 
-    public SubscriptionBundle createSubscriptionBundle(SubscriptionBundleData bundle);
+    public SubscriptionBundle createSubscriptionBundle(SubscriptionBundleData bundle, CallContext context);
 
     public Subscription getSubscriptionFromId(UUID subscriptionId);
 
@@ -51,10 +51,10 @@ public interface EntitlementDao {
     public List<Subscription> getSubscriptionsForKey(String bundleKey);
 
     // Update
-    public void updateSubscription(SubscriptionData subscription);
+    public void updateSubscription(SubscriptionData subscription, CallContext context);
 
     // Event apis
-    public void createNextPhaseEvent(UUID subscriptionId, EntitlementEvent nextPhase);
+    public void createNextPhaseEvent(UUID subscriptionId, EntitlementEvent nextPhase, CallContext context);
 
     public EntitlementEvent getEventById(UUID eventId);
 
@@ -63,17 +63,17 @@ public interface EntitlementDao {
     public List<EntitlementEvent> getPendingEventsForSubscription(UUID subscriptionId);
 
     // Subscription creation, cancellation, changePlan apis
-    public void createSubscription(SubscriptionData subscription, List<EntitlementEvent> initialEvents);
+    public void createSubscription(SubscriptionData subscription, List<EntitlementEvent> initialEvents, CallContext context);
 
-    public void recreateSubscription(UUID subscriptionId, List<EntitlementEvent> recreateEvents);
+    public void recreateSubscription(UUID subscriptionId, List<EntitlementEvent> recreateEvents , CallContext context);
 
-    public void cancelSubscription(UUID subscriptionId, EntitlementEvent cancelEvent);
+    public void cancelSubscription(UUID subscriptionId, EntitlementEvent cancelEvent, CallContext context);
 
-    public void uncancelSubscription(UUID subscriptionId, List<EntitlementEvent> uncancelEvents);
+    public void uncancelSubscription(UUID subscriptionId, List<EntitlementEvent> uncancelEvents, CallContext context);
 
-    public void changePlan(UUID subscriptionId, List<EntitlementEvent> changeEvents);
+    public void changePlan(UUID subscriptionId, List<EntitlementEvent> changeEvents, CallContext context);
 
-    public void migrate(UUID accountId, AccountMigrationData data);
+    public void migrate(UUID accountId, AccountMigrationData data, CallContext context);
 
     // Custom Fields
     public void saveCustomFields(SubscriptionData subscription, CallContext context);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
index 6f17f8c..f52bd97 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
@@ -24,6 +24,8 @@ import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.audit.dao.AuditSqlDao;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.customfield.dao.CustomFieldDao;
 import org.joda.time.DateTime;
@@ -67,10 +69,13 @@ import com.ning.billing.util.notificationq.NotificationQueue;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService.NoSuchNotificationQueue;
 
+import javax.annotation.Nullable;
 
 public class EntitlementSqlDao implements EntitlementDao {
-
     private final static Logger log = LoggerFactory.getLogger(EntitlementSqlDao.class);
+    public static final String ENTITLEMENT_EVENTS_TABLE_NAME = "entitlement_events";
+    public static final String BUNDLES_TABLE_NAME = "bundles";
+    public static final String SUBSCRIPTIONS_TABLE_NAME = "subscriptions";
 
     private final Clock clock;
     private final SubscriptionSqlDao subscriptionsDao;
@@ -112,11 +117,16 @@ public class EntitlementSqlDao implements EntitlementDao {
     }
 
     @Override
-    public SubscriptionBundle createSubscriptionBundle(final SubscriptionBundleData bundle) {
+    public SubscriptionBundle createSubscriptionBundle(final SubscriptionBundleData bundle, final CallContext context) {
         return bundlesDao.inTransaction(new Transaction<SubscriptionBundle, BundleSqlDao>() {
             @Override
             public SubscriptionBundle inTransaction(BundleSqlDao bundlesDao, TransactionStatus status) {
                 bundlesDao.insertBundle(bundle);
+
+                AuditSqlDao auditSqlDao = bundlesDao.become(AuditSqlDao.class);
+                String bundleId = bundle.getId().toString();
+                auditSqlDao.insertAuditFromTransaction(BUNDLES_TABLE_NAME, bundleId, ChangeType.INSERT, context);
+
                 return bundle;
             }
         });
@@ -170,34 +180,36 @@ public class EntitlementSqlDao implements EntitlementDao {
     }
 
     @Override
-    public void updateSubscription(final SubscriptionData subscription) {
+    public void updateSubscription(final SubscriptionData subscription, final CallContext context) {
 
         final Date ctd = (subscription.getChargedThroughDate() != null)  ? subscription.getChargedThroughDate().toDate() : null;
         final Date ptd = (subscription.getPaidThroughDate() != null)  ? subscription.getPaidThroughDate().toDate() : null;
 
-
         subscriptionsDao.inTransaction(new Transaction<Void, SubscriptionSqlDao>() {
-
             @Override
             public Void inTransaction(SubscriptionSqlDao transactionalDao,
                     TransactionStatus status) throws Exception {
-                transactionalDao.updateSubscription(subscription.getId().toString(), subscription.getActiveVersion(), ctd, ptd);
+                transactionalDao.updateSubscription(subscription.getId().toString(), subscription.getActiveVersion(), ctd, ptd, context);
+
+                AuditSqlDao auditSqlDao = transactionalDao.become(AuditSqlDao.class);
+                String subscriptionId = subscription.getId().toString();
+                auditSqlDao.insertAuditFromTransaction(SUBSCRIPTIONS_TABLE_NAME, subscriptionId, ChangeType.UPDATE, context);
                 return null;
             }
         });
     }
 
-
-
     @Override
-    public void createNextPhaseEvent(final UUID subscriptionId, final EntitlementEvent nextPhase) {
+    public void createNextPhaseEvent(final UUID subscriptionId, final EntitlementEvent nextPhase, final CallContext context) {
         eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
-
             @Override
             public Void inTransaction(EventSqlDao dao,
                     TransactionStatus status) throws Exception {
-                cancelNextPhaseEventFromTransaction(subscriptionId, dao);
+                cancelNextPhaseEventFromTransaction(subscriptionId, dao, context);
                 dao.insertEvent(nextPhase);
+                AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, nextPhase.getId().toString(), ChangeType.INSERT, context);
+
                 recordFutureNotificationFromTransaction(dao,
                         nextPhase.getEffectiveDate(),
                         new NotificationKey() {
@@ -216,24 +228,20 @@ public class EntitlementSqlDao implements EntitlementDao {
         return eventsDao.getEventById(eventId.toString());
     }
 
-
     @Override
     public List<EntitlementEvent> getEventsForSubscription(UUID subscriptionId) {
-        List<EntitlementEvent> events = eventsDao.getEventsForSubscription(subscriptionId.toString());
-        return events;
+        return eventsDao.getEventsForSubscription(subscriptionId.toString());
     }
 
     @Override
     public List<EntitlementEvent> getPendingEventsForSubscription(UUID subscriptionId) {
         Date now = clock.getUTCNow().toDate();
-        List<EntitlementEvent> results = eventsDao.getFutureActiveEventForSubscription(subscriptionId.toString(), now);
-        return results;
+        return eventsDao.getFutureActiveEventForSubscription(subscriptionId.toString(), now);
     }
 
-
     @Override
     public void createSubscription(final SubscriptionData subscription,
-            final List<EntitlementEvent> initialEvents) {
+            final List<EntitlementEvent> initialEvents, final CallContext context) {
 
         subscriptionsDao.inTransaction(new Transaction<Void, SubscriptionSqlDao>() {
 
@@ -241,11 +249,14 @@ public class EntitlementSqlDao implements EntitlementDao {
             public Void inTransaction(SubscriptionSqlDao dao,
                     TransactionStatus status) throws Exception {
 
-                dao.insertSubscription(subscription);
+                dao.insertSubscription(subscription, context);
                 // STEPH batch as well
                 EventSqlDao eventsDaoFromSameTransaction = dao.become(EventSqlDao.class);
+                List<String> eventIds = new ArrayList<String>();
+
                 for (final EntitlementEvent cur : initialEvents) {
                     eventsDaoFromSameTransaction.insertEvent(cur);
+                    eventIds.add(cur.getId().toString()); // collect ids for batch audit log insert
                     recordFutureNotificationFromTransaction(dao,
                             cur.getEffectiveDate(),
                             new NotificationKey() {
@@ -255,6 +266,9 @@ public class EntitlementSqlDao implements EntitlementDao {
                                 }
                             });
                 }
+
+                AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, eventIds, ChangeType.INSERT, context);
                 return null;
             }
         });
@@ -262,40 +276,49 @@ public class EntitlementSqlDao implements EntitlementDao {
 
     @Override
     public void recreateSubscription(final UUID subscriptionId,
-            final List<EntitlementEvent> recreateEvents) {
+            final List<EntitlementEvent> recreateEvents, final CallContext context) {
 
         eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
             @Override
             public Void inTransaction(EventSqlDao dao,
                     TransactionStatus status) throws Exception {
 
+                List<String> eventIds = new ArrayList<String>();
                 for (final EntitlementEvent cur : recreateEvents) {
                     dao.insertEvent(cur);
+                    eventIds.add(cur.getId().toString()); // gather event ids for batch audit insert
                     recordFutureNotificationFromTransaction(dao,
                             cur.getEffectiveDate(),
                             new NotificationKey() {
-                        @Override
-                        public String toString() {
-                            return cur.getId().toString();
-                        }
-                    });
+                                @Override
+                                public String toString() {
+                                    return cur.getId().toString();
+                                }
+                            });
                 }
+
+                AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, eventIds, ChangeType.INSERT, context);
                 return null;
             }
         });
     }
 
     @Override
-    public void cancelSubscription(final UUID subscriptionId, final EntitlementEvent cancelEvent) {
+    public void cancelSubscription(final UUID subscriptionId, final EntitlementEvent cancelEvent, final CallContext context) {
 
         eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
             @Override
             public Void inTransaction(EventSqlDao dao,
                     TransactionStatus status) throws Exception {
-                cancelNextCancelEventFromTransaction(subscriptionId, dao);
-                cancelNextChangeEventFromTransaction(subscriptionId, dao);
-                cancelNextPhaseEventFromTransaction(subscriptionId, dao);
+                cancelNextCancelEventFromTransaction(subscriptionId, dao, context);
+                cancelNextChangeEventFromTransaction(subscriptionId, dao, context);
+                cancelNextPhaseEventFromTransaction(subscriptionId, dao, context);
                 dao.insertEvent(cancelEvent);
+                AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                String cancelEventId = cancelEvent.getId().toString();
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, cancelEventId, ChangeType.INSERT, context);
+
                 recordFutureNotificationFromTransaction(dao,
                         cancelEvent.getEffectiveDate(),
                         new NotificationKey() {
@@ -310,7 +333,7 @@ public class EntitlementSqlDao implements EntitlementDao {
     }
 
     @Override
-    public void uncancelSubscription(final UUID subscriptionId, final List<EntitlementEvent> uncancelEvents) {
+    public void uncancelSubscription(final UUID subscriptionId, final List<EntitlementEvent> uncancelEvents, final CallContext context) {
 
         eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
 
@@ -333,17 +356,25 @@ public class EntitlementSqlDao implements EntitlementDao {
 
                 if (existingCancelId != null) {
                     dao.unactiveEvent(existingCancelId.toString(), now);
+                    String deactivatedEventId = existingCancelId.toString();
+
+                    List<String> eventIds = new ArrayList<String>();
                     for (final EntitlementEvent cur : uncancelEvents) {
                         dao.insertEvent(cur);
+                        eventIds.add(cur.getId().toString()); // gather event ids for batch insert into audit log
                         recordFutureNotificationFromTransaction(dao,
                                 cur.getEffectiveDate(),
                                 new NotificationKey() {
-                            @Override
-                            public String toString() {
-                                return cur.getId().toString();
-                            }
-                        });
+                                    @Override
+                                    public String toString() {
+                                        return cur.getId().toString();
+                                    }
+                                });
                     }
+
+                    AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                    auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, deactivatedEventId, ChangeType.UPDATE, context);
+                    auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, eventIds, ChangeType.INSERT, context);
                 }
                 return null;
             }
@@ -351,42 +382,50 @@ public class EntitlementSqlDao implements EntitlementDao {
     }
 
     @Override
-    public void changePlan(final UUID subscriptionId, final List<EntitlementEvent> changeEvents) {
+    public void changePlan(final UUID subscriptionId, final List<EntitlementEvent> changeEvents, final CallContext context) {
         eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
             @Override
-            public Void inTransaction(EventSqlDao dao,
-                    TransactionStatus status) throws Exception {
-                cancelNextChangeEventFromTransaction(subscriptionId, dao);
-                cancelNextPhaseEventFromTransaction(subscriptionId, dao);
+            public Void inTransaction(EventSqlDao dao, TransactionStatus status) throws Exception {
+                cancelNextChangeEventFromTransaction(subscriptionId, dao, context);
+                cancelNextPhaseEventFromTransaction(subscriptionId, dao, context);
+
+                List<String> eventIds = new ArrayList<String>();
                 for (final EntitlementEvent cur : changeEvents) {
                     dao.insertEvent(cur);
+                    eventIds.add(cur.getId().toString()); // gather event ids for batch audit log insert
+
                     recordFutureNotificationFromTransaction(dao,
                             cur.getEffectiveDate(),
                             new NotificationKey() {
-                        @Override
-                        public String toString() {
-                            return cur.getId().toString();
-                        }
-                    });
+                                @Override
+                                public String toString() {
+                                    return cur.getId().toString();
+                                }
+                            });
                 }
+
+                AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, eventIds, ChangeType.INSERT, context);
                 return null;
             }
         });
     }
 
-    private void cancelNextPhaseEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao) {
-        cancelFutureEventFromTransaction(subscriptionId, dao, EventType.PHASE, null);
+    private void cancelNextPhaseEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao, final CallContext context) {
+        cancelFutureEventFromTransaction(subscriptionId, dao, EventType.PHASE, null, context);
     }
 
-    private void cancelNextChangeEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao) {
-        cancelFutureEventFromTransaction(subscriptionId, dao, EventType.API_USER, ApiEventType.CHANGE);
+    private void cancelNextChangeEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao, final CallContext context) {
+        cancelFutureEventFromTransaction(subscriptionId, dao, EventType.API_USER, ApiEventType.CHANGE, context);
     }
 
-    private void cancelNextCancelEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao) {
-        cancelFutureEventFromTransaction(subscriptionId, dao, EventType.API_USER, ApiEventType.CANCEL);
+    private void cancelNextCancelEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao, final CallContext context) {
+        cancelFutureEventFromTransaction(subscriptionId, dao, EventType.API_USER, ApiEventType.CANCEL, context);
     }
 
-    private void cancelFutureEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao, EventType type, ApiEventType apiType) {
+    private void cancelFutureEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao,
+                                                  final EventType type, @Nullable final ApiEventType apiType,
+                                                  final CallContext context) {
 
         UUID futureEventId = null;
         Date now = clock.getUTCNow().toDate();
@@ -405,6 +444,9 @@ public class EntitlementSqlDao implements EntitlementDao {
 
         if (futureEventId != null) {
             dao.unactiveEvent(futureEventId.toString(), now);
+
+            AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+            auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, futureEventId.toString(), ChangeType.UPDATE, context);
         }
     }
 
@@ -419,9 +461,8 @@ public class EntitlementSqlDao implements EntitlementDao {
             return null;
         }
         List<Subscription> bundleInput = new ArrayList<Subscription>();
-        Subscription baseSubscription = null;
         if (input.getCategory() == ProductCategory.ADD_ON) {
-            baseSubscription = getBaseSubscription(input.getBundleId(), false);
+            Subscription baseSubscription = getBaseSubscription(input.getBundleId(), false);
             bundleInput.add(baseSubscription);
             bundleInput.add(input);
         } else {
@@ -507,7 +548,7 @@ public class EntitlementSqlDao implements EntitlementDao {
     }
 
     @Override
-    public void migrate(final UUID accountId, final AccountMigrationData accountData) {
+    public void migrate(final UUID accountId, final AccountMigrationData accountData, final CallContext context) {
 
         eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
 
@@ -518,12 +559,20 @@ public class EntitlementSqlDao implements EntitlementDao {
                 SubscriptionSqlDao transSubDao = transEventDao.become(SubscriptionSqlDao.class);
                 BundleSqlDao transBundleDao = transEventDao.become(BundleSqlDao.class);
 
+                List<String> bundleIds = new ArrayList<String>();
+                List<String> subscriptionIds = new ArrayList<String>();
+                List<String> eventIds = new ArrayList<String>();
+
                 for (BundleMigrationData curBundle : accountData.getData()) {
                     SubscriptionBundleData bundleData = curBundle.getData();
+
                     for (SubscriptionMigrationData curSubscription : curBundle.getSubscriptions()) {
+
                         SubscriptionData subData = curSubscription.getData();
                         for (final EntitlementEvent curEvent : curSubscription.getInitialEvents()) {
                             transEventDao.insertEvent(curEvent);
+                            eventIds.add(curEvent.getId().toString()); // gather event ids for batch audit
+
                             recordFutureNotificationFromTransaction(transEventDao,
                                     curEvent.getEffectiveDate(),
                                     new NotificationKey() {
@@ -533,20 +582,28 @@ public class EntitlementSqlDao implements EntitlementDao {
                                 }
                             });
                         }
-                        transSubDao.insertSubscription(subData);
+                        transSubDao.insertSubscription(subData, context);
+                        subscriptionIds.add(subData.getId().toString()); // gather subscription ids for batch audit
                     }
                     transBundleDao.insertBundle(bundleData);
+                    bundleIds.add(bundleData.getId().toString()); // gather bundle ids for batch audit
                 }
+
+                // add audit records for bundles, subscriptions, and events
+                AuditSqlDao auditSqlDao = transBundleDao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(SUBSCRIPTIONS_TABLE_NAME, subscriptionIds, ChangeType.INSERT, context);
+                auditSqlDao.insertAuditFromTransaction(BUNDLES_TABLE_NAME, bundleIds, ChangeType.INSERT, context);
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, eventIds, ChangeType.INSERT, context);
+
                 return null;
             }
         });
     }
 
-
     public Subscription getBaseSubscription(final UUID bundleId, boolean rebuildSubscription) {
         List<Subscription> subscriptions = subscriptionsDao.getSubscriptionsFromBundleId(bundleId.toString());
         for (Subscription cur : subscriptions) {
-            if (((SubscriptionData)cur).getCategory() == ProductCategory.BASE) {
+            if (cur.getCategory() == ProductCategory.BASE) {
                 return  rebuildSubscription ? buildSubscription(cur) : cur;
             }
         }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
index 741ae83..04f2965 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
@@ -20,6 +20,8 @@ import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextBinder;
 import com.ning.billing.util.dao.BinderBase;
 import com.ning.billing.util.dao.MapperBase;
 import org.joda.time.DateTime;
@@ -42,24 +44,26 @@ import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
-
 @ExternalizedSqlViaStringTemplate3()
 public interface SubscriptionSqlDao extends Transactional<SubscriptionSqlDao>, CloseMe, Transmogrifier {
 	@SqlUpdate
-    public void insertSubscription(@Bind(binder = ISubscriptionDaoBinder.class) SubscriptionData sub);
+    public void insertSubscription(@Bind(binder = SubscriptionBinder.class) SubscriptionData sub,
+                                   @CallContextBinder final CallContext context);
 
     @SqlQuery
-    @Mapper(ISubscriptionDaoSqlMapper.class)
+    @Mapper(SubscriptionMapper.class)
     public Subscription getSubscriptionFromId(@Bind("id") String id);
 
     @SqlQuery
-    @Mapper(ISubscriptionDaoSqlMapper.class)
+    @Mapper(SubscriptionMapper.class)
     public List<Subscription> getSubscriptionsFromBundleId(@Bind("bundle_id") String bundleId);
 
     @SqlUpdate
-    public void updateSubscription(@Bind("id") String id, @Bind("active_version") long activeVersion, @Bind("ctd_dt") Date ctd, @Bind("ptd_dt") Date ptd);
+    public void updateSubscription(@Bind("id") String id, @Bind("active_version") long activeVersion,
+                                   @Bind("ctd_dt") Date ctd, @Bind("ptd_dt") Date ptd,
+                                   @CallContextBinder final CallContext context);
    
-    public static class ISubscriptionDaoBinder extends BinderBase implements Binder<Bind, SubscriptionData> {
+    public static class SubscriptionBinder extends BinderBase implements Binder<Bind, SubscriptionData> {
         @Override
         public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, SubscriptionData sub) {
             stmt.bind("id", sub.getId().toString());
@@ -73,7 +77,7 @@ public interface SubscriptionSqlDao extends Transactional<SubscriptionSqlDao>, C
         }
     }
 
-    public static class ISubscriptionDaoSqlMapper extends MapperBase implements ResultSetMapper<SubscriptionData> {
+    public static class SubscriptionMapper extends MapperBase implements ResultSetMapper<SubscriptionData> {
         @Override
         public SubscriptionData map(int arg0, ResultSet r, StatementContext ctx)
                 throws SQLException {
@@ -87,7 +91,7 @@ public interface SubscriptionSqlDao extends Transactional<SubscriptionSqlDao>, C
             DateTime ptd = getDate(r, "ptd_dt");
             long activeVersion = r.getLong("active_version");
 
-            SubscriptionData subscription = new SubscriptionData(new SubscriptionBuilder()
+            return new SubscriptionData(new SubscriptionBuilder()
             .setId(id)
             .setBundleId(bundleId)
             .setCategory(category)
@@ -96,7 +100,6 @@ public interface SubscriptionSqlDao extends Transactional<SubscriptionSqlDao>, C
             .setActiveVersion(activeVersion)
             .setChargedThroughDate(ctd)
             .setPaidThroughDate(ptd));
-            return subscription;
         }
     }
 }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
index ee9ef84..1d679a9 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
@@ -44,10 +44,10 @@ import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.Entitl
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import org.testng.annotations.Test;
 
+@Test(groups = {"slow"})
 public abstract class TestMigration extends TestApiBase {
-
-
     public void testSingleBasePlan() {
 
         try {
@@ -57,7 +57,7 @@ public abstract class TestMigration extends TestApiBase {
             DateTime afterMigration = clock.getUTCNow();
 
             testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
-            migrationApi.migrate(toBeMigrated);
+            migrationApi.migrate(toBeMigrated, context);
             assertTrue(testListener.isCompleted(5000));
 
             List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
@@ -79,7 +79,6 @@ public abstract class TestMigration extends TestApiBase {
         }
     }
 
-
     public void testPlanWithAddOn() {
         try {
             DateTime beforeMigration = clock.getUTCNow();
@@ -90,7 +89,7 @@ public abstract class TestMigration extends TestApiBase {
 
             testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
             testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
-            migrationApi.migrate(toBeMigrated);
+            migrationApi.migrate(toBeMigrated, context);
             assertTrue(testListener.isCompleted(5000));
 
             List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
@@ -125,7 +124,6 @@ public abstract class TestMigration extends TestApiBase {
         }
     }
 
-
     public void testSingleBasePlanFutureCancelled() {
 
         try {
@@ -136,7 +134,7 @@ public abstract class TestMigration extends TestApiBase {
             DateTime afterMigration = clock.getUTCNow();
 
             testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
-            migrationApi.migrate(toBeMigrated);
+            migrationApi.migrate(toBeMigrated, context);
             assertTrue(testListener.isCompleted(5000));
 
             List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
@@ -176,13 +174,11 @@ public abstract class TestMigration extends TestApiBase {
     public void testSingleBasePlanWithPendingPhase() {
 
         try {
-            DateTime beforeMigration = clock.getUTCNow();
             final DateTime trialDate = clock.getUTCNow().minusDays(10);
             EntitlementAccountMigration toBeMigrated = createAccountFuturePendingPhase(trialDate);
-            DateTime afterMigration = clock.getUTCNow();
 
             testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
-            migrationApi.migrate(toBeMigrated);
+            migrationApi.migrate(toBeMigrated, context);
             assertTrue(testListener.isCompleted(5000));
 
             List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
@@ -220,7 +216,6 @@ public abstract class TestMigration extends TestApiBase {
         }
     }
 
-
     public void testSingleBasePlanWithPendingChange() {
 
         try {
@@ -229,7 +224,7 @@ public abstract class TestMigration extends TestApiBase {
             DateTime afterMigration = clock.getUTCNow();
 
             testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
-            migrationApi.migrate(toBeMigrated);
+            migrationApi.migrate(toBeMigrated, context);
             assertTrue(testListener.isCompleted(5000));
 
             List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
index 59121c9..c7728aa 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
@@ -26,6 +26,8 @@ import java.net.URL;
 import java.util.List;
 import java.util.UUID;
 
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TestCallContext;
 import org.apache.commons.io.IOUtils;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
@@ -79,7 +81,6 @@ import javax.annotation.Nullable;
 
 
 public abstract class TestApiBase {
-
     protected static final Logger log = LoggerFactory.getLogger(TestApiBase.class);
 
     protected static final long DAY_IN_MS = (24 * 3600 * 1000);
@@ -102,6 +103,7 @@ public abstract class TestApiBase {
     protected SubscriptionBundle bundle;
 
     private MysqlTestingHelper helper;
+    protected CallContext context = new TestCallContext("Api Test");
 
     public static void loadSystemPropertiesFromClasspath(final String resource) {
         final URL url = TestApiBase.class.getResource(resource);
@@ -195,7 +197,7 @@ public abstract class TestApiBase {
         try {
             busService.getBus().register(testListener);
             UUID accountId = UUID.randomUUID();
-            bundle = entitlementApi.createBundleForAccount(accountId, "myDefaultBundle");
+            bundle = entitlementApi.createBundleForAccount(accountId, "myDefaultBundle", context);
         } catch (Exception e) {
             Assert.fail(e.getMessage());
         }
@@ -219,12 +221,12 @@ public abstract class TestApiBase {
         return createSubscriptionWithBundle(bundle.getId(), productName, term, planSet);
     }
 
-
     protected SubscriptionData createSubscriptionWithBundle(final UUID bundleId, final String productName, final BillingPeriod term, final String planSet) throws EntitlementUserApiException {
         testListener.pushExpectedEvent(NextEvent.CREATE);
+
         SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundleId,
                 new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSet, null),
-                clock.getUTCNow());
+                clock.getUTCNow(), context);
         assertNotNull(subscription);
         assertTrue(testListener.isCompleted(5000));
         return subscription;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
index 7db938e..927ea08 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
@@ -41,7 +41,6 @@ import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.TestApiBase;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
-import com.ning.billing.entitlement.api.user.SubscriptionTransition.SubscriptionTransitionType;
 import com.ning.billing.entitlement.glue.MockEngineModuleSql;
 import com.ning.billing.util.clock.DefaultClock;
 
@@ -52,7 +51,6 @@ public class TestUserApiAddOn extends TestApiBase {
         return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
     }
 
-
     @Test(enabled=true, groups={"slow"})
     public void testCreateCancelAddon() {
 
@@ -61,7 +59,7 @@ public class TestUserApiAddOn extends TestApiBase {
             BillingPeriod baseTerm = BillingPeriod.MONTHLY;
             String basePriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
 
-            SubscriptionData baseSubscription = createSubscription(baseProduct, baseTerm, basePriceList);
+            createSubscription(baseProduct, baseTerm, basePriceList);
 
             String aoProduct = "Telescopic-Scope";
             BillingPeriod aoTerm = BillingPeriod.MONTHLY;
@@ -71,7 +69,7 @@ public class TestUserApiAddOn extends TestApiBase {
             assertEquals(aoSubscription.getState(), SubscriptionState.ACTIVE);
 
             DateTime now = clock.getUTCNow();
-            aoSubscription.cancel(now, false);
+            aoSubscription.cancel(now, false, context);
 
             testListener.reset();
             testListener.pushExpectedEvent(NextEvent.CANCEL);
@@ -114,11 +112,11 @@ public class TestUserApiAddOn extends TestApiBase {
             DateTime now = clock.getUTCNow();
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(now, ctd);
-            billingApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate, context);
             baseSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(baseSubscription.getId());
 
             // FUTURE CANCELLATION
-            baseSubscription.cancel(now, false);
+            baseSubscription.cancel(now, false, context);
 
             // REFETCH AO SUBSCRIPTION AND CHECK THIS IS ACTIVE
             aoSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(aoSubscription.getId());
@@ -131,7 +129,6 @@ public class TestUserApiAddOn extends TestApiBase {
             testListener.pushExpectedEvent(NextEvent.CANCEL);
             testListener.pushExpectedEvent(NextEvent.CANCEL);
             clock.addDeltaFromReality(ctd);
-            now = clock.getUTCNow();
             assertTrue(testListener.isCompleted(5000));
 
             // REFETCH AO SUBSCRIPTION AND CHECK THIS IS CANCELLED
@@ -174,7 +171,7 @@ public class TestUserApiAddOn extends TestApiBase {
             DateTime now = clock.getUTCNow();
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(now, ctd);
-            billingApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate, context);
             baseSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(baseSubscription.getId());
 
             // CHANGE IMMEDIATELY WITH TO BP WITH NON INCLUDED ADDON
@@ -185,7 +182,7 @@ public class TestUserApiAddOn extends TestApiBase {
             testListener.reset();
             testListener.pushExpectedEvent(NextEvent.CHANGE);
             testListener.pushExpectedEvent(NextEvent.CANCEL);
-            baseSubscription.changePlan(newBaseProduct, newBaseTerm, newBasePriceList, now);
+            baseSubscription.changePlan(newBaseProduct, newBaseTerm, newBasePriceList, now, context);
             assertTrue(testListener.isCompleted(5000));
 
             // REFETCH AO SUBSCRIPTION AND CHECK THIS CANCELLED
@@ -227,7 +224,7 @@ public class TestUserApiAddOn extends TestApiBase {
             DateTime now = clock.getUTCNow();
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(now, ctd);
-            billingApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate, context);
             baseSubscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(baseSubscription.getId());
 
             // CHANGE IMMEDIATELY WITH TO BP WITH NON AVAILABLE ADDON
@@ -235,7 +232,7 @@ public class TestUserApiAddOn extends TestApiBase {
             BillingPeriod newBaseTerm = BillingPeriod.MONTHLY;
             String newBasePriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
 
-            baseSubscription.changePlan(newBaseProduct, newBaseTerm, newBasePriceList, now);
+            baseSubscription.changePlan(newBaseProduct, newBaseTerm, newBasePriceList, now, context);
 
 
             // REFETCH AO SUBSCRIPTION AND CHECK THIS IS ACTIVE
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
index 88c3825..55ad5e8 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
@@ -64,7 +64,7 @@ public abstract class TestUserApiCancel extends TestApiBase {
             testListener.pushExpectedEvent(NextEvent.CANCEL);
 
             // CANCEL in trial period to get IMM policy
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
             currentPhase = subscription.getCurrentPhase();
             testListener.isCompleted(1000);
 
@@ -105,13 +105,13 @@ public abstract class TestUserApiCancel extends TestApiBase {
             // SET CTD + RE READ SUBSCRIPTION + CHANGE PLAN
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(expectedPhaseTrialChange, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
 
             testListener.pushExpectedEvent(NextEvent.CANCEL);
 
             // CANCEL
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
             assertFalse(testListener.isCompleted(2000));
 
             // MOVE TO EOT + RECHECK
@@ -158,7 +158,7 @@ public abstract class TestUserApiCancel extends TestApiBase {
             testListener.pushExpectedEvent(NextEvent.CANCEL);
 
             // CANCEL
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
             assertTrue(testListener.isCompleted(2000));
 
             PlanPhase currentPhase = subscription.getCurrentPhase();
@@ -202,16 +202,16 @@ public abstract class TestUserApiCancel extends TestApiBase {
             // SET CTD + RE READ SUBSCRIPTION + CHANGE PLAN
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(expectedPhaseTrialChange, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
 
             testListener.pushExpectedEvent(NextEvent.CANCEL);
 
             // CANCEL
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
             assertFalse(testListener.isCompleted(2000));
 
-            subscription.uncancel();
+            subscription.uncancel(context);
 
             // MOVE TO EOT + RECHECK
             clock.addDeltaFromReality(ctd);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
index 4505ef0..f7f8c41 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
@@ -88,7 +88,7 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
 
             // CHANGE PLAN
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
+            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow(), context);
             assertTrue(testListener.isCompleted(2000));
 
             // CHECK CHANGE PLAN
@@ -129,12 +129,12 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
             // SET CTD
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(expectedPhaseTrialChange, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
 
             // RE READ SUBSCRIPTION + CHANGE PLAN
             testListener.pushExpectedEvent(NextEvent.CHANGE);
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
-            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
+            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
             testListener.reset();
 
@@ -186,7 +186,7 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
             clock.setDeltaFromReality(moveALittleInTime, 0);
 
             // CHANGE PLAN IMM
-            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
+            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow(), context);
             checkChangePlan(subscription, toProd, ProductCategory.BASE, toTerm, PhaseType.TRIAL);
 
             assertTrue(testListener.isCompleted(2000));
@@ -245,7 +245,7 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
             // SET CTD
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(expectedPhaseTrialChange, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
 
             // RE READ SUBSCRIPTION + CHECK CURRENT PHASE
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
@@ -257,7 +257,7 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
             currentTime = clock.getUTCNow();
 
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
+            subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow(), context);
 
             checkChangePlan(subscription, fromProd, ProductCategory.BASE, fromTerm, PhaseType.EVERGREEN);
 
@@ -317,17 +317,17 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
             DateTime startDiscountPhase = DefaultClock.addDuration(subscription.getStartDate(), durationList);
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(startDiscountPhase, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
 
             // CHANGE EOT
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
 
             // CHANGE
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
 
             Plan currentPlan = subscription.getCurrentPlan();
@@ -363,18 +363,18 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
             DateTime startDiscountPhase = DefaultClock.addDuration(subscription.getStartDate(), durationList);
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(startDiscountPhase, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
 
             // CHANGE EOT
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Shotgun", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Shotgun", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
             testListener.reset();
 
             // CHANGE EOT
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
             testListener.reset();
 
@@ -442,7 +442,7 @@ public abstract class TestUserApiChangePlan extends TestApiBase {
             // CHANGE IMMEDIATE TO A 3 PHASES PLAN
             testListener.reset();
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow(), context);
             assertTrue(testListener.isCompleted(3000));
             testListener.reset();
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
index a56f13b..a8d6e0c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
@@ -60,7 +60,7 @@ public abstract class TestUserApiCreate extends TestApiBase {
 
 
             SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                    getProductSpecifier(productName, planSetName, term, null), requestedDate);
+                    getProductSpecifier(productName, planSetName, term, null), requestedDate, context);
             assertNotNull(subscription);
 
             assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
@@ -91,7 +91,7 @@ public abstract class TestUserApiCreate extends TestApiBase {
             testListener.pushExpectedEvent(NextEvent.CREATE);
 
             SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                    getProductSpecifier(productName, planSetName, term, PhaseType.EVERGREEN), clock.getUTCNow());
+                    getProductSpecifier(productName, planSetName, term, PhaseType.EVERGREEN), clock.getUTCNow(), context);
             assertNotNull(subscription);
 
             assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
@@ -130,7 +130,7 @@ public abstract class TestUserApiCreate extends TestApiBase {
 
             SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
                     getProductSpecifier(productName, planSetName, term, null),
-                    clock.getUTCNow());
+                    clock.getUTCNow(), context);
             assertNotNull(subscription);
 
             assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
@@ -179,8 +179,6 @@ public abstract class TestUserApiCreate extends TestApiBase {
         log.info("Starting testSimpleSubscriptionThroughPhases");
         try {
 
-            DateTime curTime = clock.getUTCNow();
-
             String productName = "Pistol";
             BillingPeriod term = BillingPeriod.ANNUAL;
             String planSetName = "gunclubDiscount";
@@ -189,7 +187,7 @@ public abstract class TestUserApiCreate extends TestApiBase {
 
             // CREATE SUBSCRIPTION
             SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                    getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow());
+                    getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow(), context);
             assertNotNull(subscription);
 
             PlanPhase currentPhase = subscription.getCurrentPhase();
@@ -197,12 +195,9 @@ public abstract class TestUserApiCreate extends TestApiBase {
             assertEquals(currentPhase.getPhaseType(), PhaseType.TRIAL);
             assertTrue(testListener.isCompleted(5000));
 
-
-
             // MOVE TO DISCOUNT PHASE
             testListener.pushExpectedEvent(NextEvent.PHASE);
             clock.setDeltaFromReality(currentPhase.getDuration(), DAY_IN_MS);
-            curTime = clock.getUTCNow();
             currentPhase = subscription.getCurrentPhase();
             assertNotNull(currentPhase);
             assertEquals(currentPhase.getPhaseType(), PhaseType.DISCOUNT);
@@ -214,7 +209,6 @@ public abstract class TestUserApiCreate extends TestApiBase {
             assertTrue(testListener.isCompleted(2000));
 
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
-            curTime = clock.getUTCNow();
             currentPhase = subscription.getCurrentPhase();
             assertNotNull(currentPhase);
             assertEquals(currentPhase.getPhaseType(), PhaseType.EVERGREEN);
@@ -237,7 +231,7 @@ public abstract class TestUserApiCreate extends TestApiBase {
             testListener.pushExpectedEvent(NextEvent.CREATE);
 
             SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                    getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow());
+                    getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow(), context);
             assertNotNull(subscription);
 
         } catch (EntitlementUserApiException e) {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
index 3fd8a7c..74fbef7 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
@@ -79,7 +79,7 @@ public class TestUserApiDemos extends TestApiBase {
 
             /* STEP 2. CHANGE PLAN WHILE IN TRIAL */
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow(), context);
             assertTrue(testListener.isCompleted(3000));
 
             displayState(subscription.getId(), "STEP 2. CHANGED PLAN WHILE IN TRIAL");
@@ -98,11 +98,11 @@ public class TestUserApiDemos extends TestApiBase {
 
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(startDiscountPhase, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
 
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Shotgun", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Shotgun", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
             testListener.reset();
 
@@ -110,7 +110,7 @@ public class TestUserApiDemos extends TestApiBase {
 
             /* STEP 5. CHANGE AGAIN */
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
             testListener.reset();
 
@@ -153,7 +153,7 @@ public class TestUserApiDemos extends TestApiBase {
 
             /* STEP 8. CANCEL IMM (NO CTD) */
             testListener.pushExpectedEvent(NextEvent.CANCEL);
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
 
             displayState(subscription.getId(), "STEP 8.  CANCELLATION");
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
index 7442298..11103ba 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
@@ -32,6 +32,7 @@ import org.joda.time.DateTime;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import javax.annotation.Nullable;
 import java.util.UUID;
 
 import static org.testng.Assert.assertEquals;
@@ -49,7 +50,7 @@ public class TestUserApiError extends TestApiBase {
 
     @Test(enabled=true, groups={"fast"})
     public void testCreateSubscriptionBadCatalog() {
-        // WRONG PRODUTCS
+        // WRONG PRODUCTS
         tCreateSubscriptionInternal(bundle.getId(), null, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.CAT_NULL_PRODUCT_NAME);
         tCreateSubscriptionInternal(bundle.getId(), "Whatever", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.CAT_NO_SUCH_PRODUCT);
 
@@ -89,7 +90,7 @@ public class TestUserApiError extends TestApiBase {
         try {
             SubscriptionData subscription = createSubscription("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME);
             try {
-                subscription.recreate(getProductSpecifier("Pistol", PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, null), clock.getUTCNow());
+                subscription.recreate(getProductSpecifier("Pistol", PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, null), clock.getUTCNow(), context);
                 Assert.assertFalse(true);
             } catch (EntitlementUserApiException e) {
                 assertEquals(e.getCode(), ErrorCode.ENT_RECREATE_BAD_STATE.getCode());
@@ -104,7 +105,7 @@ public class TestUserApiError extends TestApiBase {
     public void testCreateSubscriptionAddOnNotAvailable() {
         try {
             UUID accountId = UUID.randomUUID();
-            SubscriptionBundle aoBundle = entitlementApi.createBundleForAccount(accountId, "myAOBundle");
+            SubscriptionBundle aoBundle = entitlementApi.createBundleForAccount(accountId, "myAOBundle", context);
             createSubscriptionWithBundle(aoBundle.getId(), "Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
             tCreateSubscriptionInternal(aoBundle.getId(), "Telescopic-Scope", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_AO_NOT_AVAILABLE);
         } catch (Exception e) {
@@ -117,7 +118,7 @@ public class TestUserApiError extends TestApiBase {
     public void testCreateSubscriptionAddOnIncluded() {
         try {
             UUID accountId = UUID.randomUUID();
-            SubscriptionBundle aoBundle = entitlementApi.createBundleForAccount(accountId, "myAOBundle");
+            SubscriptionBundle aoBundle = entitlementApi.createBundleForAccount(accountId, "myAOBundle", context);
             createSubscriptionWithBundle(aoBundle.getId(), "Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
             tCreateSubscriptionInternal(aoBundle.getId(), "Telescopic-Scope", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_AO_ALREADY_INCLUDED);
         } catch (Exception e) {
@@ -127,12 +128,12 @@ public class TestUserApiError extends TestApiBase {
     }
 
 
-    private void tCreateSubscriptionInternal(UUID bundleId, String productName,
-            BillingPeriod term, String planSet, ErrorCode expected)  {
+    private void tCreateSubscriptionInternal(@Nullable UUID bundleId, @Nullable String productName,
+            @Nullable BillingPeriod term, String planSet, ErrorCode expected)  {
         try {
             entitlementApi.createSubscription(bundleId,
                     getProductSpecifier(productName, planSet, term, null),
-                    clock.getUTCNow());
+                    clock.getUTCNow(), context);
             Assert.fail("Exception expected, error code: " + expected);
         } catch (EntitlementUserApiException e) {
             assertEquals(e.getCode(), expected.getCode());
@@ -151,9 +152,9 @@ public class TestUserApiError extends TestApiBase {
             Subscription subscription = createSubscription("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME);
 
             testListener.pushExpectedEvent(NextEvent.CANCEL);
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
             try {
-                subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow());
+                subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow(), context);
             } catch (EntitlementUserApiException e) {
                 assertEquals(e.getCode(), ErrorCode.ENT_CHANGE_NON_ACTIVE.getCode());
                 try {
@@ -186,13 +187,13 @@ public class TestUserApiError extends TestApiBase {
             DateTime expectedPhaseTrialChange = DefaultClock.addDuration(subscription.getStartDate(), trialPhase.getDuration());
             Duration ctd = getDurationMonth(1);
             DateTime newChargedThroughDate = DefaultClock.addDuration(expectedPhaseTrialChange, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
 
             subscription = entitlementApi.getSubscriptionFromId(subscription.getId());
 
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
             try {
-                subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow());
+                subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow(), context);
             } catch (EntitlementUserApiException e) {
                 assertEquals(e.getCode(), ErrorCode.ENT_CHANGE_FUTURE_CANCELLED.getCode());
                 try {
@@ -218,7 +219,7 @@ public class TestUserApiError extends TestApiBase {
             Subscription subscription = createSubscription("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
 
             try {
-                subscription.uncancel();
+                subscription.uncancel(context);
             } catch (EntitlementUserApiException e) {
                 assertEquals(e.getCode(), ErrorCode.ENT_UNCANCEL_BAD_STATE.getCode());
                 try {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
index cff7e91..7dbc802 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
@@ -69,7 +69,7 @@ public abstract class TestUserApiRecreate extends TestApiBase {
         testListener.pushExpectedEvent(NextEvent.PHASE);
         testListener.pushExpectedEvent(NextEvent.CREATE);
         SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                getProductSpecifier(productName, planSetName, term, null), requestedDate);
+                getProductSpecifier(productName, planSetName, term, null), requestedDate, context);
         assertNotNull(subscription);
         assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
         assertEquals(subscription.getBundleId(), bundle.getId());
@@ -86,9 +86,9 @@ public abstract class TestUserApiRecreate extends TestApiBase {
 
             if (fromUserAPi) {
                 subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                        getProductSpecifier(productName, planSetName, term, null), requestedDate);
+                        getProductSpecifier(productName, planSetName, term, null), requestedDate, context);
             } else {
-                subscription.recreate(getProductSpecifier(productName, planSetName, term, null), requestedDate);
+                subscription.recreate(getProductSpecifier(productName, planSetName, term, null), requestedDate, context);
             }
             Assert.fail("Expected Create API to fail since BP already exists");
         } catch (EntitlementUserApiException e) {
@@ -97,12 +97,12 @@ public abstract class TestUserApiRecreate extends TestApiBase {
 
         // NOW CANCEL ADN THIS SHOULD WORK
         testListener.pushExpectedEvent(NextEvent.CANCEL);
-        subscription.cancel(null, false);
+        subscription.cancel(null, false, context);
 
         testListener.pushExpectedEvent(NextEvent.PHASE);
         testListener.pushExpectedEvent(NextEvent.RE_CREATE);
 
-        // Avoid ordering issue for events at excat same date; this is actually a real good test, we
+        // Avoid ordering issue for events at exact same date; this is actually a real good test, we
         // we test it at Beatrix level. At this level that would work for sql tests but not for in memory.
         try {
             Thread.sleep(1000);
@@ -112,9 +112,9 @@ public abstract class TestUserApiRecreate extends TestApiBase {
 
         if (fromUserAPi) {
             subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                    getProductSpecifier(productName, planSetName, term, null), requestedDate);
+                    getProductSpecifier(productName, planSetName, term, null), requestedDate, context);
         } else {
-            subscription.recreate(getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow());
+            subscription.recreate(getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow(), context);
         }
         assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
         assertEquals(subscription.getBundleId(), bundle.getId());
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
index f69b36a..1ece406 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
@@ -53,7 +53,7 @@ public class TestUserApiScenarios extends TestApiBase {
             assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
 
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow(), context);
             testListener.isCompleted(3000);
 
             // MOVE TO NEXT PHASE
@@ -65,21 +65,21 @@ public class TestUserApiScenarios extends TestApiBase {
             Duration ctd = getDurationMonth(1);
             DateTime expectedPhaseTrialChange = DefaultClock.addDuration(subscription.getStartDate(), trialPhase.getDuration());
             DateTime newChargedThroughDate = DefaultClock.addDuration(expectedPhaseTrialChange, ctd);
-            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+            billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, context);
             subscription = (SubscriptionData) entitlementApi.getSubscriptionFromId(subscription.getId());
 
             // CANCEL EOT
             testListener.pushExpectedEvent(NextEvent.CANCEL);
-            subscription.cancel(clock.getUTCNow(), false);
+            subscription.cancel(clock.getUTCNow(), false, context);
             assertFalse(testListener.isCompleted(2000));
             testListener.reset();
 
             // UNCANCEL
-            subscription.uncancel();
+            subscription.uncancel(context);
 
             // CHANGE EOT
             testListener.pushExpectedEvent(NextEvent.CHANGE);
-            subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow());
+            subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow(), context);
             assertFalse(testListener.isCompleted(2000));
 
             clock.addDeltaFromReality(ctd);
@@ -90,10 +90,4 @@ public class TestUserApiScenarios extends TestApiBase {
             Assert.fail(e.getMessage());
         }
     }
-
-    @Test(enabled=false)
-    private void testChangeEOTCancelUncancelChangeIMM() {
-
-    }
-
 }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
index f6881fd..bbfd42a 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
@@ -79,7 +79,7 @@ public class TestUserCustomFieldsSql extends TestApiBase {
             testListener.pushExpectedEvent(NextEvent.PHASE);
             testListener.pushExpectedEvent(NextEvent.CREATE);
             SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                    getProductSpecifier(productName, planSetName, term, null), requestedDate);
+                    getProductSpecifier(productName, planSetName, term, null), requestedDate, context);
             assertNotNull(subscription);
 
             assertEquals(subscription.getFieldValue("nonExistent"), null);
@@ -135,7 +135,7 @@ public class TestUserCustomFieldsSql extends TestApiBase {
             testListener.pushExpectedEvent(NextEvent.PHASE);
             testListener.pushExpectedEvent(NextEvent.CREATE);
             SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
-                    getProductSpecifier(productName, planSetName, term, null), requestedDate);
+                    getProductSpecifier(productName, planSetName, term, null), requestedDate, context);
             assertNotNull(subscription);
 
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
index 08f947e..6e28da8 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
@@ -119,9 +119,8 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
         return null;
     }
 
-
     @Override
-    public SubscriptionBundle createSubscriptionBundle(final SubscriptionBundleData bundle) {
+    public SubscriptionBundle createSubscriptionBundle(final SubscriptionBundleData bundle, final CallContext context) {
         bundles.add(bundle);
         return getSubscriptionBundleFromId(bundle.getId());
     }
@@ -154,7 +153,8 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
 
 
     @Override
-    public void createSubscription(final SubscriptionData subscription, final List<EntitlementEvent> initialEvents) {
+    public void createSubscription(final SubscriptionData subscription, final List<EntitlementEvent> initialEvents,
+                                   final CallContext context) {
 
         synchronized(events) {
             events.addAll(initialEvents);
@@ -173,7 +173,7 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
 
     @Override
     public void recreateSubscription(final UUID subscriptionId,
-            final List<EntitlementEvent> recreateEvents) {
+            final List<EntitlementEvent> recreateEvents, final CallContext context) {
 
         synchronized(events) {
             events.addAll(recreateEvents);
@@ -241,7 +241,8 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public void createNextPhaseEvent(final UUID subscriptionId, final EntitlementEvent nextPhase) {
+    public void createNextPhaseEvent(final UUID subscriptionId, final EntitlementEvent nextPhase,
+                                     final CallContext context) {
         cancelNextPhaseEvent(subscriptionId);
         insertEvent(nextPhase);
     }
@@ -253,7 +254,7 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public void updateSubscription(final SubscriptionData subscription) {
+    public void updateSubscription(final SubscriptionData subscription, final CallContext context) {
 
         boolean found = false;
         Iterator<Subscription> it = subscriptions.iterator();
@@ -271,7 +272,8 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public void cancelSubscription(final UUID subscriptionId, final EntitlementEvent cancelEvent) {
+    public void cancelSubscription(final UUID subscriptionId, final EntitlementEvent cancelEvent,
+                                   final CallContext context) {
         synchronized (cancelEvent) {
             cancelNextPhaseEvent(subscriptionId);
             insertEvent(cancelEvent);
@@ -279,7 +281,8 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public void changePlan(final UUID subscriptionId, final List<EntitlementEvent> changeEvents) {
+    public void changePlan(final UUID subscriptionId, final List<EntitlementEvent> changeEvents,
+                           final CallContext context) {
         synchronized(events) {
             cancelNextChangeEvent(subscriptionId);
             cancelNextPhaseEvent(subscriptionId);
@@ -355,7 +358,8 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public void uncancelSubscription(final UUID subscriptionId, final List<EntitlementEvent> uncancelEvents) {
+    public void uncancelSubscription(final UUID subscriptionId, final List<EntitlementEvent> uncancelEvents,
+                                     final CallContext context) {
 
         synchronized (events) {
             boolean foundCancel = false;
@@ -382,7 +386,7 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
 
 
     @Override
-    public void migrate(final UUID accountId, final AccountMigrationData accountData) {
+    public void migrate(final UUID accountId, final AccountMigrationData accountData, final CallContext context) {
         synchronized(events) {
 
             for (final BundleMigrationData curBundle : accountData.getData()) {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index a37f5d6..cf46d15 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -171,7 +171,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     FixedPriceInvoiceItemSqlDao fixedPriceInvoiceItemDao = invoiceDao.become(FixedPriceInvoiceItemSqlDao.class);
                     fixedPriceInvoiceItemDao.batchCreateFromTransaction(fixedPriceInvoiceItems, context);
 
-                    setChargedThroughDates(invoiceSqlDao, fixedPriceInvoiceItems, recurringInvoiceItems);
+                    setChargedThroughDates(invoiceSqlDao, fixedPriceInvoiceItems, recurringInvoiceItems, context);
 
                     // STEPH Why do we need that? Are the payments not always null at this point?
                     List<InvoicePayment> invoicePayments = invoice.getPayments();
@@ -377,7 +377,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
     }
     
     private void setChargedThroughDates(final InvoiceSqlDao dao, final Collection<InvoiceItem> fixedPriceItems,
-                                        final Collection<InvoiceItem> recurringItems) {
+                                        final Collection<InvoiceItem> recurringItems, CallContext context) {
         Map<UUID, DateTime> chargeThroughDates = new HashMap<UUID, DateTime>();
         addInvoiceItemsToChargeThroughDates(chargeThroughDates, fixedPriceItems);
         addInvoiceItemsToChargeThroughDates(chargeThroughDates, recurringItems);
@@ -385,7 +385,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
         for (UUID subscriptionId : chargeThroughDates.keySet()) {
             DateTime chargeThroughDate = chargeThroughDates.get(subscriptionId);
             log.info("Setting CTD for subscription {} to {}", subscriptionId.toString(), chargeThroughDate.toString());
-            entitlementBillingApi.setChargedThroughDateFromTransaction(dao, subscriptionId, chargeThroughDate);
+            entitlementBillingApi.setChargedThroughDateFromTransaction(dao, subscriptionId, chargeThroughDate, context);
         }
     }