killbill-aplcache

Completed merge of integration changes and got tests passing

4/16/2012 3:43:28 PM

Changes

account/pom.xml 2(+1 -1)

api/pom.xml 2(+1 -1)

beatrix/pom.xml 2(+1 -1)

catalog/pom.xml 2(+1 -1)

invoice/pom.xml 10(+9 -1)

payment/pom.xml 2(+1 -1)

pom.xml 5(+2 -3)

README.md 2(+2 -0)

util/pom.xml 5(+2 -3)

Details

account/pom.xml 2(+1 -1)

diff --git a/account/pom.xml b/account/pom.xml
index c48b8b2..de028b7 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-account</artifactId>
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
index cab3e42..eb49bf5 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
@@ -114,11 +114,6 @@ public class DefaultAccountUserApi implements com.ning.billing.account.api.Accou
      }
 
 	@Override
-	public void deleteAccountByKey(final String externalKey, final CallContext context) throws AccountApiException {
-		dao.deleteByKey(externalKey, context);
-	}
-
-	@Override
 	public Account migrateAccount(final MigrationAccountData data, final List<CustomField> fields,
                                   final List<Tag> tags, final CallContext context)
             throws AccountApiException {
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
index d25a3ea..4be1058 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
@@ -32,6 +32,4 @@ public interface AccountDao extends UpdatableEntityDao<Account> {
      * @throws AccountApiException when externalKey is null
      */
     public UUID getIdFromKey(String externalKey) throws AccountApiException;
-
-	public void deleteByKey(String externalKey, CallContext context) throws AccountApiException;
 }
\ No newline at end of file
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
index 2c400d5..8c09af4 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
@@ -22,7 +22,7 @@ import java.util.UUID;
 
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallContextBinder;
-import com.ning.billing.util.entity.MapperBase;
+import com.ning.billing.util.dao.MapperBase;
 import com.ning.billing.util.entity.UpdatableEntityDao;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
@@ -58,9 +58,6 @@ public interface AccountSqlDao extends UpdatableEntityDao<Account>, Transactiona
     @SqlUpdate
     public void update(@AccountBinder Account account, @CallContextBinder final CallContext context);
 
-    @SqlUpdate
-    public void deleteByKey(@Bind("externalKey") final String key);
-
     public static class AccountMapper extends MapperBase implements ResultSetMapper<Account> {
         @Override
         public Account map(int index, ResultSet result, StatementContext context) throws SQLException {
diff --git a/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
index ebb0a63..2d06666 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
@@ -130,7 +130,7 @@ public class AuditedAccountDao implements AccountDao {
 
                     AuditSqlDao auditDao = accountSqlDao.become(AuditSqlDao.class);
                     auditDao.insertAuditFromTransaction("account_history", historyId.toString(),
-                                                         ChangeType.INSERT.toString(), context);
+                                                         ChangeType.INSERT, context);
 
                     saveTagsFromWithinTransaction(account, transactionalDao, context);
                     saveCustomFieldsFromWithinTransaction(account, transactionalDao, context);
@@ -175,7 +175,7 @@ public class AuditedAccountDao implements AccountDao {
 
                     AuditSqlDao auditDao = accountSqlDao.become(AuditSqlDao.class);
                     auditDao.insertAuditFromTransaction("account_history" ,historyId.toString(),
-                                                        ChangeType.INSERT.toString(), context);
+                                                        ChangeType.INSERT, context);
 
                     saveTagsFromWithinTransaction(account, accountSqlDao, context);
                     saveCustomFieldsFromWithinTransaction(account, accountSqlDao, context);
@@ -197,36 +197,6 @@ public class AuditedAccountDao implements AccountDao {
     }
 
     @Override
-	public void deleteByKey(final String externalKey, final CallContext context) throws AccountApiException {
-    	try {
-            accountSqlDao.inTransaction(new Transaction<Void, AccountSqlDao>() {
-                @Override
-                public Void inTransaction(final AccountSqlDao accountSqlDao, final TransactionStatus status) throws AccountApiException, Bus.EventBusException {
-                    Account account = accountSqlDao.getAccountByKey(externalKey);
-                    accountSqlDao.deleteByKey(externalKey);
-
-                    // TODO: ensure tags and fields aren't orphaned
-                    UUID historyId = UUID.randomUUID();
-                    AccountHistorySqlDao historyDao = accountSqlDao.become(AccountHistorySqlDao.class);
-                    historyDao.insertAccountHistoryFromTransaction(account, historyId.toString(), ChangeType.UPDATE.toString(), context);
-
-                    AuditSqlDao auditDao = accountSqlDao.become(AuditSqlDao.class);
-                    auditDao.insertAuditFromTransaction("account_history", historyId.toString(),
-                            ChangeType.INSERT.toString(), context);
-
-                    return null;
-                }
-            });
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof AccountApiException) {
-                throw (AccountApiException) re.getCause();
-            } else {
-                throw re;
-            }
-        }
-	}
-
-    @Override
     public void test() {
         accountSqlDao.test();
     }
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
index 2838ef8..eda3949 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
@@ -46,12 +46,6 @@ update() ::= <<
     WHERE id = :id;
 >>
 
-deleteByKey() ::= <<
-    DELETE FROM accounts
-    WHERE external_key = :externalKey;
->>
-
-
 getAccountByKey() ::= <<
     select <accountFields()>
     from accounts
diff --git a/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java b/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java
index 265b933..d2fea9e 100644
--- a/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java
+++ b/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java
@@ -107,17 +107,6 @@ public class MockAccountUserApi implements AccountUserApi {
     }
 
 	@Override
-	public void deleteAccountByKey(final String externalKey, final CallContext context)
-			throws AccountApiException {
-		for (Account account : accounts) {
-            if (externalKey.equals(account.getExternalKey())) {
-                accounts.remove(account);
-            }
-        }	
-		
-	}
-
-	@Override
 	public Account migrateAccount(final MigrationAccountData data,
 			final List<CustomField> fields, final List<Tag> tags, final CallContext context)
 			throws AccountApiException {
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/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
index 7cfc3f1..645124b 100644
--- a/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
@@ -97,13 +97,4 @@ public class MockAccountDao implements AccountDao {
             }
         }
     }
-
-	@Override
-	public void deleteByKey(String externalKey, CallContext context) throws AccountApiException {
-		for (Account account : accounts.values()) {
-            if (externalKey.equals(account.getExternalKey())) {
-                accounts.remove(account.getId().toString());
-            }
-        }		
-	}
 }
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
index 10d904f..7feb492 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
@@ -18,7 +18,6 @@ package com.ning.billing.account.dao;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
@@ -26,6 +25,7 @@ import java.util.List;
 import java.util.UUID;
 
 import com.ning.billing.util.entity.EntityPersistenceException;
+import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.testng.annotations.Test;
 
@@ -33,39 +33,37 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.DefaultAccount;
-import com.ning.billing.account.api.user.AccountBuilder;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.util.tag.DefaultTagDefinition;
 import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.TagDefinition;
 import com.ning.billing.util.tag.dao.TagDefinitionSqlDao;
 
-@Test(groups = {"account-dao"})
+@Test(groups = {"slow", "account-dao"})
 public class TestSimpleAccountDao extends AccountDaoTestBase {
-    private AccountBuilder createTestAccountBuilder() {
+    private Account createTestAccount(int billCycleDay) {
+        return createTestAccount(billCycleDay, "123-456-7890");
+    }
+
+    private Account createTestAccount(int billCycleDay, String phone) {
         String thisKey = "test" + UUID.randomUUID().toString();
         String lastName = UUID.randomUUID().toString();
         String thisEmail = "me@me.com" + " " + UUID.randomUUID();
         String firstName = "Bob";
         String name = firstName + " " + lastName;
-        String phone = "123-456-7890";
         String locale = "EN-US";
         DateTimeZone timeZone = DateTimeZone.forID("America/Los_Angeles");
-
         int firstNameLength = firstName.length();
-        return new AccountBuilder().externalKey(thisKey)
-                                   .name(name)
-                                   .phone(phone)
-                                   .firstNameLength(firstNameLength)
-                                   .email(thisEmail)
-                                   .currency(Currency.USD)
-                                   .locale(locale)
-                                   .timeZone(timeZone);
+
+        return new DefaultAccount(UUID.randomUUID(), thisKey, thisEmail, name, firstNameLength, Currency.USD,
+                billCycleDay, null, timeZone, locale,
+                null, null, null, null, null, null, null, // add null address fields
+                phone, "test", DateTime.now(), "test", DateTime.now());
     }
 
     @Test
     public void testBasic() throws EntityPersistenceException {
-        Account a = createTestAccountBuilder().build();
+        Account a = createTestAccount(5);
         accountDao.create(a, context);
         String key = a.getExternalKey();
 
@@ -85,7 +83,7 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
     // simple test to ensure long phone numbers can be stored
     @Test
     public void testLongPhoneNumber() throws EntityPersistenceException {
-        Account account = createTestAccountBuilder().phone("123456789012345678901234").build();
+        Account account = createTestAccount(1, "123456789012345678901234");
         accountDao.create(account, context);
 
         Account saved = accountDao.getAccountByKey(account.getExternalKey());
@@ -95,13 +93,13 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
     // simple test to ensure excessively long phone numbers cannot be stored
     @Test(expectedExceptions = {EntityPersistenceException.class})
     public void testOverlyLongPhoneNumber() throws EntityPersistenceException {
-        Account account = createTestAccountBuilder().phone("12345678901234567890123456").build();
+        Account account = createTestAccount(1, "12345678901234567890123456");
         accountDao.create(account, context);
     }
 
     @Test
     public void testGetById() throws EntityPersistenceException {
-        Account account = createTestAccountBuilder().build();
+        Account account = createTestAccount(1);
         UUID id = account.getId();
         String key = account.getExternalKey();
         String name = account.getName();
@@ -120,7 +118,7 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
 
     @Test
     public void testCustomFields() throws EntityPersistenceException {
-        Account account = createTestAccountBuilder().build();
+        Account account = createTestAccount(1);
         String fieldName = "testField1";
         String fieldValue = "testField1_value";
         account.setFieldValue(fieldName, fieldValue);
@@ -135,7 +133,7 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
 
     @Test
     public void testTags() throws EntityPersistenceException {
-        Account account = createTestAccountBuilder().build();
+        Account account = createTestAccount(1);
         TagDefinition definition = new DefaultTagDefinition("Test Tag", "For testing only");
         TagDefinitionSqlDao tagDescriptionDao = dbi.onDemand(TagDefinitionSqlDao.class);
         tagDescriptionDao.create(definition, context);
@@ -153,7 +151,7 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
 
     @Test
     public void testGetIdFromKey() throws EntityPersistenceException {
-        Account account = createTestAccountBuilder().build();
+        Account account = createTestAccount(1);
         accountDao.create(account, context);
 
         try {
@@ -172,7 +170,7 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
 
     @Test
     public void testUpdate() throws Exception {
-        final Account account = createTestAccountBuilder().build();
+        final Account account = createTestAccount(1);
         accountDao.create(account, context);
 
         AccountData accountData = new AccountData() {
@@ -373,22 +371,4 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
                                                     null, null, null, null);
         accountDao.update(updatedAccount, context);
     }
-
-    @Test
-    public void testDelete() throws AccountApiException, EntityPersistenceException {
-
-        Account a = createTestAccountBuilder().build();
-        accountDao.create(a, context);
-        String key = a.getExternalKey();
-
-        Account r = accountDao.getAccountByKey(key);
-        assertNotNull(r);
-        assertEquals(r.getExternalKey(), a.getExternalKey());
-        
-        accountDao.deleteByKey(key, context);
-        
-        Account s = accountDao.getAccountByKey(key);
-        assertNull(s);
-    }
-
 }
diff --git a/analytics/pom.xml b/analytics/pom.xml
index e7e0e94..cc9370a 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-analytics</artifactId>
@@ -68,6 +68,11 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-catalog</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-entitlement</artifactId>
diff --git a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
index 4d26ac0..1d1b1ad 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
@@ -21,8 +21,6 @@ import org.skife.jdbi.v2.IDBI;
 import com.ning.billing.account.glue.AccountModule;
 import com.ning.billing.analytics.setup.AnalyticsModule;
 import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.api.overdue.MockOverdueChecker;
-import com.ning.billing.entitlement.api.overdue.OverdueChecker;
 import com.ning.billing.entitlement.glue.EntitlementModule;
 import com.ning.billing.invoice.glue.InvoiceModule;
 import com.ning.billing.mock.overdue.MockOverdueAccessModule;
@@ -49,16 +47,9 @@ public class AnalyticsTestModule extends AnalyticsModule
         install(new TagStoreModule());
         install(new AccountModule());
         install(new BusModule());
-        install(new EntitlementModule() {
-
-            @Override
-            protected void installOverdueChecker() {
-                bind(OverdueChecker.class).to(MockOverdueChecker.class).asEagerSingleton();
-            }
-            
-        });
-        install(new InvoiceModule());
+        install(new EntitlementModule());
         install(new MockOverdueAccessModule());
+        install(new InvoiceModule());
         install(new PaymentModule());
         install(new TagStoreModule());
         install(new NotificationQueueModule());
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 a3040fd..ebfbd9a 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
@@ -142,16 +142,15 @@ public class TestAnalyticsService {
     private InvoiceCreationNotification invoiceCreationNotification;
     private PaymentInfo paymentInfoNotification;
 
-    @BeforeMethod
+    @BeforeMethod(groups = "slow")
     public void cleanup() throws Exception
     {
         helper.cleanupTable("bst");
         helper.cleanupTable("bac");
-
     }
 
 
-    @BeforeClass(alwaysRun = true)
+    @BeforeClass(groups = "slow")
     public void startMysql() throws IOException, ClassNotFoundException, SQLException, EntitlementUserApiException {
         // Killbill generic setup
         setupBusAndMySQL();
@@ -199,7 +198,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);
@@ -272,7 +271,7 @@ public class TestAnalyticsService {
         Assert.assertEquals(paymentDao.getPaymentInfo(Arrays.asList(invoice.getId().toString())).size(), 1);
     }
 
-    @AfterClass(alwaysRun = true)
+    @AfterClass(groups = "slow")
     public void stopMysql() {
         helper.stopMysql();
     }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
index 85ec378..315ce7f 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
@@ -77,11 +77,6 @@ public class MockIAccountUserApi implements AccountUserApi
     }
 
 	@Override
-	public void deleteAccountByKey(String externalKey, final CallContext context) {
-		throw new UnsupportedOperationException();
-	}
-
-	@Override
 	public Account migrateAccount(MigrationAccountData data,
 			List<CustomField> fields, List<Tag> tags, final CallContext context)
 			throws AccountApiException {
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 cce9984..0e4c2a3 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -55,13 +55,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();
     }
@@ -114,7 +114,7 @@ public class MockSubscription implements Subscription
 
 
     @Override
-    public void uncancel() throws EntitlementUserApiException
+    public void uncancel(CallContext context) throws EntitlementUserApiException
     {
         throw new UnsupportedOperationException();
     }
@@ -156,7 +156,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 ca782b9..13d6e05 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -57,7 +57,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);
     }
 

api/pom.xml 2(+1 -1)

diff --git a/api/pom.xml b/api/pom.xml
index ac7f6c9..a9cec84 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java b/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
index 2ab04dc..98d6272 100644
--- a/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
+++ b/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
@@ -51,6 +51,4 @@ public interface AccountUserApi {
     public List<Account> getAccounts();
 
     public UUID getIdFromKey(String externalKey) throws AccountApiException;
-
-	public void deleteAccountByKey(String externalKey, CallContext context) throws AccountApiException;
 }
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 04ca9bb..90572b3 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 826860b..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;
@@ -44,10 +45,10 @@ public interface EntitlementMigrationApi {
 
     /**
      *
-     * Each case is either a PHASE or a different PlanSpecifer
+     * Each case is either a PHASE or a different PlanSpecifier
      */
     public interface EntitlementSubscriptionMigrationCase {
-        public PlanPhaseSpecifier getPlanPhaseSpecifer();
+        public PlanPhaseSpecifier getPlanPhaseSpecifier();
         public DateTime getEffectiveDate();
         public DateTime getCancelledDate();
     }
@@ -58,17 +59,9 @@ public interface EntitlementMigrationApi {
      * The semantics is 'all or nothing' (atomic operation)
      *
      * @param toBeMigrated all the bundles and associated subscription that should be migrated for the account
+     * @throws EntitlementMigrationApiException an entitlement api exception
      *
      */
-    public void migrate(EntitlementAccountMigration toBeMigrated)
+    public void migrate(EntitlementAccountMigration toBeMigrated, CallContext context)
         throws EntitlementMigrationApiException;
-
-    /**
-     * Remove all the data pertaining to that acount
-     *
-     * @param accountKey
-     */
-    public void undoMigration(UUID accountKey)
-        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 162b92e..66091e2 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;
 
@@ -38,10 +40,10 @@ public interface EntitlementUserApi {
     
     public Subscription getBaseSubscription(UUID bundleId);
 
-    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 7304f5b..ecac7aa 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
@@ -26,21 +26,22 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.entity.ExtendedEntity;
 
 
 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 {

beatrix/pom.xml 2(+1 -1)

diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 28f478f..64726c8 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-beatrix</artifactId>
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
index 0e8063d..98fe90b 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
@@ -92,9 +92,9 @@ public class MockModule extends AbstractModule {
         install(new AccountModule());
         install(new CatalogModule());
         install(new EntitlementModule());
+        install(new MockOverdueAccessModule());
         install(new InvoiceModule());
         install(new PaymentMockModule());
-        install(new MockOverdueAccessModule());
     }
 
     private static final class PaymentMockModule extends PaymentModule {
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 44b76f0..f081c29 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
@@ -19,6 +19,7 @@ package com.ning.billing.beatrix.integration;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import java.io.IOException;
 import java.math.BigDecimal;
@@ -33,6 +34,7 @@ import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.InvoicingConfiguration;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallOrigin;
 import com.ning.billing.util.callcontext.UserType;
@@ -82,8 +84,8 @@ import com.ning.billing.util.bus.BusService;
 @Test(groups = "slow")
 @Guice(modules = {MockModule.class})
 public class TestIntegration {
-    private static final int NUMBER_OF_DECIMALS = 4;
-    private static final int ROUNDING_METHOD = BigDecimal.ROUND_HALF_EVEN;
+    private static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
+    private static final int ROUNDING_METHOD = InvoicingConfiguration.getRoundingMode();
 
     private static final BigDecimal ONE = new BigDecimal("1.0000").setScale(NUMBER_OF_DECIMALS);
     private static final BigDecimal TWENTY_NINE = new BigDecimal("29.0000").setScale(NUMBER_OF_DECIMALS);
@@ -244,7 +246,9 @@ public class TestIntegration {
             }
         }
 
-        assertTrue(wasFound);
+        if (!wasFound) {
+            fail();
+        }
 
         DateTime ctd = subscription.getChargedThroughDate();
         assertNotNull(ctd);
@@ -314,7 +318,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 +330,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 +353,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 +369,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 +384,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 +396,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 +419,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 +494,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 +542,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 +573,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 +582,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 +592,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 +615,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);

catalog/pom.xml 2(+1 -1)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 60984c5..6f6a8c5 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-catalog</artifactId>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
index fee8c37..e3b24b5 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
@@ -72,7 +72,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 	@XmlElement(name="rules", required=true)
 	private PlanRules planRules;
 
-    @XmlElement(name="overdueRules", required=true)
+    @XmlElement(name="overdueRules", required=false)
     private OverdueRules overdueRules;
 
 	@XmlElementWrapper(name="plans", required=true)
@@ -247,7 +247,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 		validate(catalog,errors, plans);
 		priceLists.validate(catalog,errors);
 		planRules.validate(catalog, errors);
-		overdueRules.validate(catalog,errors);
+		if(overdueRules != null) {overdueRules.validate(catalog,errors); }
 		return errors;
 	}
 
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index cccf568..426d9f8 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
index b354348..2965b8f 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
@@ -48,11 +48,11 @@ public class MigrationPlanAligner {
 
         try {
             TimedMigration [] events = null;
-            Plan plan0 = catalogService.getFullCatalog().findPlan(input[0].getPlanPhaseSpecifer().getProductName(),
-                    input[0].getPlanPhaseSpecifer().getBillingPeriod(), input[0].getPlanPhaseSpecifer().getPriceListName(), now);
+            Plan plan0 = catalogService.getFullCatalog().findPlan(input[0].getPlanPhaseSpecifier().getProductName(),
+                    input[0].getPlanPhaseSpecifier().getBillingPeriod(), input[0].getPlanPhaseSpecifier().getPriceListName(), now);
 
-            Plan plan1 = (input.length > 1) ? catalogService.getFullCatalog().findPlan(input[1].getPlanPhaseSpecifer().getProductName(),
-                    input[1].getPlanPhaseSpecifer().getBillingPeriod(), input[1].getPlanPhaseSpecifer().getPriceListName(), now) :
+            Plan plan1 = (input.length > 1) ? catalogService.getFullCatalog().findPlan(input[1].getPlanPhaseSpecifier().getProductName(),
+                    input[1].getPlanPhaseSpecifier().getBillingPeriod(), input[1].getPlanPhaseSpecifier().getPriceListName(), now) :
                         null;
 
             DateTime migrationStartDate = now;
@@ -60,21 +60,21 @@ public class MigrationPlanAligner {
             if (isRegularMigratedSubscription(input)) {
 
                 events = getEventsOnRegularMigration(plan0,
-                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
-                        input[0].getPlanPhaseSpecifer().getPriceListName(),
+                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifier().getPhaseType()),
+                        input[0].getPlanPhaseSpecifier().getPriceListName(),
                         now);
 
             } else if (isRegularFutureCancelledMigratedSubscription(input)) {
 
                 events = getEventsOnFuturePlanCancelMigration(plan0,
-                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
-                        input[0].getPlanPhaseSpecifer().getPriceListName(),
+                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifier().getPhaseType()),
+                        input[0].getPlanPhaseSpecifier().getPriceListName(),
                         now,
                         input[0].getCancelledDate());
 
             } else if (isPhaseChangeMigratedSubscription(input)) {
 
-                PhaseType curPhaseType = input[0].getPlanPhaseSpecifer().getPhaseType();
+                PhaseType curPhaseType = input[0].getPlanPhaseSpecifier().getPhaseType();
                 Duration curPhaseDuration = null;
                 for (PlanPhase cur : plan0.getAllPhases()) {
                     if (cur.getPhaseType() == curPhaseType) {
@@ -89,18 +89,18 @@ public class MigrationPlanAligner {
 
                 migrationStartDate = DefaultClock.removeDuration(input[1].getEffectiveDate(), curPhaseDuration);
                 events = getEventsOnFuturePhaseChangeMigration(plan0,
-                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
-                        input[0].getPlanPhaseSpecifer().getPriceListName(),
+                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifier().getPhaseType()),
+                        input[0].getPlanPhaseSpecifier().getPriceListName(),
                         migrationStartDate,
                         input[1].getEffectiveDate());
 
             } else if (isPlanChangeMigratedSubscription(input)) {
 
                 events = getEventsOnFuturePlanChangeMigration(plan0,
-                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
+                        getPlanPhase(plan0, input[0].getPlanPhaseSpecifier().getPhaseType()),
                         plan1,
-                        getPlanPhase(plan1, input[1].getPlanPhaseSpecifer().getPhaseType()),
-                        input[0].getPlanPhaseSpecifer().getPriceListName(),
+                        getPlanPhase(plan1, input[1].getPlanPhaseSpecifier().getPhaseType()),
+                        input[0].getPlanPhaseSpecifier().getPriceListName(),
                         now,
                         input[1].getEffectiveDate());
 
@@ -181,15 +181,15 @@ public class MigrationPlanAligner {
         if (input.length != 2) {
             return false;
         }
-        return (isSamePlan(input[0].getPlanPhaseSpecifer(), input[1].getPlanPhaseSpecifer()) &&
-                !isSamePhase(input[0].getPlanPhaseSpecifer(), input[1].getPlanPhaseSpecifer()));
+        return (isSamePlan(input[0].getPlanPhaseSpecifier(), input[1].getPlanPhaseSpecifier()) &&
+                !isSamePhase(input[0].getPlanPhaseSpecifier(), input[1].getPlanPhaseSpecifier()));
     }
 
     private boolean isPlanChangeMigratedSubscription(EntitlementSubscriptionMigrationCase [] input) {
         if (input.length != 2) {
             return false;
         }
-        return ! isSamePlan(input[0].getPlanPhaseSpecifer(), input[1].getPlanPhaseSpecifer());
+        return ! isSamePlan(input[0].getPlanPhaseSpecifier(), input[1].getPlanPhaseSpecifier());
     }
 
     private boolean isSamePlan(PlanPhaseSpecifier plan0, PlanPhaseSpecifier plan1) {
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 1fd595c..7af5e5c 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
@@ -22,6 +22,15 @@ import java.util.SortedSet;
 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;
+import com.ning.billing.util.callcontext.CallContextFactory;
+
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.slf4j.Logger;
@@ -35,6 +44,7 @@ import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.api.user.SubscriptionTransition;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
@@ -51,11 +61,15 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
     private final EntitlementDao entitlementDao;
     private final AccountUserApi accountApi;
     private final BillCycleDayCalculator bcdCalculator;
+    private final SubscriptionFactory subscriptionFactory;
+  
+    private static final String SUBSCRIPTION_TABLE_NAME = "subscriptions";
 
     @Inject
-    public DefaultEntitlementBillingApi(final CallContextFactory factory, final EntitlementDao dao, final AccountUserApi accountApi, final BillCycleDayCalculator bcdCalculator) {
+    public DefaultEntitlementBillingApi(final CallContextFactory factory, final SubscriptionFactory subscriptionFactory, final EntitlementDao dao, final AccountUserApi accountApi, final BillCycleDayCalculator bcdCalculator) {
         super();
         this.factory = factory;
+        this.subscriptionFactory = subscriptionFactory;
         this.entitlementDao = dao;
         this.accountApi = accountApi;
         this.bcdCalculator = bcdCalculator;
@@ -70,7 +84,8 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
         List<SubscriptionBundle> bundles = entitlementDao.getSubscriptionBundleForAccount(accountId);
         SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();
         for (final SubscriptionBundle bundle: bundles) {
-        	List<Subscription> subscriptions = entitlementDao.getSubscriptions(bundle.getId());
+        	List<Subscription> subscriptions = entitlementDao.getSubscriptions(subscriptionFactory, bundle.getId());
+
         	for (final Subscription subscription: subscriptions) {
         		for (final SubscriptionTransition transition : ((SubscriptionData) subscription).getBillingTransitions()) {
         			try {
@@ -103,18 +118,19 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
     }
 
     @Override
-    public void setChargedThroughDate(final UUID subscriptionId, final DateTime ctd) {
-        SubscriptionData subscription = (SubscriptionData) entitlementDao.getSubscriptionFromId(subscriptionId);
+    public void setChargedThroughDate(final UUID subscriptionId, final DateTime ctd, CallContext context) {
+        SubscriptionData subscription = (SubscriptionData) entitlementDao.getSubscriptionFromId(subscriptionFactory, 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());
 
@@ -126,7 +142,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 812378b..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,15 +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);
-    }
-
-    @Override
-    public void undoMigration(UUID accountId) {
-        dao.undoMigration(accountId);
+        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 a664327..7fc99a2 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
@@ -37,6 +37,7 @@ import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBui
 import com.ning.billing.entitlement.engine.addon.AddonUtils;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.DefaultClock;
 
@@ -47,10 +48,11 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
     private final SubscriptionApiService apiService;
     private final OverdueChecker overdueChecker;
     private final AddonUtils addonUtils;
+    private final SubscriptionFactory subscriptionFactory;
 
     @Inject
     public DefaultEntitlementUserApi(Clock clock, EntitlementDao dao, CatalogService catalogService,
-            SubscriptionApiService apiService, AddonUtils addonUtils, OverdueChecker overdueChecker) {
+            SubscriptionApiService apiService, final SubscriptionFactory subscriptionFactory, AddonUtils addonUtils, OverdueChecker overdueChecker) {
         super();
         this.clock = clock;
         this.apiService = apiService;
@@ -58,6 +60,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
         this.catalogService = catalogService;
         this.addonUtils = addonUtils;
         this.overdueChecker = overdueChecker;
+        this.subscriptionFactory = subscriptionFactory;
     }
 
     @Override
@@ -67,7 +70,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
 
     @Override
     public Subscription getSubscriptionFromId(UUID id) {
-        return dao.getSubscriptionFromId(id);
+        return dao.getSubscriptionFromId(subscriptionFactory, id);
     }
 
     @Override
@@ -82,28 +85,29 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
 
     @Override
     public List<Subscription> getSubscriptionsForKey(String bundleKey) {
-        return dao.getSubscriptionsForKey(bundleKey);
+        return dao.getSubscriptionsForKey(subscriptionFactory, bundleKey);
     }
 
     @Override
     public List<Subscription> getSubscriptionsForBundle(UUID bundleId) {
-        return dao.getSubscriptions(bundleId);
+        return dao.getSubscriptions(subscriptionFactory, bundleId);
     }
 
     @Override
     public Subscription getBaseSubscription(UUID bundleId) {
-        return dao.getBaseSubscription(bundleId);
+        return dao.getBaseSubscription(subscriptionFactory, bundleId);
     }
     
-    @Override
-    public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleName)
-            throws EntitlementUserApiException {
+
+    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();
@@ -128,7 +132,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
             }
 
             DateTime bundleStartDate = null;
-            SubscriptionData baseSubscription = (SubscriptionData) dao.getBaseSubscription(bundleId);
+            SubscriptionData baseSubscription = (SubscriptionData) dao.getBaseSubscription(subscriptionFactory, bundleId);
             switch(plan.getProduct().getCategory()) {
             case BASE:
                 if (baseSubscription != null) {
@@ -136,7 +140,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;
                     }
                 }
@@ -162,12 +166,12 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
             }
 
             SubscriptionData subscription = apiService.createPlan(new SubscriptionBuilder()
-            .setId(UUID.randomUUID())
-            .setBundleId(bundleId)
-            .setCategory(plan.getProduct().getCategory())
-            .setBundleStartDate(bundleStartDate)
-            .setStartDate(effectiveDate),
-            plan, spec.getPhaseType(), realPriceList, requestedDate, effectiveDate, now);
+                 .setId(UUID.randomUUID())
+                .setBundleId(bundleId)
+                .setCategory(plan.getProduct().getCategory())
+                .setBundleStartDate(bundleStartDate)
+                .setStartDate(effectiveDate),
+            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 4a3dcfb..2a69428 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
@@ -75,7 +75,8 @@ 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);
@@ -83,11 +84,11 @@ public class SubscriptionApiService {
         overdueChecker.checkBlocked(subscription);
 
         
-        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 {
         
         overdueChecker.checkBlocked(subscription);
@@ -112,15 +113,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 {
 
         overdueChecker.checkBlocked(subscription);
@@ -150,9 +151,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) {
@@ -160,10 +161,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 {
@@ -195,7 +193,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);
@@ -203,7 +201,7 @@ public class SubscriptionApiService {
     }
 
 
-    public void uncancel(SubscriptionData subscription)
+    public void uncancel(SubscriptionData subscription, CallContext context)
         throws EntitlementUserApiException {
 
         if (!subscription.isSubscriptionFutureCancelled()) {
@@ -229,13 +227,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 {
         
         overdueChecker.checkBlocked(subscription);
@@ -304,7 +301,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 e8e1bb0..a5b76ab 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
@@ -106,7 +106,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);
     }
@@ -166,25 +166,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..32ffb90 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;
@@ -43,6 +47,7 @@ import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.engine.addon.AddonUtils;
@@ -84,7 +89,8 @@ public class Engine implements EventListener, EntitlementService {
 
     private final EntitlementConfig config;
     private final NotificationQueueService notificationQueueService;
-
+    private final CallContextFactory factory;
+    private final SubscriptionFactory subscriptionFactory;
     private NotificationQueue subscriptionEventQueue;
 
     @Inject
@@ -92,7 +98,9 @@ public class Engine implements EventListener, EntitlementService {
             EntitlementConfig config, DefaultEntitlementUserApi userApi,
             DefaultEntitlementBillingApi billingApi,
             DefaultEntitlementMigrationApi migrationApi, AddonUtils addonUtils, Bus eventBus,
-            NotificationQueueService notificationQueueService) {
+            NotificationQueueService notificationQueueService,
+            SubscriptionFactory subscriptionFactory,
+            CallContextFactory factory) {
         super();
         this.clock = clock;
         this.dao = dao;
@@ -104,6 +112,8 @@ public class Engine implements EventListener, EntitlementService {
         this.config = config;
         this.eventBus = eventBus;
         this.notificationQueueService = notificationQueueService;
+        this.subscriptionFactory = subscriptionFactory;
+        this.factory = factory;
     }
 
     @Override
@@ -124,7 +134,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,11 +192,11 @@ public class Engine implements EventListener, EntitlementService {
 
 
     @Override
-    public void processEventReady(EntitlementEvent event) {
+    public void processEventReady(EntitlementEvent event, CallContext context) {
         if (!event.isActive()) {
             return;
         }
-        SubscriptionData subscription = (SubscriptionData) dao.getSubscriptionFromId(event.getSubscriptionId());
+        SubscriptionData subscription = (SubscriptionData) dao.getSubscriptionFromId(subscriptionFactory, event.getSubscriptionId());
         if (subscription == null) {
             log.warn("Failed to retrieve subscription for id %s", event.getSubscriptionId());
             return;
@@ -194,10 +205,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 +218,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,21 +226,21 @@ 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();
 
         Product baseProduct = (baseSubscription.getState() == SubscriptionState.CANCELLED ) ?
                 null : baseSubscription.getCurrentPlan().getProduct();
 
-        List<Subscription> subscriptions = dao.getSubscriptions(baseSubscription.getBundleId());
+        List<Subscription> subscriptions = dao.getSubscriptions(subscriptionFactory, baseSubscription.getBundleId());
 
         Iterator<Subscription> it = subscriptions.iterator();
         while (it.hasNext()) {
@@ -252,7 +263,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/BundleSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
index e6b6d2a..f6f5497 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
@@ -35,21 +35,19 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
-import com.google.inject.Inject;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
-import com.ning.billing.util.entity.BinderBase;
-import com.ning.billing.util.entity.MapperBase;
-import com.ning.billing.util.overdue.OverdueAccessApi;
+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;
 
 @ExternalizedSqlViaStringTemplate3()
 public interface BundleSqlDao extends Transactional<BundleSqlDao>, CloseMe, Transmogrifier {
 
     @SqlUpdate
-    public void insertBundle(@Bind(binder = SubscriptionBundleBinder.class) SubscriptionBundleData bundle);
-
-    @SqlUpdate
-    public void removeBundle(@Bind("id") String id);
+    public void insertBundle(@Bind(binder = SubscriptionBundleBinder.class) SubscriptionBundleData bundle,
+                             @CallContextBinder final CallContext context);
 
     @SqlQuery
     @Mapper(ISubscriptionBundleSqlMapper.class)
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 6ca1c15..d79444a 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
@@ -26,58 +26,57 @@ import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 
 public interface EntitlementDao {
     // Bundle apis
-    public List<SubscriptionBundle> getSubscriptionBundleForAccount(UUID accountId);
+    public List<SubscriptionBundle> getSubscriptionBundleForAccount(final UUID accountId);
 
-    public SubscriptionBundle getSubscriptionBundleFromKey(String bundleKey);
+    public SubscriptionBundle getSubscriptionBundleFromKey(final String bundleKey);
 
-    public SubscriptionBundle getSubscriptionBundleFromId(UUID bundleId);
+    public SubscriptionBundle getSubscriptionBundleFromId(final UUID bundleId);
 
-    public SubscriptionBundle createSubscriptionBundle(SubscriptionBundleData bundle);
+    public SubscriptionBundle createSubscriptionBundle(final SubscriptionBundleData bundle, CallContext context);
 
-    public Subscription getSubscriptionFromId(UUID subscriptionId);
+    public Subscription getSubscriptionFromId(final SubscriptionFactory factory, final UUID subscriptionId);
 
     // Account retrieval
-    public UUID getAccountIdFromSubscriptionId(UUID subscriptionId);
+    public UUID getAccountIdFromSubscriptionId(final UUID subscriptionId);
 
     // Subscription retrieval
-    public Subscription getBaseSubscription(UUID bundleId);
+    public Subscription getBaseSubscription(final SubscriptionFactory factory, final UUID bundleId);
 
-    public List<Subscription> getSubscriptions(UUID bundleId);
+    public List<Subscription> getSubscriptions(final SubscriptionFactory factory, final UUID bundleId);
 
-    public List<Subscription> getSubscriptionsForKey(String bundleKey);
+    public List<Subscription> getSubscriptionsForKey(final SubscriptionFactory factory, final String bundleKey);
 
     // Update
-    public void updateSubscription(SubscriptionData subscription);
+    public void updateSubscription(final SubscriptionData subscription, final CallContext context);
 
     // Event apis
-    public void createNextPhaseEvent(UUID subscriptionId, EntitlementEvent nextPhase);
+    public void createNextPhaseEvent(final UUID subscriptionId, final EntitlementEvent nextPhase, final CallContext context);
 
-    public EntitlementEvent getEventById(UUID eventId);
+    public EntitlementEvent getEventById(final UUID eventId);
 
-    public List<EntitlementEvent> getEventsForSubscription(UUID subscriptionId);
+    public List<EntitlementEvent> getEventsForSubscription(final UUID subscriptionId);
 
-    public List<EntitlementEvent> getPendingEventsForSubscription(UUID subscriptionId);
+    public List<EntitlementEvent> getPendingEventsForSubscription(final UUID subscriptionId);
 
     // Subscription creation, cancellation, changePlan apis
-    public void createSubscription(SubscriptionData subscription, List<EntitlementEvent> initialEvents);
+    public void createSubscription(final SubscriptionData subscription, final List<EntitlementEvent> initialEvents, final CallContext context);
 
-    public void recreateSubscription(UUID subscriptionId, List<EntitlementEvent> recreateEvents);
+    public void recreateSubscription(final UUID subscriptionId, final List<EntitlementEvent> recreateEvents, final CallContext context);
 
-    public void cancelSubscription(UUID subscriptionId, EntitlementEvent cancelEvent);
+    public void cancelSubscription(final UUID subscriptionId, final EntitlementEvent cancelEvent, final CallContext context);
 
-    public void uncancelSubscription(UUID subscriptionId, List<EntitlementEvent> uncancelEvents);
+    public void uncancelSubscription(final UUID subscriptionId, final List<EntitlementEvent> uncancelEvents, final CallContext context);
 
-    public void changePlan(UUID subscriptionId, List<EntitlementEvent> changeEvents);
+    public void changePlan(final UUID subscriptionId, final List<EntitlementEvent> changeEvents, final CallContext context);
 
-    public void migrate(UUID accountId, AccountMigrationData data);
-
-    public void undoMigration(UUID accountId);
+    public void migrate(final UUID accountId, final AccountMigrationData data, final CallContext context);
 
     // Custom Fields
-    public void saveCustomFields(SubscriptionData subscription, CallContext context);
+    public void saveCustomFields(final SubscriptionData subscription, final 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 413cd3e..12d5f15 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 javax.annotation.Nullable;
+
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.IDBI;
 import org.skife.jdbi.v2.Transaction;
@@ -60,6 +62,8 @@ import com.ning.billing.entitlement.events.user.ApiEventCancel;
 import com.ning.billing.entitlement.events.user.ApiEventChange;
 import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
+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.clock.Clock;
 import com.ning.billing.util.customfield.CustomField;
@@ -71,30 +75,36 @@ import com.ning.billing.util.notificationq.NotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService.NoSuchNotificationQueue;
 import com.ning.billing.util.overdue.OverdueAccessApi;
 
-
 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;
     private final BundleSqlDao bundlesDao;
     private final EventSqlDao eventsDao;
-    private final SubscriptionFactory factory;
     private final NotificationQueueService notificationQueueService;
     private final AddonUtils addonUtils;
     private final CustomFieldDao customFieldDao;
     private final OverdueAccessApi overdueApi;
     private final CatalogService catalogService;
 
+    
+    //
+    // We are not injecting SubscriptionFactory since that creates circular dependencies--
+    // Guice would still work, but this is playing with fire.
+    //
+    // Instead that factory passed through API top to bottom for the call where is it needed-- where we returned fully rehydrated Subscriptions
+    //
     @Inject
-    public EntitlementSqlDao(final IDBI dbi, final Clock clock, final SubscriptionFactory factory,
+    public EntitlementSqlDao(final IDBI dbi, final Clock clock,
                              final AddonUtils addonUtils, final NotificationQueueService notificationQueueService,
                              final CustomFieldDao customFieldDao,
                              final OverdueAccessApi overdueApi,
                              final CatalogService catalogService) {
         this.clock = clock;
-        this.factory = factory;
         this.subscriptionsDao = dbi.onDemand(SubscriptionSqlDao.class);
         this.eventsDao = dbi.onDemand(EventSqlDao.class);
         this.bundlesDao = dbi.onDemand(BundleSqlDao.class);
@@ -122,11 +132,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);
+                bundlesDao.insertBundle(bundle, context);
+
+                AuditSqlDao auditSqlDao = bundlesDao.become(AuditSqlDao.class);
+                String bundleId = bundle.getId().toString();
+                auditSqlDao.insertAuditFromTransaction(BUNDLES_TABLE_NAME, bundleId, ChangeType.INSERT, context);
+
                 return bundle;
             }
         });
@@ -156,58 +171,60 @@ public class EntitlementSqlDao implements EntitlementDao {
     }
 
     @Override
-    public Subscription getBaseSubscription(final UUID bundleId) {
-        return getBaseSubscription(bundleId, true);
+    public Subscription getBaseSubscription(final SubscriptionFactory factory, final UUID bundleId) {
+        return getBaseSubscription(factory, bundleId, true);
     }
 
     @Override
-    public Subscription getSubscriptionFromId(final UUID subscriptionId) {
-        return buildSubscription(subscriptionsDao.getSubscriptionFromId(subscriptionId.toString()));
+    public Subscription getSubscriptionFromId(final SubscriptionFactory factory, final UUID subscriptionId) {
+        return buildSubscription(factory, subscriptionsDao.getSubscriptionFromId(subscriptionId.toString()));
     }
 
     @Override
-    public List<Subscription> getSubscriptions(UUID bundleId) {
-        return buildBundleSubscriptions(subscriptionsDao.getSubscriptionsFromBundleId(bundleId.toString()));
+    public List<Subscription> getSubscriptions(final SubscriptionFactory factory, final UUID bundleId) {
+        return buildBundleSubscriptions(factory, subscriptionsDao.getSubscriptionsFromBundleId(bundleId.toString()));
     }
 
     @Override
-    public List<Subscription> getSubscriptionsForKey(String bundleKey) {
+    public List<Subscription> getSubscriptionsForKey(final SubscriptionFactory factory, final String bundleKey) {
         SubscriptionBundle bundle =  bundlesDao.getBundleFromKey(bundleKey);
         if (bundle == null) {
             return Collections.emptyList();
         }
-        return getSubscriptions(bundle.getId());
+        return getSubscriptions(factory, bundle.getId());
     }
 
     @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);
-                dao.insertEvent(nextPhase);
+                cancelNextPhaseEventFromTransaction(subscriptionId, dao, context);
+                dao.insertEvent(nextPhase, context);
+                AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, nextPhase.getId().toString(), ChangeType.INSERT, context);
+
                 recordFutureNotificationFromTransaction(dao,
                         nextPhase.getEffectiveDate(),
                         new NotificationKey() {
@@ -226,24 +243,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>() {
 
@@ -251,11 +264,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);
+                    eventsDaoFromSameTransaction.insertEvent(cur, context);
+                    eventIds.add(cur.getId().toString()); // collect ids for batch audit log insert
                     recordFutureNotificationFromTransaction(dao,
                             cur.getEffectiveDate(),
                             new NotificationKey() {
@@ -265,6 +281,9 @@ public class EntitlementSqlDao implements EntitlementDao {
                                 }
                             });
                 }
+
+                AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+                auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, eventIds, ChangeType.INSERT, context);
                 return null;
             }
         });
@@ -272,40 +291,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);
+                    dao.insertEvent(cur, context);
+                    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);
-                dao.insertEvent(cancelEvent);
+                cancelNextCancelEventFromTransaction(subscriptionId, dao, context);
+                cancelNextChangeEventFromTransaction(subscriptionId, dao, context);
+                cancelNextPhaseEventFromTransaction(subscriptionId, dao, context);
+                dao.insertEvent(cancelEvent, context);
+                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() {
@@ -320,7 +348,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>() {
 
@@ -342,18 +370,26 @@ public class EntitlementSqlDao implements EntitlementDao {
                 }
 
                 if (existingCancelId != null) {
-                    dao.unactiveEvent(existingCancelId.toString(), now);
+                    dao.unactiveEvent(existingCancelId.toString(), context);
+                    String deactivatedEventId = existingCancelId.toString();
+
+                    List<String> eventIds = new ArrayList<String>();
                     for (final EntitlementEvent cur : uncancelEvents) {
-                        dao.insertEvent(cur);
+                        dao.insertEvent(cur, context);
+                        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;
             }
@@ -361,42 +397,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);
+                    dao.insertEvent(cur, context);
+                    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();
@@ -414,7 +458,10 @@ public class EntitlementSqlDao implements EntitlementDao {
         }
 
         if (futureEventId != null) {
-            dao.unactiveEvent(futureEventId.toString(), now);
+            dao.unactiveEvent(futureEventId.toString(), context);
+
+            AuditSqlDao auditSqlDao = dao.become(AuditSqlDao.class);
+            auditSqlDao.insertAuditFromTransaction(ENTITLEMENT_EVENTS_TABLE_NAME, futureEventId.toString(), ChangeType.UPDATE, context);
         }
     }
 
@@ -424,20 +471,19 @@ public class EntitlementSqlDao implements EntitlementDao {
         customFieldDao.saveFields(transactionalDao, subscription.getId(), subscription.getObjectName(), subscription.getFieldList(), context);
     }
 
-    private Subscription buildSubscription(Subscription input) {
+    private Subscription buildSubscription(final SubscriptionFactory factory, final Subscription input) {
         if (input == null) {
             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(factory, input.getBundleId(), false);
             bundleInput.add(baseSubscription);
             bundleInput.add(input);
         } else {
             bundleInput.add(input);
         }
-        List<Subscription> reloadedSubscriptions = buildBundleSubscriptions(bundleInput);
+        List<Subscription> reloadedSubscriptions = buildBundleSubscriptions(factory, bundleInput);
         for (Subscription cur : reloadedSubscriptions) {
             if (cur.getId().equals(input.getId())) {
                 return cur;
@@ -446,7 +492,7 @@ public class EntitlementSqlDao implements EntitlementDao {
          throw new EntitlementError(String.format("Unexpected code path in buildSubscription"));
     }
 
-    private List<Subscription> buildBundleSubscriptions(List<Subscription> input) {
+    private List<Subscription> buildBundleSubscriptions(final SubscriptionFactory factory, final List<Subscription> input) {
         // Make sure BasePlan -- if exists-- is first
         Collections.sort(input, new Comparator<Subscription>() {
             @Override
@@ -517,7 +563,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>() {
 
@@ -528,15 +574,20 @@ public class EntitlementSqlDao implements EntitlementDao {
                 SubscriptionSqlDao transSubDao = transEventDao.become(SubscriptionSqlDao.class);
                 BundleSqlDao transBundleDao = transEventDao.become(BundleSqlDao.class);
 
-                // First get rid of any data from account
-                undoMigrationFromTransaction(accountId, transEventDao, transBundleDao, transSubDao);
+                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);
+                            transEventDao.insertEvent(curEvent, context);
+                            eventIds.add(curEvent.getId().toString()); // gather event ids for batch audit
+
                             recordFutureNotificationFromTransaction(transEventDao,
                                     curEvent.getEffectiveDate(),
                                     new NotificationKey() {
@@ -546,55 +597,35 @@ 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);
+                    transBundleDao.insertBundle(bundleData, context);
+                    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) {
+    private Subscription getBaseSubscription(final SubscriptionFactory factory, final UUID bundleId, boolean rebuildSubscription) {
         List<Subscription> subscriptions = subscriptionsDao.getSubscriptionsFromBundleId(bundleId.toString());
         for (Subscription cur : subscriptions) {
-            if (((SubscriptionData)cur).getCategory() == ProductCategory.BASE) {
-                return  rebuildSubscription ? buildSubscription(cur) : cur;
+            if (cur.getCategory() == ProductCategory.BASE) {
+                return  rebuildSubscription ? buildSubscription(factory, cur) : cur;
             }
         }
         return null;
     }
 
-    @Override
-    public void undoMigration(final UUID accountId) {
-
-        eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
-
-            @Override
-            public Void inTransaction(EventSqlDao transEventDao,
-                    TransactionStatus status) throws Exception {
-
-                SubscriptionSqlDao transSubDao = transEventDao.become(SubscriptionSqlDao.class);
-                BundleSqlDao transBundleDao = transEventDao.become(BundleSqlDao.class);
-                undoMigrationFromTransaction(accountId, transEventDao, transBundleDao, transSubDao);
-                return null;
-            }
-        });
-    }
-
-    private void undoMigrationFromTransaction(final UUID accountId, EventSqlDao transEventDao, BundleSqlDao transBundleDao, SubscriptionSqlDao transSubDao) {
-        final List<SubscriptionBundle> bundles = transBundleDao.getBundleFromAccount(accountId.toString());
-        for (SubscriptionBundle curBundle : bundles) {
-            List<Subscription> subscriptions = transSubDao.getSubscriptionsFromBundleId(curBundle.getId().toString());
-            for (Subscription cur : subscriptions) {
-                eventsDao.removeEvents(cur.getId().toString());
-                transSubDao.removeSubscription(cur.getId().toString());
-            }
-            transBundleDao.removeBundle(curBundle.getId().toString());
-        }
-    }
-
     private void recordFutureNotificationFromTransaction(final Transmogrifier transactionalDao, final DateTime effectiveDate, final NotificationKey notificationKey) {
         try {
             NotificationQueue subscriptionEventQueue = notificationQueueService.getNotificationQueue(Engine.ENTITLEMENT_SERVICE_NAME,
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
index adf007e..0c2ba04 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
@@ -24,8 +24,10 @@ import com.ning.billing.entitlement.events.phase.PhaseEventBuilder;
 import com.ning.billing.entitlement.events.phase.PhaseEventData;
 import com.ning.billing.entitlement.events.user.*;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
-import com.ning.billing.util.entity.BinderBase;
-import com.ning.billing.util.entity.MapperBase;
+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;
 import org.skife.jdbi.v2.SQLStatement;
 import org.skife.jdbi.v2.StatementContext;
@@ -53,16 +55,16 @@ public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transm
     public EntitlementEvent getEventById(@Bind("event_id") String eventId);
 
     @SqlUpdate
-    public void insertEvent(@Bind(binder = EventSqlDaoBinder.class) EntitlementEvent evt);
+    public void insertEvent(@Bind(binder = EventSqlDaoBinder.class) EntitlementEvent evt,
+                            @CallContextBinder final CallContext context);
 
     @SqlUpdate
-    public void removeEvents(@Bind("subscription_id") String subscriptionId);
+    public void unactiveEvent(@Bind("event_id")String eventId,
+                              @CallContextBinder final CallContext context);
 
     @SqlUpdate
-    public void unactiveEvent(@Bind("event_id")String eventId, @Bind("now") Date now);
-
-    @SqlUpdate
-    public void reactiveEvent(@Bind("event_id")String eventId, @Bind("now") Date now);
+    public void reactiveEvent(@Bind("event_id")String eventId,
+                              @CallContextBinder final CallContext context);
 
     @SqlQuery
     @Mapper(EventSqlMapper.class)
@@ -78,8 +80,6 @@ public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transm
             stmt.bind("event_id", evt.getId().toString());
             stmt.bind("event_type", evt.getType().toString());
             stmt.bind("user_type", (evt.getType() == EventType.API_USER) ? ((ApiEvent) evt).getEventType().toString() : null);
-            stmt.bind("created_dt", getDate(evt.getProcessedDate()));
-            stmt.bind("updated_dt", getDate(evt.getProcessedDate()));
             stmt.bind("requested_dt", getDate(evt.getRequestedDate()));
             stmt.bind("effective_dt", getDate(evt.getEffectiveDate()));
             stmt.bind("subscription_id", evt.getSubscriptionId().toString());
@@ -100,7 +100,7 @@ public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transm
             UUID id = UUID.fromString(r.getString("event_id"));
             EventType eventType = EventType.valueOf(r.getString("event_type"));
             ApiEventType userType = (eventType == EventType.API_USER) ? ApiEventType.valueOf(r.getString("user_type")) : null;
-            DateTime createdDate = getDate(r, "created_dt");
+            DateTime createdDate = getDate(r, "created_date");
             DateTime requestedDate = getDate(r, "requested_dt");
             DateTime effectiveDate = getDate(r, "effective_dt");
             UUID subscriptionId = UUID.fromString(r.getString("subscription_id"));
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 3f222ca..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,10 +20,11 @@ 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.entity.BinderBase;
-import com.ning.billing.util.entity.MapperBase;
+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;
-import org.joda.time.DateTimeZone;
 import org.skife.jdbi.v2.SQLStatement;
 import org.skife.jdbi.v2.StatementContext;
 import org.skife.jdbi.v2.sqlobject.Bind;
@@ -39,34 +40,30 @@ import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Timestamp;
 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);
-
-    @SqlUpdate
-    public void removeSubscription(@Bind("id") String id);
+    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());
@@ -80,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 {
@@ -94,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)
@@ -103,7 +100,6 @@ public interface SubscriptionSqlDao extends Transactional<SubscriptionSqlDao>, C
             .setActiveVersion(activeVersion)
             .setChargedThroughDate(ctd)
             .setPaidThroughDate(ptd));
-            return subscription;
         }
     }
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index 01c33f7..055f465 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -32,6 +32,7 @@ import com.ning.billing.entitlement.api.overdue.OverdueChecker;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.SubscriptionApiService;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
 import com.ning.billing.entitlement.engine.addon.AddonUtils;
 import com.ning.billing.entitlement.engine.core.Engine;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
@@ -52,6 +53,7 @@ public class EntitlementModule extends AbstractModule {
     }
 
     protected void installEntitlementCore() {
+    	bind(SubscriptionFactory.class).asEagerSingleton();
         bind(SubscriptionApiService.class).asEagerSingleton();
         bind(EntitlementService.class).to(Engine.class).asEagerSingleton();
         bind(Engine.class).asEagerSingleton();
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
index c39d001..bef27aa 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
@@ -5,8 +5,6 @@ CREATE TABLE entitlement_events (
     event_id char(36) NOT NULL,
     event_type varchar(9) NOT NULL,
     user_type varchar(25) DEFAULT NULL,
-    created_dt datetime NOT NULL,
-    updated_dt datetime NOT NULL,
     requested_dt datetime NOT NULL,
     effective_dt datetime NOT NULL,
     subscription_id char(36) NOT NULL,
@@ -15,11 +13,14 @@ CREATE TABLE entitlement_events (
     plist_name varchar(64) DEFAULT NULL,
     current_version int(11) DEFAULT 1,
     is_active bool DEFAULT 1,
+    created_by varchar(50) NOT NULL,
+    created_date datetime NOT NULL,
+    updated_by varchar(50) NOT NULL,
+    updated_date datetime NOT NULL,
     PRIMARY KEY(id)
 ) ENGINE=innodb;
 CREATE INDEX idx_ent_1 ON entitlement_events(subscription_id,is_active,effective_dt);
-CREATE INDEX idx_ent_2 ON entitlement_events(subscription_id,effective_dt,created_dt,requested_dt,id);
-
+CREATE INDEX idx_ent_2 ON entitlement_events(subscription_id,effective_dt,created_date,requested_dt,id);
 
 DROP TABLE IF EXISTS subscriptions;
 CREATE TABLE subscriptions (
@@ -31,6 +32,10 @@ CREATE TABLE subscriptions (
     active_version int(11) DEFAULT 1,
     ctd_dt datetime DEFAULT NULL,
     ptd_dt datetime DEFAULT NULL,
+    created_by varchar(50) NOT NULL,
+    created_date datetime NOT NULL,
+    updated_by varchar(50) NOT NULL,
+    updated_date datetime NOT NULL,
     PRIMARY KEY(id)
 ) ENGINE=innodb;
 
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg
index d9f26c2..4f0e4db 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg
@@ -14,13 +14,6 @@ insertBundle() ::= <<
     );
 >>
 
-removeBundle(id) ::= <<
-    delete from bundles
-    where
-      id = :id
-    ;
->>
-
 getBundleFromId(id) ::= <<
     select
       id
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg
index b639dce..9179943 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg
@@ -1,21 +1,25 @@
 group EventSqlDao;
 
-getEventById(event_id) ::= <<
-  select
-      id
-      , event_id
-      , event_type
-      , user_type
-      , created_dt
-      , updated_dt
-      , requested_dt
-      , effective_dt
-      , subscription_id
-      , plan_name
-      , phase_name
-      , plist_name
-      , current_version
-      , is_active  
+fields(prefix) ::= <<
+    <prefix>event_id,
+    <prefix>event_type,
+    <prefix>user_type,
+    <prefix>requested_dt,
+    <prefix>effective_dt,
+    <prefix>subscription_id,
+    <prefix>plan_name,
+    <prefix>phase_name,
+    <prefix>plist_name,
+    <prefix>current_version,
+    <prefix>is_active,
+    <prefix>created_by,
+    <prefix>created_date,
+    <prefix>updated_by,
+    <prefix>updated_date
+>>
+
+getEventById() ::= <<
+  select id, <fields()>
   from entitlement_events
   where
       event_id = :event_id
@@ -23,26 +27,11 @@ getEventById(event_id) ::= <<
 >>
 
 insertEvent() ::= <<
-    insert into entitlement_events (
-      event_id
-      , event_type
-      , user_type
-      , created_dt
-      , updated_dt
-      , requested_dt
-      , effective_dt
-      , subscription_id
-      , plan_name
-      , phase_name
-      , plist_name
-      , current_version
-      , is_active
-    ) values (
+    insert into entitlement_events (<fields()>)
+    values (
       :event_id
       , :event_type
       , :user_type
-      , :created_dt
-      , :updated_dt
       , :requested_dt
       , :effective_dt
       , :subscription_id
@@ -51,52 +40,37 @@ insertEvent() ::= <<
       , :plist_name
       , :current_version
       , :is_active
+      , :userName
+      , :createdDate
+      , :userName
+      , :updatedDate
     );   
 >>
 
-removeEvents(subscription_id) ::= <<
-    delete from entitlement_events
-      where
-    subscription_id = :subscription_id
-    ;
->>
-
-unactiveEvent(event_id, now) ::= <<
+unactiveEvent() ::= <<
     update entitlement_events
     set
       is_active = 0
-      , updated_dt = :now
+      , updated_by = :userName
+      , updated_date = :updatedDate
     where
       event_id = :event_id
     ;
 >>
 
-reactiveEvent(event_id, now) ::= <<
+reactiveEvent() ::= <<
     update entitlement_events
     set
       is_active = 1
-      , updated_dt = :now
+      , updated_by = :userName
+      , updated_date = :updatedDate
     where
       event_id = :event_id
     ;
 >>
 
-getFutureActiveEventForSubscription(subscription_id, now) ::= <<
-    select 
-      id
-      , event_id
-      , event_type
-      , user_type
-      , created_dt
-      , updated_dt
-      , requested_dt
-      , effective_dt
-      , subscription_id
-      , plan_name
-      , phase_name
-      , plist_name
-      , current_version
-      , is_active
+getFutureActiveEventForSubscription() ::= <<
+    select id, <fields()>
     from entitlement_events
     where
       subscription_id = :subscription_id
@@ -104,34 +78,20 @@ getFutureActiveEventForSubscription(subscription_id, now) ::= <<
       and effective_dt > :now
     order by
       effective_dt asc
-      , created_dt asc
+      , created_date asc
       , requested_dt asc
       , id asc
     ;
 >> 
 
 getEventsForSubscription(subscription_id) ::= <<
-    select
-       id
-      , event_id
-      , event_type
-      , user_type
-      , created_dt
-      , updated_dt
-      , requested_dt
-      , effective_dt
-      , subscription_id
-      , plan_name
-      , phase_name
-      , plist_name
-      , current_version
-      , is_active
+    select id, <fields()>
     from entitlement_events
     where
       subscription_id = :subscription_id
     order by
       effective_dt asc
-      , created_dt asc
+      , created_date asc
       , requested_dt asc
       , id asc
     ;      
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg
index bb7400b..780c06a 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg
@@ -10,6 +10,10 @@ insertSubscription() ::= <<
       , active_version
       , ctd_dt
       , ptd_dt
+      , created_by
+      , created_date
+      , updated_by
+      , updated_date
     ) values (
         :id
       , :bundle_id
@@ -18,16 +22,14 @@ insertSubscription() ::= <<
       , :bundle_start_dt
       , :active_version
       , :ctd_dt
-      , :ptd_dt 
+      , :ptd_dt
+      , :userName
+      , :createdDate
+      , :userName
+      , :updatedDate
     );
 >>
 
-removeSubscription(id) ::= <<
-    delete from subscriptions
-     where id = :id
-    ;    
->>
-
 getSubscriptionFromId(id) ::= <<
     select
         id
@@ -64,6 +66,8 @@ updateSubscription(id, active_version, ctd_dt, ptd_dt) ::= <<
       active_version = :active_version
       , ctd_dt = :ctd_dt
       , ptd_dt = :ptd_dt
+      , updated_by = :userName
+      , updated_date = :updatedDate
     where id = :id
     ;
 >>
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
index c514164..68f5cbb 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
@@ -141,7 +141,7 @@ public class TestDefaultEntitlementBillingApi {
 
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, dao, accountApi, bcdCalculator);
+		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, null, dao, accountApi, bcdCalculator);
 		SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 		Assert.assertEquals(events.size(), 0);
 	}
@@ -168,7 +168,7 @@ public class TestDefaultEntitlementBillingApi {
 
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, dao, accountApi, bcdCalculator);
+        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, null, dao, accountApi, bcdCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
 		checkFirstEvent(events, nextPlan, 32, oneId, now, nextPhase, ApiEventType.CREATE.toString());
@@ -197,7 +197,7 @@ public class TestDefaultEntitlementBillingApi {
 
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, dao, accountApi, bcdCalculator);
+        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, null, dao, accountApi, bcdCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
 		checkFirstEvent(events, nextPlan, subscription.getStartDate().getDayOfMonth(), oneId, now, nextPhase, ApiEventType.CREATE.toString());
@@ -224,7 +224,7 @@ public class TestDefaultEntitlementBillingApi {
 
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, dao, accountApi, bcdCalculator);
+        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, null, dao, accountApi, bcdCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
 		checkFirstEvent(events, nextPlan, 32, oneId, now, nextPhase, ApiEventType.CREATE.toString());
@@ -253,7 +253,7 @@ public class TestDefaultEntitlementBillingApi {
 
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, dao, accountApi, bcdCalculator);
+        DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(factory, null, dao, accountApi, bcdCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
 		checkFirstEvent(events, nextPlan, subscription.getStartDate().plusDays(30).getDayOfMonth(), oneId, now, nextPhase, ApiEventType.CREATE.toString());
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 75dfc89..3e1b421 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
@@ -29,7 +29,6 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 import org.testng.Assert;
 
-import com.google.common.collect.Lists;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Duration;
 import com.ning.billing.catalog.api.PhaseType;
@@ -45,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 {
@@ -58,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());
@@ -80,7 +79,6 @@ public abstract class TestMigration extends TestApiBase {
         }
     }
 
-
     public void testPlanWithAddOn() {
         try {
             DateTime beforeMigration = clock.getUTCNow();
@@ -91,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());
@@ -126,7 +124,6 @@ public abstract class TestMigration extends TestApiBase {
         }
     }
 
-
     public void testSingleBasePlanFutureCancelled() {
 
         try {
@@ -137,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());
@@ -177,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());
@@ -221,7 +216,6 @@ public abstract class TestMigration extends TestApiBase {
         }
     }
 
-
     public void testSingleBasePlanWithPendingChange() {
 
         try {
@@ -230,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());
@@ -292,7 +286,7 @@ public abstract class TestMigration extends TestApiBase {
                                 }
                                 @Override
                                 public ProductCategory getCategory() {
-                                    return curCases.get(0).getPlanPhaseSpecifer().getProductCategory();
+                                    return curCases.get(0).getPlanPhaseSpecifier().getProductCategory();
                                 }
                                 @Override
                                 public DateTime getChargedThroughDate() {
@@ -428,7 +422,7 @@ public abstract class TestMigration extends TestApiBase {
         }
 
         @Override
-        public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+        public PlanPhaseSpecifier getPlanPhaseSpecifier() {
             return pps;
         }
 
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 a770b4d..c78ee3c 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;
@@ -80,7 +82,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);
@@ -103,6 +104,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);
@@ -157,7 +159,7 @@ public abstract class TestApiBase {
         return (! (theDao instanceof MockEntitlementDaoMemory));
     }
 
-    private void setupMySQL() throws IOException {
+   private void setupMySQL() throws IOException {
         if (helper != null) {
             final String entitlementDdl = IOUtils.toString(TestApiBase.class.getResourceAsStream("/com/ning/billing/entitlement/ddl.sql"));
             final String utilDdl = IOUtils.toString(TestApiBase.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
@@ -189,14 +191,20 @@ public abstract class TestApiBase {
 
         log.warn("RESET TEST FRAMEWORK\n\n");
 
-        testListener.reset();
+        if (testListener != null) {
+            testListener.reset();
+        }
 
         clock.resetDeltaFromReality();
         ((MockEntitlementDao) dao).reset();
 
-        busService.getBus().register(testListener);
-        UUID accountId = UUID.randomUUID();
-        bundle = entitlementApi.createBundleForAccount(accountId, "myDefaultBundle");
+        try {
+            busService.getBus().register(testListener);
+            UUID accountId = UUID.randomUUID();
+            bundle = entitlementApi.createBundleForAccount(accountId, "myDefaultBundle", context);
+        } catch (Exception e) {
+            Assert.fail(e.getMessage());
+        }
         assertNotNull(bundle);
 
         ((Engine)entitlementService).start();
@@ -217,12 +225,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 4043254..0d1d446 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.mock.overdue.MockOverdueAccessModule;
 import com.ning.billing.util.clock.DefaultClock;
@@ -53,7 +52,6 @@ public class TestUserApiAddOn extends TestApiBase {
         return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
     }
 
-
     @Test(enabled=true, groups={"slow"})
     public void testCreateCancelAddon() {
 
@@ -62,7 +60,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;
@@ -72,7 +70,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);
@@ -115,11 +113,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());
@@ -132,7 +130,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
@@ -175,7 +172,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
@@ -186,7 +183,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
@@ -228,7 +225,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
@@ -236,7 +233,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/TestUserApiCancelMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
index b21b16d..5162f17 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
@@ -34,25 +34,25 @@ public class TestUserApiCancelMemory extends TestUserApiCancel {
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testCancelSubscriptionIMM() {
         super.testCancelSubscriptionIMM();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testCancelSubscriptionEOTWithChargeThroughDate() throws EntitlementBillingApiException {
         super.testCancelSubscriptionEOTWithChargeThroughDate();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testCancelSubscriptionEOTWithNoChargeThroughDate() {
         super.testCancelSubscriptionEOTWithNoChargeThroughDate();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testUncancel() throws EntitlementBillingApiException {
         super.testUncancel();
     }
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/TestUserApiChangePlanMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
index 0359d8c..7ec661c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
@@ -34,44 +34,46 @@ public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
 
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testChangePlanBundleAlignEOTWithNoChargeThroughDate() {
          super.testChangePlanBundleAlignEOTWithNoChargeThroughDate();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testChangePlanBundleAlignEOTWithChargeThroughDate() throws EntitlementBillingApiException {
         super.testChangePlanBundleAlignEOTWithChargeThroughDate();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testChangePlanBundleAlignIMM() {
         super.testChangePlanBundleAlignIMM();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testMultipleChangeLastIMM() throws EntitlementBillingApiException {
         super.testMultipleChangeLastIMM();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testMultipleChangeLastEOT() throws EntitlementBillingApiException {
         super.testMultipleChangeLastEOT();
     }
 
+    /*
     // Set to false until we implement rescue example.
     @Override
     @Test(enabled=false, groups={"fast"})
     public void testChangePlanChangePlanAlignEOTWithChargeThroughDate() throws EntitlementBillingApiException {
         super.testChangePlanChangePlanAlignEOTWithChargeThroughDate();
     }
+    */
 
     @Override
-    @Test(enabled=true, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testCorrectPhaseAlignmentOnChange() {
         super.testCorrectPhaseAlignmentOnChange();
     }
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/TestUserApiCreateMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
index b88ed86..922de5e 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
@@ -33,31 +33,31 @@ public class TestUserApiCreateMemory extends TestUserApiCreate {
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testCreateWithRequestedDate() {
         super.testCreateWithRequestedDate();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testCreateWithInitialPhase() {
         super.testSimpleSubscriptionThroughPhases();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     public void testSimpleCreateSubscription() {
         super.testSimpleCreateSubscription();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     protected void testSimpleSubscriptionThroughPhases() {
         super.testSimpleSubscriptionThroughPhases();
     }
 
     @Override
-    @Test(enabled=false, groups={"fast"})
+    @Test(enabled=true, groups={"fast-disabled"})
     protected void testSubscriptionWithAddOn() {
         super.testSubscriptionWithAddOn();
     }
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 ab60304..23e6a6e 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 e18b8cd..3ec6da1 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
@@ -33,6 +33,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;
@@ -50,7 +51,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);
 
@@ -90,7 +91,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());
@@ -105,7 +106,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) {
@@ -118,7 +119,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) {
@@ -128,12 +129,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());
@@ -152,9 +153,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 {
@@ -187,13 +188,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 {
@@ -219,7 +220,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 81125db..80eafc9 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
@@ -54,7 +54,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
@@ -66,21 +66,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);
@@ -91,10 +91,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 c7ef8ad..3e2d52f 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
@@ -80,7 +80,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);
@@ -136,7 +136,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 f73e7e0..94836a8 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
@@ -32,6 +32,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
+import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.catalog.api.TimeUnit;
 import com.ning.billing.config.EntitlementConfig;
@@ -64,17 +65,17 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     private final TreeSet<EntitlementEvent> events;
     private final Clock clock;
     private final EntitlementConfig config;
-    private final SubscriptionFactory factory;
     private final NotificationQueueService notificationQueueService;
+    private final CatalogService catalogService;
 
     @Inject
     public MockEntitlementDaoMemory(final Clock clock, final EntitlementConfig config,
-                                    final SubscriptionFactory factory,
-                                    final NotificationQueueService notificationQueueService) {
+                                    final NotificationQueueService notificationQueueService,
+                                    final CatalogService catalogService) {
         super();
         this.clock = clock;
         this.config = config;
-        this.factory = factory;
+        this.catalogService = catalogService;
         this.notificationQueueService = notificationQueueService;
         this.bundles = new ArrayList<SubscriptionBundle>();
         this.subscriptions = new ArrayList<Subscription>();
@@ -119,18 +120,17 @@ 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());
     }
 
     @Override
-    public Subscription getSubscriptionFromId(final UUID subscriptionId) {
+    public Subscription getSubscriptionFromId(final SubscriptionFactory factory, final UUID subscriptionId) {
         for (final Subscription cur : subscriptions) {
             if (cur.getId().equals(subscriptionId)) {
-                return buildSubscription((SubscriptionData) cur);
+                return buildSubscription(factory, (SubscriptionData) cur);
             }
         }
         return null;
@@ -142,11 +142,11 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public List<Subscription> getSubscriptionsForKey(final String bundleKey) {
+    public List<Subscription> getSubscriptionsForKey(final SubscriptionFactory factory, final String bundleKey) {
 
         for (final SubscriptionBundle cur : bundles) {
             if (cur.getKey().equals(bundleKey)) {
-                return getSubscriptions(cur.getId());
+                return getSubscriptions(factory, cur.getId());
             }
         }
         return Collections.emptyList();
@@ -154,7 +154,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);
@@ -167,13 +168,13 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
                 });
             }
         }
-        Subscription updatedSubscription = buildSubscription(subscription);
+        Subscription updatedSubscription = buildSubscription(null, subscription);
         subscriptions.add(updatedSubscription);
     }
 
     @Override
     public void recreateSubscription(final UUID subscriptionId,
-            final List<EntitlementEvent> recreateEvents) {
+            final List<EntitlementEvent> recreateEvents, final CallContext context) {
 
         synchronized(events) {
             events.addAll(recreateEvents);
@@ -189,12 +190,12 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public List<Subscription> getSubscriptions(final UUID bundleId) {
+    public List<Subscription> getSubscriptions(final SubscriptionFactory factory, final UUID bundleId) {
 
         List<Subscription> results = new ArrayList<Subscription>();
         for (final Subscription cur : subscriptions) {
             if (cur.getBundleId().equals(bundleId)) {
-                results.add(buildSubscription((SubscriptionData) cur));
+                results.add(buildSubscription(factory, (SubscriptionData) cur));
             }
         }
         return results;
@@ -230,30 +231,39 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
 
 
     @Override
-    public Subscription getBaseSubscription(final UUID bundleId) {
+    public Subscription getBaseSubscription(final SubscriptionFactory factory, final UUID bundleId) {
         for (final Subscription cur : subscriptions) {
             if (cur.getBundleId().equals(bundleId) &&
                     cur.getCurrentPlan().getProduct().getCategory() == ProductCategory.BASE) {
-                return buildSubscription((SubscriptionData) cur);
+                return buildSubscription(factory, (SubscriptionData) cur);
             }
         }
         return null;
     }
 
     @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);
     }
 
 
 
-    private Subscription buildSubscription(final SubscriptionData in) {
-        return factory.createSubscription(new SubscriptionBuilder(in), getEventsForSubscription(in.getId()));
+    private Subscription buildSubscription(final SubscriptionFactory factory, final SubscriptionData in) {
+    	if (factory != null) {
+    		return factory.createSubscription(new SubscriptionBuilder(in), getEventsForSubscription(in.getId()));
+    	} else {
+    		SubscriptionData subscription = new SubscriptionData(new SubscriptionBuilder(in), null, clock);
+            if (events.size() > 0) {
+                subscription.rebuildTransitions(getEventsForSubscription(in.getId()), catalogService.getFullCatalog());
+            }
+            return subscription;
+    	}
     }
 
     @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 +281,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 +290,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);
@@ -307,9 +319,10 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
         }
     }
 
+    
     private void cancelNextPhaseEvent(final UUID subscriptionId) {
 
-        Subscription curSubscription = getSubscriptionFromId(subscriptionId);
+        Subscription curSubscription = getSubscriptionFromId(null, subscriptionId);
         if (curSubscription.getCurrentPhase() == null ||
                 curSubscription.getCurrentPhase().getDuration().getUnit() == TimeUnit.UNLIMITED) {
             return;
@@ -355,7 +368,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,11 +396,9 @@ 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) {
 
-            undoMigration(accountId);
-
             for (final BundleMigrationData curBundle : accountData.getData()) {
                 SubscriptionBundleData bundleData = curBundle.getData();
                 for (final SubscriptionMigrationData curSubscription : curBundle.getSubscriptions()) {
@@ -409,26 +421,6 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
-    public void undoMigration(final UUID accountId) {
-        synchronized(events) {
-
-            List<SubscriptionBundle> allBundles = getSubscriptionBundleForAccount(accountId);
-            for (final SubscriptionBundle bundle : allBundles) {
-                List<Subscription> allSubscriptions = getSubscriptions(bundle.getId());
-                for (final Subscription subscription : allSubscriptions) {
-                    List<EntitlementEvent> allEvents = getEventsForSubscription(subscription.getId());
-                    for (final EntitlementEvent event : allEvents) {
-                        events.remove(event);
-                    }
-                    subscriptions.remove(subscription);
-                }
-                bundles.remove(bundle);
-            }
-        }
-
-    }
-
-    @Override
     public EntitlementEvent getEventById(final UUID eventId) {
         synchronized(events) {
             for (final EntitlementEvent cur : events) {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
index 323dd72..54d0e34 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
@@ -38,10 +38,10 @@ public class MockEntitlementDaoSql extends EntitlementSqlDao implements MockEnti
     private final ResetSqlDao resetDao;
 
     @Inject
-    public MockEntitlementDaoSql(IDBI dbi, Clock clock, SubscriptionFactory factory, AddonUtils addonUtils, NotificationQueueService notificationQueueService,
+    public MockEntitlementDaoSql(IDBI dbi, Clock clock, AddonUtils addonUtils, NotificationQueueService notificationQueueService,
                                  CustomFieldDao customFieldDao, final OverdueAccessApi overdueApi,
                                  final CatalogService catalogService) {
-        super(dbi, clock, factory, addonUtils, notificationQueueService, customFieldDao, overdueApi, catalogService);
+        super(dbi, clock, addonUtils, notificationQueueService, customFieldDao, overdueApi, catalogService);
         this.resetDao = dbi.onDemand(ResetSqlDao.class);
     }
 

invoice/pom.xml 10(+9 -1)

diff --git a/invoice/pom.xml b/invoice/pom.xml
index ccef93e..8db3258 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-invoice</artifactId>
@@ -39,13 +39,21 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+            <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-entitlement</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-entitlement</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-catalog</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>com.ning.billing</groupId>
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 9601455..e51ec58 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();
@@ -179,10 +179,10 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     invoicePaymentSqlDao.batchCreateFromTransaction(invoicePayments, context);
 
                     AuditSqlDao auditSqlDao = invoiceDao.become(AuditSqlDao.class);
-                    auditSqlDao.insertAuditFromTransaction("invoices", invoice.getId().toString(), ChangeType.INSERT.toString(), context);
-                    auditSqlDao.insertAuditFromTransaction("recurring_invoice_items", getIdsFromInvoiceItems(recurringInvoiceItems), ChangeType.INSERT.toString(), context);
-                    auditSqlDao.insertAuditFromTransaction("fixed_invoice_items", getIdsFromInvoiceItems(fixedPriceInvoiceItems), ChangeType.INSERT.toString(), context);
-                    auditSqlDao.insertAuditFromTransaction("invoice_payments", getIdsFromInvoicePayments(invoicePayments), ChangeType.INSERT.toString(), context);
+                    auditSqlDao.insertAuditFromTransaction("invoices", invoice.getId().toString(), ChangeType.INSERT, context);
+                    auditSqlDao.insertAuditFromTransaction("recurring_invoice_items", getIdsFromInvoiceItems(recurringInvoiceItems), ChangeType.INSERT, context);
+                    auditSqlDao.insertAuditFromTransaction("fixed_invoice_items", getIdsFromInvoiceItems(fixedPriceInvoiceItems), ChangeType.INSERT, context);
+                    auditSqlDao.insertAuditFromTransaction("invoice_payments", getIdsFromInvoicePayments(invoicePayments), ChangeType.INSERT, context);
 
                 }
 
@@ -242,8 +242,19 @@ public class DefaultInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void notifyOfPaymentAttempt(InvoicePayment invoicePayment, CallContext context) {
-        invoicePaymentSqlDao.notifyOfPaymentAttempt(invoicePayment, context);
+    public void notifyOfPaymentAttempt(final InvoicePayment invoicePayment, final CallContext context) {
+        invoicePaymentSqlDao.inTransaction(new Transaction<Void, InvoicePaymentSqlDao>() {
+            @Override
+            public Void inTransaction(InvoicePaymentSqlDao transactional, TransactionStatus status) throws Exception {
+                transactional.notifyOfPaymentAttempt(invoicePayment, context);
+
+                AuditSqlDao auditSqlDao = transactional.become(AuditSqlDao.class);
+                String invoicePaymentId = invoicePayment.getId().toString();
+                auditSqlDao.insertAuditFromTransaction("invoice_payments", invoicePaymentId, ChangeType.INSERT, context);
+
+                return null;
+            }
+        });
     }
 
     @Override
@@ -366,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);
@@ -375,7 +386,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
             if(subscriptionId != null) {
                 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);
             }
         }
     }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java
index eed9680..c51d65d 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java
@@ -30,7 +30,7 @@ import java.util.UUID;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallContextBinder;
-import com.ning.billing.util.entity.MapperBase;
+import com.ning.billing.util.dao.MapperBase;
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.SQLStatement;
 import org.skife.jdbi.v2.StatementContext;
@@ -42,6 +42,8 @@ import org.skife.jdbi.v2.sqlobject.SqlBatch;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
 import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
@@ -49,7 +51,7 @@ import com.ning.billing.invoice.api.InvoicePayment;
 
 @ExternalizedSqlViaStringTemplate3
 @RegisterMapper(InvoicePaymentSqlDao.InvoicePaymentMapper.class)
-public interface InvoicePaymentSqlDao {
+public interface InvoicePaymentSqlDao extends Transactional<InvoicePaymentSqlDao>, Transmogrifier {
     @SqlQuery
     public InvoicePayment getByPaymentAttemptId(@Bind("paymentAttempt") final String paymentAttemptId);
 
@@ -74,6 +76,8 @@ public interface InvoicePaymentSqlDao {
     void notifyOfPaymentAttempt(@InvoicePaymentBinder final InvoicePayment invoicePayment,
                                 @CallContextBinder final CallContext context);
 
+
+
     public static class InvoicePaymentMapper extends MapperBase implements ResultSetMapper<InvoicePayment> {
         @Override
         public InvoicePayment map(int index, ResultSet result, StatementContext context) throws SQLException {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoicingConfiguration.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoicingConfiguration.java
index 554dc62..7741f00 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoicingConfiguration.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoicingConfiguration.java
@@ -20,7 +20,7 @@ import java.math.BigDecimal;
 
 public class InvoicingConfiguration {
     private final static int roundingMethod = BigDecimal.ROUND_HALF_UP;
-    private final static int numberOfDecimals = 4;
+    private final static int numberOfDecimals = 2;
 
     public static int getRoundingMode() {
         return roundingMethod;
diff --git a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
index 5107d71..03dc211 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
@@ -25,8 +25,8 @@ import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
 import com.ning.billing.config.InvoiceConfig;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.invoice.InvoiceListener;
 import com.ning.billing.invoice.api.DefaultInvoiceService;
 import com.ning.billing.util.bus.Bus;
@@ -45,17 +45,18 @@ public class DefaultNextBillingDateNotifier implements  NextBillingDateNotifier 
 
     private final NotificationQueueService notificationQueueService;
 	private final InvoiceConfig config;
-    private final EntitlementDao entitlementDao;
+	private final EntitlementUserApi entitlementUserApi;
 
+	
     private NotificationQueue nextBillingQueue;
 	private final InvoiceListener listener;
 
     @Inject
 	public DefaultNextBillingDateNotifier(NotificationQueueService notificationQueueService,
-			InvoiceConfig config, EntitlementDao entitlementDao, InvoiceListener listener){
+			InvoiceConfig config, EntitlementUserApi entitlementUserApi, InvoiceListener listener){
 		this.notificationQueueService = notificationQueueService;
 		this.config = config;
-        this.entitlementDao = entitlementDao;
+        this.entitlementUserApi = entitlementUserApi;
         this.listener = listener;
 	}
 
@@ -69,7 +70,7 @@ public class DefaultNextBillingDateNotifier implements  NextBillingDateNotifier 
                 public void handleReadyNotification(String notificationKey, DateTime eventDate) {
                 	try {
                  		UUID key = UUID.fromString(notificationKey);
-                        Subscription subscription = entitlementDao.getSubscriptionFromId(key);
+                        Subscription subscription = entitlementUserApi.getSubscriptionFromId(key);
                         if (subscription == null) {
                             log.warn("Next Billing Date Notification Queue handled spurious notification (key: " + key + ")" );
                         } else {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
index 10f3bef..49d2cb1 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
@@ -52,7 +52,6 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
     protected Clock clock;
     protected CallContext context;
     protected InvoiceGenerator generator;
-    private BusService busService;
 
     private final InvoiceConfig invoiceConfig = new InvoiceConfig() {
         @Override
@@ -70,12 +69,10 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
     @BeforeClass(alwaysRun = true)
     protected void setup() throws IOException {
             module = new InvoiceModuleWithEmbeddedDb();
-            final String accountDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
             final String invoiceDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
             final String entitlementDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/entitlement/ddl.sql"));
 
             module.startDb();
-            module.initDb(accountDdl);
             module.initDb(invoiceDdl);
             module.initDb(entitlementDdl);
 
@@ -127,9 +124,6 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
 
     @AfterClass(alwaysRun = true)
     protected void tearDown() {
-    	if (busService != null) {
-            ((DefaultBusService) busService).stopBus();
-        }
         module.stopDb();
         assertTrue(true);
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
index fd15171..fdcab00 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
@@ -16,11 +16,19 @@
 
 package com.ning.billing.invoice.glue;
 
+import static org.testng.Assert.assertNotNull;
+
 import java.io.IOException;
 import java.net.URL;
 
-import com.ning.billing.invoice.api.test.InvoiceTestApi;
+import org.skife.jdbi.v2.IDBI;
+
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.catalog.glue.CatalogModule;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.glue.EntitlementModule;
 import com.ning.billing.invoice.api.test.DefaultInvoiceTestApi;
+import com.ning.billing.invoice.api.test.InvoiceTestApi;
 import com.ning.billing.invoice.dao.InvoicePaymentSqlDao;
 import com.ning.billing.invoice.dao.RecurringInvoiceItemSqlDao;
 import com.ning.billing.invoice.notification.MockNextBillingDateNotifier;
@@ -28,25 +36,18 @@ import com.ning.billing.invoice.notification.MockNextBillingDatePoster;
 import com.ning.billing.invoice.notification.NextBillingDateNotifier;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
 import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.overdue.MockOverdueAccessModule;
 import com.ning.billing.util.callcontext.CallContextFactory;
 import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.glue.FieldStoreModule;
-import com.ning.billing.util.glue.GlobalLockerModule;
-import com.ning.billing.util.glue.TagStoreModule;
-import org.skife.jdbi.v2.IDBI;
-
-import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.catalog.glue.CatalogModule;
-import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.glue.EntitlementModule;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.DefaultClock;
 import com.ning.billing.util.glue.BusModule;
+import com.ning.billing.util.glue.FieldStoreModule;
+import com.ning.billing.util.glue.GlobalLockerModule;
+import com.ning.billing.util.glue.TagStoreModule;
 import com.ning.billing.util.notificationq.MockNotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 
-import static org.testng.Assert.assertNotNull;
-
 public class InvoiceModuleWithEmbeddedDb extends InvoiceModule {
     private final MysqlTestingHelper helper = new MysqlTestingHelper();
     private IDBI dbi;
@@ -102,6 +103,7 @@ public class InvoiceModuleWithEmbeddedDb extends InvoiceModule {
         bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
         install(new CatalogModule());
         install(new EntitlementModule());
+        install(new MockOverdueAccessModule());
         install(new GlobalLockerModule());
 
         super.configure();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
index c75395f..6c201b6 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
@@ -137,8 +137,8 @@ public class TestNextBillingDateNotifier {
                 IDBI dbi = helper.getDBI();
                 bind(IDBI.class).toInstance(dbi);
                 bind(TagDao.class).to(AuditedTagDao.class).asEagerSingleton();
-                bind(CustomFieldDao.class).to(AuditedCustomFieldDao.class).asEagerSingleton();
                 bind(EntitlementDao.class).to(EntitlementSqlDao.class).asEagerSingleton();
+                bind(CustomFieldDao.class).to(AuditedCustomFieldDao.class).asEagerSingleton();
                 bind(GlobalLocker.class).to(MySqlGlobalLocker.class).asEagerSingleton();
                 bind(InvoiceGenerator.class).to(DefaultInvoiceGenerator.class).asEagerSingleton();
                 bind(InvoiceDao.class).to(DefaultInvoiceDao.class);
@@ -167,12 +167,12 @@ public class TestNextBillingDateNotifier {
         InvoiceDispatcher dispatcher = g.getInstance(InvoiceDispatcher.class);
 
         Subscription subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
-        EntitlementDao entitlementDao = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementDao.class);
-        ((ZombieControl) entitlementDao).addResult("getSubscriptionFromId", subscription);
+        EntitlementUserApi entitlementUserApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+        ((ZombieControl) entitlementUserApi).addResult("getSubscriptionFromId", subscription);
 
         CallContextFactory factory = new DefaultCallContextFactory(clock);
         listener = new InvoiceListenerMock(factory, dispatcher);
-        notifier = new DefaultNextBillingDateNotifier(notificationQueueService,g.getInstance(InvoiceConfig.class), entitlementDao, listener);
+        notifier = new DefaultNextBillingDateNotifier(notificationQueueService,g.getInstance(InvoiceConfig.class), entitlementUserApi, listener);
         startMysql();
 	}
 

payment/pom.xml 2(+1 -1)

diff --git a/payment/pom.xml b/payment/pom.xml
index fc660f7..d55d8d9 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-payment</artifactId>
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
index c014b45..6031600 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
@@ -23,7 +23,6 @@ import java.util.UUID;
 
 import javax.annotation.Nullable;
 
-import com.ning.billing.util.callcontext.CallContext;
 import org.apache.commons.lang.StringUtils;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
@@ -40,6 +39,7 @@ import com.ning.billing.payment.dao.PaymentDao;
 import com.ning.billing.payment.provider.PaymentProviderPlugin;
 import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
 import com.ning.billing.payment.setup.PaymentConfig;
+import com.ning.billing.util.callcontext.CallContext;
 
 public class DefaultPaymentApi implements PaymentApi {
     private final PaymentProviderPluginRegistry pluginRegistry;
@@ -182,13 +182,8 @@ public class DefaultPaymentApi implements PaymentApi {
             Invoice invoice = invoicePaymentApi.getInvoice(UUID.fromString(invoiceId));
 
             if (invoice.getBalance().compareTo(BigDecimal.ZERO) <= 0 ) {
-                // TODO: send a notification that invoice was ignored?
-                log.info("Received invoice for payment with balance of 0 {} ", invoice);
-                Either<PaymentError, PaymentInfo> result = Either.left(new PaymentError("invoice_balance_0",
-                                                                                        "Invoice balance was 0 or less",
-                                                                                        account.getId(),
-                                                                                        UUID.fromString(invoiceId)));
-                processedPaymentsOrErrors.add(result);
+                log.debug("Received invoice for payment with balance of 0 {} ", invoice);
+
             }
             else if (invoice.isMigrationInvoice()) {
             	log.info("Received invoice for payment that is a migration invoice - don't know how to handle those yet: {}", invoice);
@@ -308,9 +303,11 @@ public class DefaultPaymentApi implements PaymentApi {
     }
 
     @Override
-    public List<Either<PaymentError, PaymentInfo>> createRefund(Account account, List<String> invoiceIds, CallContext context) {
-        //TODO
-        throw new UnsupportedOperationException();
+    public List<Either<PaymentError, PaymentInfo>> createRefund(Account account,
+                                                                List<String> invoiceIds,
+                                                                CallContext context) {
+        final PaymentProviderPlugin plugin = getPaymentProviderPlugin(account);
+        return plugin.processRefund(account);
     }
 
     @Override
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java b/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java
index 38e95d6..bcdda9a 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java
@@ -62,7 +62,7 @@ public class AuditedPaymentDao implements PaymentDao {
                 transactional.insertPaymentAttemptHistory(historyRecordId.toString(), paymentAttempt, context);
                 AuditSqlDao auditSqlDao = transactional.become(AuditSqlDao.class);
                 auditSqlDao.insertAuditFromTransaction("payment_attempt", historyRecordId.toString(),
-                                                       ChangeType.INSERT.toString(), context);
+                                                       ChangeType.INSERT, context);
                 return savedPaymentAttempt;
             }
         });
@@ -79,7 +79,7 @@ public class AuditedPaymentDao implements PaymentDao {
                 transactional.insertPaymentAttemptHistory(historyRecordId.toString(), paymentAttempt, context);
                 AuditSqlDao auditSqlDao = transactional.become(AuditSqlDao.class);
                 auditSqlDao.insertAuditFromTransaction("payment_attempt", historyRecordId.toString(),
-                                                       ChangeType.INSERT.toString(), context);
+                                                       ChangeType.INSERT, context);
 
                 return paymentAttempt;
             }
@@ -96,7 +96,7 @@ public class AuditedPaymentDao implements PaymentDao {
                 transactional.insertPaymentInfoHistory(historyRecordId.toString(), info, context);
                 AuditSqlDao auditSqlDao = transactional.become(AuditSqlDao.class);
                 auditSqlDao.insertAuditFromTransaction("payment", historyRecordId.toString(),
-                                                       ChangeType.INSERT.toString(), context);
+                                                       ChangeType.INSERT, context);
 
                 return null;
             }
@@ -114,7 +114,7 @@ public class AuditedPaymentDao implements PaymentDao {
                 transactional.insertPaymentAttemptHistory(historyRecordId.toString(), paymentAttempt, context);
                 AuditSqlDao auditSqlDao = transactional.become(AuditSqlDao.class);
                 auditSqlDao.insertAuditFromTransaction("payment_attempt", historyRecordId.toString(),
-                                                       ChangeType.UPDATE.toString(), context);
+                                                       ChangeType.UPDATE, context);
 
                 return null;
             }
@@ -128,12 +128,12 @@ public class AuditedPaymentDao implements PaymentDao {
             @Override
             public Void inTransaction(PaymentSqlDao transactional, TransactionStatus status) throws Exception {
                 transactional.updatePaymentInfo(type, paymentId, cardType, cardCountry, context);
-                PaymentInfo paymentInfo = transactional.getPaymentInfo(paymentId.toString());
+                PaymentInfo paymentInfo = transactional.getPaymentInfo(paymentId);
                 UUID historyRecordId = UUID.randomUUID();
                 transactional.insertPaymentInfoHistory(historyRecordId.toString(), paymentInfo, context);
                 AuditSqlDao auditSqlDao = transactional.become(AuditSqlDao.class);
                 auditSqlDao.insertAuditFromTransaction("payments", historyRecordId.toString(),
-                                                       ChangeType.UPDATE.toString(), context);
+                                                       ChangeType.UPDATE, context);
 
                 return null;
             }
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
index 245a971..96d7e0b 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
@@ -19,24 +19,20 @@ package com.ning.billing.payment.dao;
 import java.math.BigDecimal;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallContextBinder;
-import com.ning.billing.util.entity.BinderBase;
-import com.ning.billing.util.entity.MapperBase;
+import com.ning.billing.util.dao.BinderBase;
+import com.ning.billing.util.dao.MapperBase;
 import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
 import org.skife.jdbi.v2.SQLStatement;
 import org.skife.jdbi.v2.StatementContext;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.Binder;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
 import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
 import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
 import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
index 280d1e0..a23a4f7 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
@@ -108,4 +108,10 @@ public class NoOpPaymentProviderPlugin implements PaymentProviderPlugin {
         return Either.right(null);
     }
 
+    @Override
+    public List<Either<PaymentError, PaymentInfo>> processRefund(Account account) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java
index 7a9ae71..fd9d160 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java
@@ -42,5 +42,6 @@ public interface PaymentProviderPlugin {
 
     Either<PaymentError, Void> updatePaymentProviderAccountExistingContact(Account account);
     Either<PaymentError, Void> updatePaymentProviderAccountWithNewContact(Account account);
+    List<Either<PaymentError, PaymentInfo>> processRefund(Account account);
 
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
index d85589b..9d89bdf 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.Arrays;
 import java.util.List;
 import java.util.UUID;
@@ -80,7 +81,7 @@ public abstract class TestPaymentApi {
         final DateTime now = new DateTime(DateTimeZone.UTC);
         final Account account = testHelper.createTestCreditCardAccount();
         final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD);
-        final BigDecimal amount = new BigDecimal("10.00");
+        final BigDecimal amount = new BigDecimal("10.0011");
         final UUID subscriptionId = UUID.randomUUID();
         final UUID bundleId = UUID.randomUUID();
 
@@ -102,7 +103,7 @@ public abstract class TestPaymentApi {
         PaymentInfo paymentInfo = results.get(0).getRight();
 
         assertNotNull(paymentInfo.getPaymentId());
-        assertTrue(paymentInfo.getAmount().compareTo(amount) == 0);
+        assertTrue(paymentInfo.getAmount().compareTo(amount.setScale(2, RoundingMode.HALF_EVEN)) == 0);
         assertNotNull(paymentInfo.getPaymentNumber());
         assertFalse(paymentInfo.getStatus().equals("Error"));
 
diff --git a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
index 47713bb..adda477 100644
--- a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -24,13 +24,11 @@ import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import com.google.inject.Inject;
-import com.ning.billing.util.clock.Clock;
 import org.apache.commons.lang.RandomStringUtils;
-import org.joda.time.DateTime;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
+import com.google.inject.Inject;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.payment.api.CreditCardPaymentMethodInfo;
@@ -40,6 +38,7 @@ import com.ning.billing.payment.api.PaymentInfo;
 import com.ning.billing.payment.api.PaymentMethodInfo;
 import com.ning.billing.payment.api.PaymentProviderAccount;
 import com.ning.billing.payment.api.PaypalPaymentMethodInfo;
+import com.ning.billing.util.clock.Clock;
 
 public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
     private final AtomicBoolean makeNextInvoiceFail = new AtomicBoolean(false);
@@ -266,8 +265,14 @@ public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
 
     @Override
     public Either<PaymentError, Void> updatePaymentProviderAccountWithNewContact(Account account) {
-        // nothing to do here
-        return Either.right(null);
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<Either<PaymentError, PaymentInfo>> processRefund(Account account) {
+        // TODO Auto-generated method stub
+        return null;
     }
 
 }

pom.xml 5(+2 -3)

diff --git a/pom.xml b/pom.xml
index 8fc2813..8252d49 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,8 +7,7 @@
     OR CONDITIONS OF ANY KIND, either express or implied. See the ~ License for 
     the specific language governing permissions and limitations ~ under the License. -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <groupId>org.sonatype.oss</groupId>
         <artifactId>oss-parent</artifactId>
@@ -18,7 +17,7 @@
     <groupId>com.ning.billing</groupId>
     <artifactId>killbill</artifactId>
     <packaging>pom</packaging>
-    <version>0.1.8-SNAPSHOT</version>
+    <version>0.1.11-SNAPSHOT</version>
     <name>killbill</name>
     <description>Library for managing recurring subscriptions and the associated billing</description>
     <url>http://github.com/ning/killbill</url>

README.md 2(+2 -0)

diff --git a/README.md b/README.md
index e69de29..314b6f4 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,2 @@
+Killbill is an open source subscription management/billing system.
+You can find the documentation [here](http://ning.github.com/killbill/).

util/pom.xml 5(+2 -3)

diff --git a/util/pom.xml b/util/pom.xml
index dc5c251..e0d256c 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -8,13 +8,12 @@
     OR CONDITIONS OF ANY KIND, either express or implied. See the ~ License for 
     the specific language governing permissions and limitations ~ under the License. -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.8-SNAPSHOT</version>
+        <version>0.1.11-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-util</artifactId>
diff --git a/util/src/main/java/com/ning/billing/util/audit/dao/AuditSqlDao.java b/util/src/main/java/com/ning/billing/util/audit/dao/AuditSqlDao.java
index f3f96f4..8c14942 100644
--- a/util/src/main/java/com/ning/billing/util/audit/dao/AuditSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/audit/dao/AuditSqlDao.java
@@ -16,8 +16,10 @@
 
 package com.ning.billing.util.audit.dao;
 
+import com.ning.billing.util.ChangeType;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallContextBinder;
+import com.ning.billing.util.dao.ChangeTypeBinder;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlBatch;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
@@ -30,12 +32,12 @@ public interface AuditSqlDao {
     @SqlUpdate
     public void insertAuditFromTransaction(@Bind("tableName") final String tableName,
                                            @Bind("recordId") final String recordId,
-                                           @Bind("changeType") String changeType,
+                                           @ChangeTypeBinder final ChangeType changeType,
                                            @CallContextBinder CallContext context);
 
     @SqlBatch(transactional = false)
     public void insertAuditFromTransaction(@Bind("tableName") final String tableName,
                                            @Bind("recordId") final List<String> recordIds,
-                                           @Bind("changeType") String changeType,
+                                           @ChangeTypeBinder final ChangeType changeType,
                                            @CallContextBinder CallContext context);
 }
diff --git a/util/src/main/java/com/ning/billing/util/customfield/CustomFieldMapper.java b/util/src/main/java/com/ning/billing/util/customfield/CustomFieldMapper.java
index 97d469d..0c2bc5b 100644
--- a/util/src/main/java/com/ning/billing/util/customfield/CustomFieldMapper.java
+++ b/util/src/main/java/com/ning/billing/util/customfield/CustomFieldMapper.java
@@ -16,7 +16,7 @@
 
 package com.ning.billing.util.customfield;
 
-import com.ning.billing.util.entity.MapperBase;
+import com.ning.billing.util.dao.MapperBase;
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.StatementContext;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
diff --git a/util/src/main/java/com/ning/billing/util/dao/ChangeTypeBinder.java b/util/src/main/java/com/ning/billing/util/dao/ChangeTypeBinder.java
new file mode 100644
index 0000000..58ed27b
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/dao/ChangeTypeBinder.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.dao;
+
+import com.ning.billing.util.ChangeType;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@BindingAnnotation(ChangeTypeBinder.ChangeTypeBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface ChangeTypeBinder {
+    public static class ChangeTypeBinderFactory implements BinderFactory {
+        public Binder build(Annotation annotation) {
+            return new Binder<ChangeTypeBinder, ChangeType>() {
+                public void bind(SQLStatement q, ChangeTypeBinder bind, ChangeType changeType) {
+                    q.bind("changeType", changeType.toString());
+                }
+            };
+        }
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/OverdueAccessModule.java b/util/src/main/java/com/ning/billing/util/glue/OverdueAccessModule.java
index 8f4f634..a56718e 100644
--- a/util/src/main/java/com/ning/billing/util/glue/OverdueAccessModule.java
+++ b/util/src/main/java/com/ning/billing/util/glue/OverdueAccessModule.java
@@ -21,6 +21,8 @@ import org.skife.jdbi.v2.IDBI;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import com.ning.billing.util.overdue.DefaultOverdueAcessApi;
+import com.ning.billing.util.overdue.OverdueAccessApi;
 import com.ning.billing.util.overdue.dao.OverdueAccessDao;
 import com.ning.billing.util.overdue.dao.OverdueAccessSqlDao;
 
@@ -29,6 +31,7 @@ public class OverdueAccessModule extends AbstractModule {
     @Override
     protected void configure() {
         bind(OverdueAccessDao.class).toProvider(OverdueAccessDaoProvider.class);
+        bind(OverdueAccessApi.class).to(DefaultOverdueAcessApi.class);
     }
 
     public static class OverdueAccessDaoProvider implements Provider<OverdueAccessDao>{
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java b/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
index f0a54f3..bb97dd7 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
@@ -18,15 +18,13 @@ package com.ning.billing.util.notificationq.dao;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Timestamp;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
-import com.ning.billing.util.entity.BinderBase;
-import com.ning.billing.util.entity.MapperBase;
+import com.ning.billing.util.dao.BinderBase;
+import com.ning.billing.util.dao.MapperBase;
 import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
 import org.skife.jdbi.v2.SQLStatement;
 import org.skife.jdbi.v2.StatementContext;
 import org.skife.jdbi.v2.sqlobject.Bind;
diff --git a/util/src/main/java/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.java b/util/src/main/java/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.java
index 8dfd32b..25c0ee6 100644
--- a/util/src/main/java/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.java
@@ -37,8 +37,8 @@ import org.skife.jdbi.v2.tweak.ResultSetMapper;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.overdue.Overdueable;
 import com.ning.billing.catalog.api.overdue.Overdueable.Type;
-import com.ning.billing.util.entity.BinderBase;
-import com.ning.billing.util.entity.MapperBase;
+import com.ning.billing.util.dao.BinderBase;
+import com.ning.billing.util.dao.MapperBase;
 import com.ning.billing.util.overdue.OverdueAccessApi;
 import com.ning.billing.util.overdue.OverdueEvent;
 
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
index 6e361f9..374e0a3 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
@@ -19,6 +19,8 @@ package com.ning.billing.util.tag.dao;
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
 import com.ning.billing.invoice.api.InvoiceApiException;
+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.tag.Tag;
 import org.skife.jdbi.v2.IDBI;
@@ -26,48 +28,23 @@ import org.skife.jdbi.v2.Transaction;
 import org.skife.jdbi.v2.TransactionStatus;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.UUID;
 
 public class AuditedTagDao implements TagDao {
     private final TagSqlDao tagSqlDao;
-    private final TagAuditSqlDao tagAuditSqlDao;
 
     @Inject
     public AuditedTagDao(final IDBI dbi) {
         this.tagSqlDao = dbi.onDemand(TagSqlDao.class);
-        this.tagAuditSqlDao = dbi.onDemand(TagAuditSqlDao.class);
     }
 
     @Override
     public void saveTags(final UUID objectId, final String objectType,
                          final List<Tag> tags, final CallContext context) {
-        // get list of existing tags
-        List<Tag> existingTags = tagSqlDao.load(objectId.toString(), objectType);
-
-        // sort into tags to update (tagsToUpdate), tags to add (tags), and tags to delete (existingTags)
-        Iterator<Tag> tagIterator = tags.iterator();
-        while (tagIterator.hasNext()) {
-            Tag tag = tagIterator.next();
-
-            Iterator<Tag> existingTagIterator = existingTags.iterator();
-            while (existingTagIterator.hasNext()) {
-                Tag existingTag = existingTagIterator.next();
-                if (tag.getTagDefinitionName().equals(existingTag.getTagDefinitionName())) {
-                    // if the tags match, remove from both lists
-                    // in the case of tag, this just means the tag remains associated
-                    tagIterator.remove();
-                    existingTagIterator.remove();
-                }
-            }
-        }
-
-        tagSqlDao.batchInsertFromTransaction(objectId.toString(), objectType, tags, context);
-        tagSqlDao.batchDeleteFromTransaction(objectId.toString(), objectType, existingTags, context);
-
-        tagAuditSqlDao.batchInsertFromTransaction(tags, context);
-        tagAuditSqlDao.batchDeleteFromTransaction(existingTags, context);
+        saveTagsFromTransaction(tagSqlDao, objectId, objectType, tags, context);
     }
 
     @Override
@@ -98,9 +75,22 @@ public class AuditedTagDao implements TagDao {
         tagSqlDao.batchInsertFromTransaction(objectId.toString(), objectType, tags, context);
         tagSqlDao.batchDeleteFromTransaction(objectId.toString(), objectType, existingTags, context);
 
-        TagAuditSqlDao auditDao = dao.become(TagAuditSqlDao.class);
-        auditDao.batchInsertFromTransaction(tags, context);
-        auditDao.batchDeleteFromTransaction(existingTags, context);
+        List<String> historyIdsForInsert = getIdList(tags.size());
+        tagSqlDao.batchInsertHistoryFromTransaction(objectId.toString(), objectType, historyIdsForInsert, tags, ChangeType.INSERT, context);
+        List<String> historyIdsForDelete = getIdList(existingTags.size());
+        tagSqlDao.batchInsertHistoryFromTransaction(objectId.toString(), objectType, historyIdsForDelete, existingTags, ChangeType.DELETE, context);
+
+        AuditSqlDao auditSqlDao = tagSqlDao.become(AuditSqlDao.class);
+        auditSqlDao.insertAuditFromTransaction("tag_history", historyIdsForInsert, ChangeType.INSERT, context);
+        auditSqlDao.insertAuditFromTransaction("tag_history", historyIdsForDelete, ChangeType.DELETE, context);
+    }
+
+    private List<String> getIdList(int size) {
+        List<String> results = new ArrayList<String>();
+        for (int i = 0; i < size; i++) {
+            results.add(UUID.randomUUID().toString());
+        }
+        return results;
     }
 
     @Override
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagAuditSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagAuditSqlDao.java
index 02fb33d..7e6cbee 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagAuditSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagAuditSqlDao.java
@@ -31,14 +31,6 @@ import java.util.List;
 @ExternalizedSqlViaStringTemplate3
 @RegisterMapper(TagMapper.class)
 public interface TagAuditSqlDao extends Transactional<TagAuditSqlDao> {
-    @SqlBatch(transactional=false)
-    public void batchInsertFromTransaction(@TagBinder final List<Tag> tag,
-                                           @CallContextBinder final CallContext context);
-
-    @SqlBatch(transactional=false)
-    public void batchDeleteFromTransaction(@TagBinder final List<Tag> tag,
-                                           @CallContextBinder final CallContext context);
-
     @SqlUpdate
     public void addTagFromTransaction(@Bind("id") final String tagId,
                                       @CallContextBinder final CallContext context);
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java
index 74e6f04..211ae5a 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java
@@ -18,13 +18,9 @@ package com.ning.billing.util.tag.dao;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
 import java.util.UUID;
 
-import com.ning.billing.util.entity.MapperBase;
-import com.ning.billing.util.tag.ControlTag;
+import com.ning.billing.util.dao.MapperBase;
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.StatementContext;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
index 79b68b0..a20e757 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
@@ -18,8 +18,10 @@ package com.ning.billing.util.tag.dao;
 
 import java.util.List;
 
+import com.ning.billing.util.ChangeType;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallContextBinder;
+import com.ning.billing.util.dao.ChangeTypeBinder;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlBatch;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
@@ -48,6 +50,14 @@ public interface TagSqlDao extends EntityCollectionDao<Tag>, Transactional<TagSq
                                            @TagBinder final List<Tag> entities,
                                            @CallContextBinder final CallContext context);
 
+    @SqlBatch(transactional = false)
+    public void batchInsertHistoryFromTransaction(@Bind("objectId") final String objectId,
+                                                  @Bind("objectType") final String objectType,
+                                                  @Bind("historyRecordId") final List<String> historyRecordIdList,
+                                                  @TagBinder final List<Tag> tags,
+                                                  @ChangeTypeBinder final ChangeType changeType,
+                                                  @CallContextBinder final CallContext context);
+
     @SqlUpdate
     public void addTagFromTransaction(@Bind("id") final String tagId,
                                       @Bind("tagDefinitionName") final String tagName,
diff --git a/util/src/main/resources/com/ning/billing/util/ddl.sql b/util/src/main/resources/com/ning/billing/util/ddl.sql
index b40e5a4..a2ef08f 100644
--- a/util/src/main/resources/com/ning/billing/util/ddl.sql
+++ b/util/src/main/resources/com/ning/billing/util/ddl.sql
@@ -68,7 +68,8 @@ CREATE UNIQUE INDEX tags_unique ON tags(tag_definition_name, object_id);
 
 DROP TABLE IF EXISTS tag_history;
 CREATE TABLE tag_history (
-  id char(36) NULL,
+  history_record_id char(36) NOT NULL,
+  id char(36) NOT NULL,
   tag_definition_name varchar(20) NOT NULL,
   object_id char(36) NOT NULL,
   object_type varchar(30) NOT NULL,
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagAuditSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagAuditSqlDao.sql.stg
index c591fba..e3262a4 100644
--- a/util/src/main/resources/com/ning/billing/util/tag/dao/TagAuditSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagAuditSqlDao.sql.stg
@@ -10,16 +10,6 @@ fields(prefix) ::= <<
     <prefix>comments
 >>
 
-batchInsertFromTransaction() ::= <<
-    INSERT INTO audit_log(<fields()>)
-    VALUES('tag', :id, 'INSERT', :createdDate, :userName, NULL, NULL);
->>
-
-batchDeleteFromTransaction() ::= <<
-    INSERT INTO audit_log(<fields()>)
-    VALUES('tag', :id, 'DELETE', :updatedDate, :userName, NULL, NULL);
->>
-
 addTagFromTransaction() ::= <<
     INSERT INTO audit_log(<fields()>)
     VALUES('tag', :id, 'INSERT', :createdDate, :userName, NULL, NULL);
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
index e950d75..8f98452 100644
--- a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
@@ -14,6 +14,11 @@ batchInsertFromTransaction() ::= <<
   VALUES (:id, :tagDefinitionName, :objectId, :objectType, :userName, :createdDate);
 >>
 
+batchInsertHistoryFromTransaction() ::= <<
+    INSERT INTO tag_history (history_record_id, id, tag_definition_name, object_id, object_type, change_type, updated_by, date)
+    VALUES (:historyRecordId, :id, :tagDefinitionName, :objectId, :objectType, :changeType, :userName, :updatedDate);
+>>
+
 batchDeleteFromTransaction() ::= <<
     DELETE FROM tags
     WHERE tag_definition_name = :tagDefinitionName
diff --git a/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java b/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
index 1e51e57..a8d353f 100644
--- a/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
+++ b/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
@@ -388,7 +388,7 @@ public class TestTagStore {
         assertEquals(savedTag.getId(), tag.getId());
 
         Handle handle = dbi.open();
-        String query = String.format("select * from audit_log where table_name = 'Tag' and record_id='%s'",
+        String query = String.format("select * from audit_log a inner join tag_history th on a.record_id = th.history_record_id where a.table_name = 'tag_history' and th.id='%s' and a.change_type='INSERT'",
                                      tag.getId().toString());
         List<Map<String, Object>> result = handle.select(query);
         assertNotNull(result);
@@ -417,7 +417,7 @@ public class TestTagStore {
         assertEquals(savedTags.size(), 0);
 
         Handle handle = dbi.open();
-        String query = String.format("select * from audit_log where table_name = 'tag' and record_id='%s' and change_type='DELETE'",
+        String query = String.format("select * from audit_log a inner join tag_history th on a.record_id = th.history_record_id where a.table_name = 'tag_history' and th.id='%s' and a.change_type='DELETE'",
                                      tag.getId().toString());
         List<Map<String, Object>> result = handle.select(query);
         assertNotNull(result);