killbill-memoizeit

Merge branch 'bugfixes' of github.com:ning/killbill into

7/7/2012 1:12:35 AM

Changes

api/src/main/java/com/ning/billing/invoice/api/test/InvoiceTestApi.java 24(+0 -24)

invoice/src/main/java/com/ning/billing/invoice/api/test/DefaultInvoiceTestApi.java 36(+0 -36)

Details

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 405c431..c249f6a 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
@@ -225,7 +225,7 @@ public class TestAnalyticsService extends TestWithEmbeddedDB {
                 INVOICE_AMOUNT, ACCOUNT_CURRENCY);
         invoice.addInvoiceItem(invoiceItem);
 
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
         final List<Invoice> invoices = invoiceDao.getInvoicesByAccount(account.getId());
         Assert.assertEquals(invoices.size(), 1);
         Assert.assertEquals(invoices.get(0).getInvoiceItems().size(), 1);
diff --git a/api/src/main/java/com/ning/billing/glue/InvoiceModule.java b/api/src/main/java/com/ning/billing/glue/InvoiceModule.java
index 7e55895..f513edd 100644
--- a/api/src/main/java/com/ning/billing/glue/InvoiceModule.java
+++ b/api/src/main/java/com/ning/billing/glue/InvoiceModule.java
@@ -17,13 +17,9 @@
 package com.ning.billing.glue;
 
 public interface InvoiceModule {
-
     public abstract void installInvoiceUserApi();
 
     public abstract void installInvoicePaymentApi();
 
     public abstract void installInvoiceMigrationApi();
-
-    public abstract void installInvoiceTestApi();
-
-}
\ No newline at end of file
+}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index 7aeaa80..cb19fa0 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -13,6 +13,7 @@
  * License for the specific language governing permissions and limitations
  * under the License.
  */
+
 package com.ning.billing.beatrix.integration;
 
 import java.io.IOException;
@@ -87,7 +88,6 @@ public class TestIntegrationBase implements TestListenerStatus {
     protected static final Logger log = LoggerFactory.getLogger(TestIntegration.class);
     protected static long AT_LEAST_ONE_MONTH_MS = 31L * 24L * 3600L * 1000L;
 
-
     protected static final long DELAY = 5000;
 
     @Inject
@@ -148,7 +148,6 @@ public class TestIntegrationBase implements TestListenerStatus {
 
     protected TestApiListener busHandler;
 
-
     private boolean isListenerFailed;
     private String listenerFailedMsg;
 
@@ -164,7 +163,6 @@ public class TestIntegrationBase implements TestListenerStatus {
         listenerFailedMsg = null;
     }
 
-
     protected void assertListenerStatus() {
         if (isListenerFailed) {
             log.error(listenerFailedMsg);
@@ -192,15 +190,12 @@ public class TestIntegrationBase implements TestListenerStatus {
         helper.initDb(junctionDb);
     }
 
-
     @BeforeClass(groups = "slow")
     public void setup() throws Exception {
-
         setupMySQL();
 
         context = new DefaultCallContextFactory(clock).createCallContext("Integration Test", CallOrigin.TEST, UserType.TEST);
         busHandler = new TestApiListener(this);
-
     }
 
     @AfterClass(groups = "slow")
@@ -208,10 +203,8 @@ public class TestIntegrationBase implements TestListenerStatus {
         helper.stopMysql();
     }
 
-
     @BeforeMethod(groups = "slow")
     public void setupTest() throws Exception {
-
         log.warn("\n");
         log.warn("RESET TEST FRAMEWORK\n\n");
 
@@ -236,7 +229,6 @@ public class TestIntegrationBase implements TestListenerStatus {
         log.warn("DONE WITH TEST\n");
     }
 
-
     protected void verifyTestResult(final UUID accountId, final UUID subscriptionId,
                                     final DateTime startDate, final DateTime endDate,
                                     final BigDecimal amount, final DateTime chargeThroughDate,
@@ -303,11 +295,11 @@ public class TestIntegrationBase implements TestListenerStatus {
                 return UUID.randomUUID().toString();
             }
         };
+
         paymentApi.addPaymentMethod(BeatrixModule.PLUGIN_NAME, account, true, info, context);
         return accountUserApi.getAccountById(account.getId());
     }
 
-
     protected AccountData getAccountData(final int billingDay) {
         final String someRandomKey = UUID.randomUUID().toString();
         return new AccountData() {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
index 9e9b95c..67d3c77 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
@@ -20,8 +20,13 @@ import java.math.BigDecimal;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
@@ -35,23 +40,35 @@ import com.ning.billing.util.callcontext.UserType;
 import com.ning.billing.util.clock.Clock;
 
 public class DefaultInvoiceMigrationApi implements InvoiceMigrationApi {
+    private static final Logger log = LoggerFactory.getLogger(DefaultInvoiceMigrationApi.class);
 
+    private final AccountUserApi accountUserApi;
     private final DefaultInvoiceDao dao;
     private final Clock clock;
 
     @Inject
-    public DefaultInvoiceMigrationApi(final DefaultInvoiceDao dao, final Clock clock) {
+    public DefaultInvoiceMigrationApi(final AccountUserApi accountUserApi, final DefaultInvoiceDao dao, final Clock clock) {
+        this.accountUserApi = accountUserApi;
         this.dao = dao;
         this.clock = clock;
     }
 
     @Override
     public UUID createMigrationInvoice(final UUID accountId, final DateTime targetDate, final BigDecimal balance, final Currency currency) {
+        final Account account;
+        try {
+            account = accountUserApi.getAccountById(accountId);
+        } catch (AccountApiException e) {
+            log.warn("Unable to find account for id {}", accountId);
+            return null;
+        }
+
         final CallContext context = new DefaultCallContextFactory(clock).createMigrationCallContext("Migration", CallOrigin.INTERNAL, UserType.MIGRATION, clock.getUTCNow(), clock.getUTCNow());
         final Invoice migrationInvoice = new MigrationInvoice(accountId, clock.getUTCNow(), targetDate, currency);
         final InvoiceItem migrationInvoiceItem = new MigrationInvoiceItem(migrationInvoice.getId(), accountId, targetDate, balance, currency);
         migrationInvoice.addInvoiceItem(migrationInvoiceItem);
-        dao.create(migrationInvoice, context);
+
+        dao.create(migrationInvoice, account.getBillCycleDay(), context);
         return migrationInvoice.getId();
     }
 }
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 06eab09..11dc976 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
@@ -19,20 +19,14 @@ package com.ning.billing.invoice.dao;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
-import javax.annotation.Nullable;
-
 import org.joda.time.DateTime;
-import org.joda.time.MutableDateTime;
-import org.joda.time.field.ZeroIsMaxDateTimeField;
 import org.skife.jdbi.v2.IDBI;
 import org.skife.jdbi.v2.Transaction;
 import org.skife.jdbi.v2.TransactionStatus;
 
-import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.inject.Inject;
@@ -48,7 +42,6 @@ import com.ning.billing.invoice.model.CreditAdjInvoiceItem;
 import com.ning.billing.invoice.model.CreditBalanceAdjInvoiceItem;
 import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.DefaultInvoicePayment;
-import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.invoice.model.RefundAdjInvoiceItem;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
@@ -66,7 +59,6 @@ public class DefaultInvoiceDao implements InvoiceDao {
     private final InvoicePaymentSqlDao invoicePaymentSqlDao;
     private final TagUserApi tagUserApi;
     private final NextBillingDatePoster nextBillingDatePoster;
-
     private final InvoiceItemSqlDao invoiceItemSqlDao;
 
     @Inject
@@ -147,13 +139,11 @@ public class DefaultInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void create(final Invoice invoice, final CallContext context) {
+    public void create(final Invoice invoice, final int billCycleDay, final CallContext context) {
         invoiceSqlDao.inTransaction(new Transaction<Void, InvoiceSqlDao>() {
             @Override
             public Void inTransaction(final InvoiceSqlDao transactional, final TransactionStatus status) throws Exception {
-
                 final Invoice currentInvoice = transactional.getById(invoice.getId().toString());
-
                 if (currentInvoice == null) {
                     final List<EntityAudit> audits = new ArrayList<EntityAudit>();
 
@@ -169,9 +159,8 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     recordIdList = transInvoiceItemSqlDao.getRecordIds(invoice.getId().toString());
                     audits.addAll(createAudits(TableName.INVOICE_ITEMS, recordIdList));
 
-                    List<InvoiceItem> recurringInvoiceItems = invoice.getInvoiceItems(RecurringInvoiceItem.class);
-
-                    notifyOfFutureBillingEvents(transactional, invoice.getAccountId(), recurringInvoiceItems);
+                    final List<InvoiceItem> recurringInvoiceItems = invoice.getInvoiceItems(RecurringInvoiceItem.class);
+                    notifyOfFutureBillingEvents(transactional, invoice.getAccountId(), billCycleDay, recurringInvoiceItems);
 
                     final List<InvoicePayment> invoicePayments = invoice.getPayments();
                     final InvoicePaymentSqlDao invoicePaymentSqlDao = transactional.become(InvoicePaymentSqlDao.class);
@@ -186,8 +175,6 @@ public class DefaultInvoiceDao implements InvoiceDao {
         });
     }
 
-
-
     private List<EntityAudit> createAudits(final TableName tableName, final List<Long> recordIdList) {
         final List<EntityAudit> entityAuditList = new ArrayList<EntityAudit>();
         for (final Long recordId : recordIdList) {
@@ -217,12 +204,11 @@ public class DefaultInvoiceDao implements InvoiceDao {
         return invoiceSqlDao.inTransaction(new Transaction<BigDecimal, InvoiceSqlDao>() {
             @Override
             public BigDecimal inTransaction(final InvoiceSqlDao transactional, final TransactionStatus status) throws Exception {
-
                 BigDecimal cba = BigDecimal.ZERO;
 
                 BigDecimal accountBalance = BigDecimal.ZERO;
-                List<Invoice> invoices = getAllInvoicesByAccountFromTransaction(accountId, transactional);
-                for (Invoice cur : invoices) {
+                final List<Invoice> invoices = getAllInvoicesByAccountFromTransaction(accountId, transactional);
+                for (final Invoice cur : invoices) {
                     accountBalance = accountBalance.add(cur.getBalance());
                     cba = cba.add(cur.getCBAAmount());
                 }
@@ -241,7 +227,6 @@ public class DefaultInvoiceDao implements InvoiceDao {
         });
     }
 
-
     @Override
     public void notifyOfPayment(final InvoicePayment invoicePayment, final CallContext context) {
         invoicePaymentSqlDao.inTransaction(new Transaction<Void, InvoicePaymentSqlDao>() {
@@ -297,11 +282,9 @@ public class DefaultInvoiceDao implements InvoiceDao {
         tagUserApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.toTagDefinition(), context);
     }
 
-
     @Override
-    public InvoicePayment createRefund(final UUID paymentId, final BigDecimal amount, final boolean isInvoiceAdjusted, final UUID paymentCookieId,  final CallContext context)
+    public InvoicePayment createRefund(final UUID paymentId, final BigDecimal amount, final boolean isInvoiceAdjusted, final UUID paymentCookieId, final CallContext context)
             throws InvoiceApiException {
-
         return invoicePaymentSqlDao.inTransaction(new Transaction<InvoicePayment, InvoicePaymentSqlDao>() {
             @Override
             public InvoicePayment inTransaction(final InvoicePaymentSqlDao transactional, final TransactionStatus status) throws Exception {
@@ -329,34 +312,36 @@ public class DefaultInvoiceDao implements InvoiceDao {
                 }
 
                 final InvoicePayment refund = new DefaultInvoicePayment(UUID.randomUUID(), InvoicePaymentType.REFUND, paymentId,
-                        payment.getInvoiceId(), context.getCreatedDate(), requestedPositiveAmount.negate(), payment.getCurrency(), paymentCookieId, payment.getId());
+                                                                        payment.getInvoiceId(), context.getCreatedDate(), requestedPositiveAmount.negate(),
+                                                                        payment.getCurrency(), paymentCookieId, payment.getId());
                 transactional.create(refund, context);
 
                 // Retrieve invoice after the Refund
-                InvoiceSqlDao transInvoiceDao = transactional.become(InvoiceSqlDao.class);
-                Invoice invoice = transInvoiceDao.getById(payment.getInvoiceId().toString());
+                final InvoiceSqlDao transInvoiceDao = transactional.become(InvoiceSqlDao.class);
+                final Invoice invoice = transInvoiceDao.getById(payment.getInvoiceId().toString());
                 if (invoice != null) {
                     populateChildren(invoice, transInvoiceDao);
+                } else {
+                    throw new IllegalStateException("Invoice shouldn't be null for payment " + payment.getId());
                 }
 
                 final BigDecimal invoiceBalanceAfterRefund = invoice.getBalance();
-                InvoiceItemSqlDao transInvoiceItemDao = transInvoiceDao.become(InvoiceItemSqlDao.class);
+                final InvoiceItemSqlDao transInvoiceItemDao = transInvoiceDao.become(InvoiceItemSqlDao.class);
 
                 // If we have an existing CBA > 0, we need to adjust it
                 //final BigDecimal cbaAmountAfterRefund = invoice.getCBAAmount();
                 final BigDecimal accountCbaAvailable = getAccountCBAFromTransaction(invoice.getAccountId(), transInvoiceDao);
                 BigDecimal cbaAdjAmount = BigDecimal.ZERO;
                 if (accountCbaAvailable.compareTo(BigDecimal.ZERO) > 0) {
-                    cbaAdjAmount = (requestedPositiveAmount.compareTo(accountCbaAvailable) > 0) ?  accountCbaAvailable.negate() : requestedPositiveAmount.negate();
+                    cbaAdjAmount = (requestedPositiveAmount.compareTo(accountCbaAvailable) > 0) ? accountCbaAvailable.negate() : requestedPositiveAmount.negate();
                     final InvoiceItem cbaAdjItem = new CreditBalanceAdjInvoiceItem(invoice.getId(), invoice.getAccountId(), context.getCreatedDate(), cbaAdjAmount, invoice.getCurrency());
                     transInvoiceItemDao.create(cbaAdjItem, context);
                 }
                 final BigDecimal requestedPositiveAmountAfterCbaAdj = requestedPositiveAmount.add(cbaAdjAmount);
 
                 if (isInvoiceAdjusted) {
-
-                    BigDecimal maxBalanceToAdjust = (invoiceBalanceAfterRefund.compareTo(BigDecimal.ZERO) <= 0) ? BigDecimal.ZERO : invoiceBalanceAfterRefund;
-                    BigDecimal requestedPositiveAmountToAdjust = requestedPositiveAmountAfterCbaAdj.compareTo(maxBalanceToAdjust)  > 0 ? maxBalanceToAdjust : requestedPositiveAmountAfterCbaAdj;
+                    final BigDecimal maxBalanceToAdjust = (invoiceBalanceAfterRefund.compareTo(BigDecimal.ZERO) <= 0) ? BigDecimal.ZERO : invoiceBalanceAfterRefund;
+                    final BigDecimal requestedPositiveAmountToAdjust = requestedPositiveAmountAfterCbaAdj.compareTo(maxBalanceToAdjust) > 0 ? maxBalanceToAdjust : requestedPositiveAmountAfterCbaAdj;
                     if (requestedPositiveAmountToAdjust.compareTo(BigDecimal.ZERO) > 0) {
                         final InvoiceItem adjItem = new RefundAdjInvoiceItem(invoice.getId(), invoice.getAccountId(), context.getCreatedDate(), requestedPositiveAmountToAdjust.negate(), invoice.getCurrency());
                         transInvoiceItemDao.create(adjItem, context);
@@ -367,14 +352,12 @@ public class DefaultInvoiceDao implements InvoiceDao {
         });
     }
 
-
     @Override
     public InvoicePayment postChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
 
         return invoicePaymentSqlDao.inTransaction(new Transaction<InvoicePayment, InvoicePaymentSqlDao>() {
             @Override
             public InvoicePayment inTransaction(final InvoicePaymentSqlDao transactional, final TransactionStatus status) throws Exception {
-
                 final BigDecimal maxChargedBackAmount = getRemainingAmountPaidFromTransaction(invoicePaymentId, transactional);
                 final BigDecimal requestedChargedBackAmout = (amount == null) ? maxChargedBackAmount : amount;
                 if (requestedChargedBackAmout.compareTo(BigDecimal.ZERO) <= 0) {
@@ -389,7 +372,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     throw new InvoiceApiException(ErrorCode.INVOICE_PAYMENT_NOT_FOUND, invoicePaymentId.toString());
                 } else {
                     final InvoicePayment chargeBack = new DefaultInvoicePayment(UUID.randomUUID(), InvoicePaymentType.CHARGED_BACK, null,
-                            payment.getInvoiceId(), context.getCreatedDate(), requestedChargedBackAmout.negate(), payment.getCurrency(), null, payment.getId());
+                                                                                payment.getInvoiceId(), context.getCreatedDate(), requestedChargedBackAmout.negate(), payment.getCurrency(), null, payment.getId());
                     invoicePaymentSqlDao.create(chargeBack, context);
                     return chargeBack;
                 }
@@ -439,8 +422,8 @@ public class DefaultInvoiceDao implements InvoiceDao {
 
     @Override
     public InvoiceItem insertCredit(final UUID accountId, final UUID invoiceId, final BigDecimal amount,
-            final DateTime effectiveDate, final Currency currency,
-            final CallContext context) {
+                                    final DateTime effectiveDate, final Currency currency,
+                                    final CallContext context) {
 
         return invoiceSqlDao.inTransaction(new Transaction<InvoiceItem, InvoiceSqlDao>() {
             @Override
@@ -451,8 +434,9 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     transactional.create(invoiceForRefund, context);
                     invoiceIdForRefund = invoiceForRefund.getId();
                 }
+
                 final InvoiceItem credit = new CreditAdjInvoiceItem(invoiceIdForRefund, accountId, effectiveDate, amount, currency);
-                InvoiceItemSqlDao transInvoiceItemDao = transactional.become(InvoiceItemSqlDao.class);
+                final InvoiceItemSqlDao transInvoiceItemDao = transactional.become(InvoiceItemSqlDao.class);
                 transInvoiceItemDao.create(credit, context);
                 return credit;
             }
@@ -466,14 +450,14 @@ public class DefaultInvoiceDao implements InvoiceDao {
 
     private BigDecimal getAccountCBAFromTransaction(final UUID accountId, final InvoiceSqlDao transactional) {
         BigDecimal cba = BigDecimal.ZERO;
-        List<Invoice> invoices = getAllInvoicesByAccountFromTransaction(accountId, transactional);
-        for (Invoice cur : invoices) {
+        final List<Invoice> invoices = getAllInvoicesByAccountFromTransaction(accountId, transactional);
+        for (final Invoice cur : invoices) {
             cba = cba.add(cur.getCBAAmount());
         }
+
         return cba;
     }
 
-
     private void populateChildren(final Invoice invoice, final InvoiceSqlDao invoiceSqlDao) {
         getInvoiceItemsWithinTransaction(invoice, invoiceSqlDao);
         getInvoicePaymentsWithinTransaction(invoice, invoiceSqlDao);
@@ -490,14 +474,11 @@ public class DefaultInvoiceDao implements InvoiceDao {
         return invoices;
     }
 
-
     private BigDecimal getRemainingAmountPaidFromTransaction(final UUID invoicePaymentId, final InvoicePaymentSqlDao transactional) {
         final BigDecimal amount = transactional.getRemainingAmountPaid(invoicePaymentId.toString());
         return amount == null ? BigDecimal.ZERO : amount;
     }
 
-
-
     private void getInvoiceItemsWithinTransaction(final List<Invoice> invoices, final InvoiceSqlDao invoiceDao) {
         for (final Invoice invoice : invoices) {
             getInvoiceItemsWithinTransaction(invoice, invoiceDao);
@@ -525,12 +506,11 @@ public class DefaultInvoiceDao implements InvoiceDao {
         invoice.addPayments(invoicePayments);
     }
 
-    private void notifyOfFutureBillingEvents(final InvoiceSqlDao dao, final UUID accountId, final List<InvoiceItem> invoiceItems) {
+
+    private void notifyOfFutureBillingEvents(final InvoiceSqlDao dao, final UUID accountId, final int billCycleDay, final List<InvoiceItem> invoiceItems) {
         DateTime nextBCD = null;
         UUID subscriptionForNextBCD = null;
         for (final InvoiceItem item : invoiceItems) {
-
-
             if (item.getInvoiceItemType() == InvoiceItemType.RECURRING) {
                 final RecurringInvoiceItem recurringInvoiceItem = (RecurringInvoiceItem) item;
                 if ((recurringInvoiceItem.getEndDate() != null) &&
@@ -543,7 +523,13 @@ public class DefaultInvoiceDao implements InvoiceDao {
                 }
             }
         }
-        if (subscriptionForNextBCD != null) {
+        // We need to be notified if and only if the maximum end date of the invoiced recurring items is equal
+        // to the next bill cycle day.
+        // We take the maximum because we're guaranteed to have invoiced all subscriptions up until that date
+        // (and no further processing is needed).
+        // Also, we only need to get notified on the BDC. For other invoice events (e.g. phase changes),
+        // we'll be notified by entitlement.
+        if (subscriptionForNextBCD != null && nextBCD != null && nextBCD.getDayOfMonth() == billCycleDay) {
             nextBillingDatePoster.insertNextBillingNotification(dao, accountId, subscriptionForNextBCD, nextBCD);
         }
     }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index 9c2403b..1812ed1 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -31,7 +31,7 @@ import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.CallContext;
 
 public interface InvoiceDao {
-    void create(Invoice invoice, CallContext context);
+    void create(final Invoice invoice, final int billCycleDay, final CallContext context);
 
     Invoice getById(final UUID id);
 
diff --git a/invoice/src/main/java/com/ning/billing/invoice/glue/DefaultInvoiceModule.java b/invoice/src/main/java/com/ning/billing/invoice/glue/DefaultInvoiceModule.java
index 7ed75e1..1f2507b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/glue/DefaultInvoiceModule.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/glue/DefaultInvoiceModule.java
@@ -31,8 +31,6 @@ import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.invoice.api.formatters.InvoiceFormatterFactory;
 import com.ning.billing.invoice.api.invoice.DefaultInvoicePaymentApi;
 import com.ning.billing.invoice.api.migration.DefaultInvoiceMigrationApi;
-import com.ning.billing.invoice.api.test.DefaultInvoiceTestApi;
-import com.ning.billing.invoice.api.test.InvoiceTestApi;
 import com.ning.billing.invoice.api.user.DefaultInvoiceUserApi;
 import com.ning.billing.invoice.dao.DefaultInvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceDao;
@@ -44,7 +42,6 @@ import com.ning.billing.invoice.notification.EmailInvoiceNotifier;
 import com.ning.billing.invoice.notification.NextBillingDateNotifier;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
 import com.ning.billing.invoice.notification.NullInvoiceNotifier;
-import com.ning.billing.invoice.template.formatters.DefaultInvoiceFormatterFactory;
 import com.ning.billing.util.template.translation.TranslatorConfig;
 
 public class DefaultInvoiceModule extends AbstractModule implements InvoiceModule {
@@ -60,11 +57,6 @@ public class DefaultInvoiceModule extends AbstractModule implements InvoiceModul
     }
 
     @Override
-    public void installInvoiceTestApi() {
-        bind(InvoiceTestApi.class).to(DefaultInvoiceTestApi.class).asEagerSingleton();
-    }
-
-    @Override
     public void installInvoicePaymentApi() {
         bind(InvoicePaymentApi.class).to(DefaultInvoicePaymentApi.class).asEagerSingleton();
     }
@@ -120,6 +112,5 @@ public class DefaultInvoiceModule extends AbstractModule implements InvoiceModul
         installInvoiceUserApi();
         installInvoicePaymentApi();
         installInvoiceMigrationApi();
-        installInvoiceTestApi();
     }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
index 01948ba..1fdb6f7 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -172,7 +172,7 @@ public class InvoiceDispatcher {
                 }
                 outputDebugData(billingEvents, invoices);
                 if (!dryRun) {
-                    invoiceDao.create(invoice, context);
+                    invoiceDao.create(invoice, account.getBillCycleDay(), context);
 
                     final List<InvoiceItem> fixedPriceInvoiceItems = invoice.getInvoiceItems(FixedPriceInvoiceItem.class);
                     final List<InvoiceItem> recurringInvoiceItems = invoice.getInvoiceItems(RecurringInvoiceItem.class);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index 310b24b..a81485f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -46,7 +46,7 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void create(final Invoice invoice, final CallContext context) {
+    public void create(final Invoice invoice, final int billCycleDay, final CallContext context) {
         synchronized (monitor) {
             invoices.put(invoice.getId(), invoice);
         }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
index 626cb2f..87978ab 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
@@ -76,7 +76,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final Invoice invoice = new DefaultInvoice(accountId, clock.getUTCNow(), clock.getUTCNow(), Currency.USD);
         final DateTime invoiceDate = invoice.getInvoiceDate();
 
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
 
         final List<Invoice> invoices = invoiceDao.getInvoicesByAccount(accountId);
         assertNotNull(invoices);
@@ -102,7 +102,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                 new BigDecimal("21.00"), new BigDecimal("7.00"), Currency.USD);
 
         invoice.addInvoiceItem(invoiceItem);
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
 
         final Invoice savedInvoice = invoiceDao.getById(invoiceId);
         assertNotNull(savedInvoice);
@@ -139,7 +139,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final DateTime paymentDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
         final BigDecimal paymentAmount = new BigDecimal("14.0");
 
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
         invoiceDao.notifyOfPayment(new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoice.getId(), paymentDate, paymentAmount, Currency.USD), context);
 
         invoice = invoiceDao.getById(invoice.getId());
@@ -156,7 +156,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final DateTime paymentDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
 
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
         invoiceDao.notifyOfPayment(new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice.getId(), paymentDate, invoice.getBalance(), Currency.USD), context);
         invoice = invoiceDao.getById(invoice.getId());
         assertEquals(invoice.getLastPaymentDate().compareTo(paymentDate), 0);
@@ -180,7 +180,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -205,7 +205,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -256,7 +256,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -281,7 +281,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -332,7 +332,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -373,7 +373,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -422,11 +422,11 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID accountId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime targetDate2 = new DateTime(2011, 12, 6, 0, 0, 0, 0);
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate2, Currency.USD);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
 
         List<Invoice> invoices;
@@ -452,7 +452,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
         final DateTime endDate = startDate.plusMonths(1);
@@ -483,7 +483,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
         final DateTime endDate = startDate.plusMonths(1);
@@ -508,7 +508,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
         final DateTime endDate = startDate.plusMonths(1);
@@ -533,7 +533,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID accountId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final BigDecimal payment1 = new BigDecimal("48.0");
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice1.getId(), new DateTime(), payment1, Currency.USD);
@@ -559,7 +559,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
         final DateTime endDate = startDate.plusMonths(1);
@@ -623,12 +623,11 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
 
     private void testAccountBalanceWithRefundAndCBAInternal(boolean withAdjustment, final BigDecimal refundAmount, final BigDecimal expectedFinalBalance) throws InvoiceApiException {
-
         final UUID accountId = UUID.randomUUID();
         final UUID bundleId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
         final DateTime endDate = startDate.plusMonths(1);
@@ -695,7 +694,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
         final DateTime endDate = startDate.plusMonths(1);
@@ -760,7 +759,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // NEXT RECURRING on invoice 2
 
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1.plusMonths(1), Currency.USD);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
 
         final RecurringInvoiceItem nextItem = new RecurringInvoiceItem(invoice2.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test bla", startDate.plusMonths(1),
@@ -788,7 +787,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
         final DateTime endDate = startDate.plusMonths(1);
@@ -818,7 +817,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final DateTime targetDate2 = new DateTime(2011, 7, 1, 0, 0, 0, 0);
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate2, Currency.USD);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
         final DateTime startDate2 = new DateTime(2011, 6, 1, 0, 0, 0, 0);
         final DateTime endDate2 = startDate2.plusMonths(3);
@@ -888,8 +887,8 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice2.getBalance(), FIVE);
         invoiceList.add(invoice2);
 
-        invoiceDao.create(invoice1, context);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
         final Invoice savedInvoice1 = invoiceDao.getById(invoice1.getId());
         assertEquals(savedInvoice1.getBalance(), ZERO);
@@ -963,7 +962,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final List<Invoice> invoiceList = new ArrayList<Invoice>();
         invoiceList.add(invoice1);
 
-        //invoiceDao.create(invoice1, context);
+        //invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
 
         final DateTime effectiveDate2 = effectiveDate1.plusDays(30);
         final BillingEvent event2 = createMockBillingEvent(null, subscription, effectiveDate2, plan, phase2, null,
@@ -978,7 +977,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         invoiceList.add(invoice2);
 
-        //invoiceDao.create(invoice2, context);
+        //invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
 
         final DateTime effectiveDate3 = effectiveDate2.plusMonths(1);
         final Invoice invoice3 = generator.generateInvoice(accountId, events, invoiceList, effectiveDate3, Currency.USD);
@@ -986,7 +985,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice3.getNumberOfItems(), 1);
         assertEquals(invoice3.getBalance().compareTo(cheapAmount), 0);
 
-        //invoiceDao.create(invoice3, context);
+        //invoiceDao.create(invoice3, invoice3.getTargetDate().getDayOfMonth(), context);
     }
 
     @Test(groups = {"slow"})
@@ -1031,7 +1030,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice.getNumberOfItems(), 2);
         assertEquals(invoice.getBalance().compareTo(cheapAmount), 0);
 
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
         final Invoice savedInvoice = invoiceDao.getById(invoice.getId());
 
         assertNotNull(savedInvoice);
@@ -1067,7 +1066,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         Invoice invoice1 = generator.generateInvoice(UUID.randomUUID(), events, invoices, targetDate1, Currency.USD);
         invoices.add(invoice1);
-        invoiceDao.create(invoice1, context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
         invoice1 = invoiceDao.getById(invoice1.getId());
         assertNotNull(invoice1.getInvoiceNumber());
 
@@ -1077,7 +1076,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                 "testEvent2", 2L, SubscriptionTransitionType.CHANGE);
         events.add(event2);
         Invoice invoice2 = generator.generateInvoice(UUID.randomUUID(), events, invoices, targetDate2, Currency.USD);
-        invoiceDao.create(invoice2, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
         invoice2 = invoiceDao.getById(invoice2.getId());
         assertNotNull(invoice2.getInvoiceNumber());
     }
@@ -1104,7 +1103,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         events.add(event1);
 
         final Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, targetDate1, Currency.USD);
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
         invoiceDao.setWrittenOff(invoice.getId(), context);
 
         final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
@@ -1135,7 +1134,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         events.add(event1);
 
         final Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, targetDate1, Currency.USD);
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
         invoiceDao.setWrittenOff(invoice.getId(), context);
 
         final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
index 931d0ae..78bbdd6 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
@@ -114,7 +114,7 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
         final DateTime targetDate = new DateTime(2011, 5, 23, 0, 0, 0, 0);
         final DefaultInvoice invoice = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
 
-        invoiceDao.create(invoice, context);
+        invoiceDao.create(invoice, targetDate.getDayOfMonth(), context);
 
         final UUID invoiceId = invoice.getId();
         final DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java b/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java
index b46edc7..378e50f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.Test;
@@ -71,7 +72,6 @@ import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
 public class TestDefaultInvoiceGenerator extends InvoicingTestBase {
-
     private static final Logger log = LoggerFactory.getLogger(TestDefaultInvoiceGenerator.class);
 
     private final Clock clock = new ClockMock();
@@ -79,8 +79,6 @@ public class TestDefaultInvoiceGenerator extends InvoicingTestBase {
     private final InvoiceGenerator generator;
 
     public TestDefaultInvoiceGenerator() {
-        super();
-
         final Clock clock = new DefaultClock();
         final InvoiceConfig invoiceConfig = new InvoiceConfig() {
             @Override
@@ -497,8 +495,8 @@ public class TestDefaultInvoiceGenerator extends InvoicingTestBase {
         final Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, targetDate, Currency.USD);
         final RecurringInvoiceItem item = (RecurringInvoiceItem) invoice.getInvoiceItems().get(0);
 
-        // end date of the invoice item should be equal to exactly one month later
-        assertEquals(item.getEndDate().compareTo(startDate.plusMonths(1)), 0);
+        // end date of the invoice item should be equal to exactly one month later (rounded)
+        assertDatesEqualRounded(item.getEndDate(), startDate.plusMonths(1));
     }
 
     @Test(groups = {"fast"})
@@ -632,7 +630,7 @@ public class TestDefaultInvoiceGenerator extends InvoicingTestBase {
         final PlanPhase phase3 = createMockMonthlyPlanPhase(new BigDecimal("19.95"), null, PhaseType.EVERGREEN);
 
         // set up billing events
-        final DateTime creationDate = new DateTime(2012, 3, 6, 21, 36, 18, 896);
+        final DateTime creationDate = new DateTime(2012, 3, 6, 21, 36, 18, 896, DateTimeZone.UTC);
         events.add(createBillingEvent(subscriptionId, creationDate, plan1, phase1, BILL_CYCLE_DAY));
 
         // trialPhaseEndDate = 2012/4/5
@@ -654,7 +652,7 @@ public class TestDefaultInvoiceGenerator extends InvoicingTestBase {
         final Invoice invoice2 = generator.generateInvoice(accountId, events, invoiceList, trialPhaseEndDate, Currency.USD);
         assertNotNull(invoice2);
         assertEquals(invoice2.getNumberOfItems(), 1);
-        assertEquals(invoice2.getInvoiceItems().get(0).getStartDate().compareTo(trialPhaseEndDate), 0);
+        assertDatesEqualRounded(invoice2.getInvoiceItems().get(0).getStartDate(), trialPhaseEndDate);
         assertEquals(invoice2.getBalance().compareTo(new BigDecimal("3.21")), 0);
 
         invoiceList.add(invoice2);
@@ -662,7 +660,7 @@ public class TestDefaultInvoiceGenerator extends InvoicingTestBase {
         final Invoice invoice3 = generator.generateInvoice(accountId, events, invoiceList, targetDate, Currency.USD);
         assertNotNull(invoice3);
         assertEquals(invoice3.getNumberOfItems(), 1);
-        assertEquals(invoice3.getInvoiceItems().get(0).getStartDate().compareTo(targetDate), 0);
+        assertDatesEqualRounded(invoice3.getInvoiceItems().get(0).getStartDate(), targetDate);
         assertEquals(invoice3.getBalance().compareTo(DISCOUNT_PRICE), 0);
 
         invoiceList.add(invoice3);
@@ -1007,4 +1005,9 @@ public class TestDefaultInvoiceGenerator extends InvoicingTestBase {
         log.info("--------------------  END DETAIL ----------------------");
     }
 
+    private void assertDatesEqualRounded(final DateTime date1, final DateTime date2) {
+        assertEquals(date1.toDateTime(DateTimeZone.UTC).getDayOfMonth(), date2.toDateTime(DateTimeZone.UTC).getDayOfMonth());
+        assertEquals(date1.toDateTime(DateTimeZone.UTC).getMonthOfYear(), date2.toDateTime(DateTimeZone.UTC).getMonthOfYear());
+        assertEquals(date1.toDateTime(DateTimeZone.UTC).getYear(), date2.toDateTime(DateTimeZone.UTC).getYear());
+    }
 }
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 a317cad..e4bf810 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
@@ -25,8 +25,6 @@ import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.catalog.glue.CatalogModule;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.invoice.api.InvoiceNotifier;
-import com.ning.billing.invoice.api.test.DefaultInvoiceTestApi;
-import com.ning.billing.invoice.api.test.InvoiceTestApi;
 import com.ning.billing.invoice.dao.InvoiceItemSqlDao;
 import com.ning.billing.invoice.dao.InvoicePaymentSqlDao;
 import com.ning.billing.invoice.notification.MockNextBillingDateNotifier;
@@ -117,7 +115,6 @@ public class InvoiceModuleWithEmbeddedDb extends DefaultInvoiceModule {
 
         super.configure();
 
-        bind(InvoiceTestApi.class).to(DefaultInvoiceTestApi.class).asEagerSingleton();
         install(new BusModule());
         install(new TemplateModule());
 
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
index bfa2379..9949110 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
@@ -23,7 +23,6 @@ import com.ning.billing.config.NotificationConfig;
 import com.ning.billing.util.clock.Clock;
 
 public class DefaultNotificationQueueService extends NotificationQueueServiceBase {
-
     private final IDBI dbi;
 
     @Inject
@@ -34,7 +33,8 @@ public class DefaultNotificationQueueService extends NotificationQueueServiceBas
 
     @Override
     protected NotificationQueue createNotificationQueueInternal(final String svcName,
-                                                                final String queueName, final NotificationQueueHandler handler,
+                                                                final String queueName,
+                                                                final NotificationQueueHandler handler,
                                                                 final NotificationConfig config) {
         return new DefaultNotificationQueue(dbi, clock, svcName, queueName, handler, config);
     }
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
index fcc8c08..e26dd6a 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
@@ -44,8 +44,7 @@ public abstract class NotificationQueueBase extends PersistentQueueBase implemen
     private final NotificationConfig config;
     private final Clock clock;
     private final String hostname;
-
-    private AtomicLong nbProcessedEvents;
+    private final AtomicLong nbProcessedEvents;
 
     // Package visibility on purpose
     NotificationQueueBase(final Clock clock, final String svcName, final String queueName, final NotificationQueueHandler handler, final NotificationConfig config) {
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
index 03aed2c..f39fc46 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
@@ -31,7 +31,6 @@ import com.ning.billing.config.NotificationConfig;
 import com.ning.billing.util.clock.Clock;
 
 public abstract class NotificationQueueServiceBase implements NotificationQueueService {
-
     protected final Logger log = LoggerFactory.getLogger(DefaultNotificationQueueService.class);
 
     protected final Clock clock;
@@ -44,10 +43,10 @@ public abstract class NotificationQueueServiceBase implements NotificationQueueS
         this.queues = new TreeMap<String, NotificationQueue>();
     }
 
-
     @Override
     public NotificationQueue createNotificationQueue(final String svcName,
-                                                     final String queueName, final NotificationQueueHandler handler,
+                                                     final String queueName,
+                                                     final NotificationQueueHandler handler,
                                                      final NotificationConfig config) throws NotificationQueueAlreadyExists {
         if (svcName == null || queueName == null || handler == null || config == null) {
             throw new RuntimeException("Need to specify all parameters");
@@ -71,7 +70,7 @@ public abstract class NotificationQueueServiceBase implements NotificationQueueS
     public NotificationQueue getNotificationQueue(final String svcName,
                                                   final String queueName) throws NoSuchNotificationQueue {
 
-        NotificationQueue result = null;
+        NotificationQueue result;
         final String compositeName = getCompositeName(svcName, queueName);
         synchronized (queues) {
             result = queues.get(compositeName);
@@ -83,7 +82,6 @@ public abstract class NotificationQueueServiceBase implements NotificationQueueS
         return result;
     }
 
-
     public void deleteNotificationQueue(final String svcName, final String queueName)
             throws NoSuchNotificationQueue {
         final String compositeName = getCompositeName(svcName, queueName);
@@ -97,7 +95,6 @@ public abstract class NotificationQueueServiceBase implements NotificationQueueS
         }
     }
 
-
     //
     // Test ONLY
     //
@@ -144,8 +141,16 @@ public abstract class NotificationQueueServiceBase implements NotificationQueueS
                                                                          String queueName, NotificationQueueHandler handler,
                                                                          NotificationConfig config);
 
-
     public static String getCompositeName(final String svcName, final String queueName) {
         return svcName + ":" + queueName;
     }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("NotificationQueueServiceBase");
+        sb.append("{queues=").append(queues);
+        sb.append('}');
+        return sb.toString();
+    }
 }
diff --git a/util/src/test/java/com/ning/billing/mock/glue/MockInvoiceModule.java b/util/src/test/java/com/ning/billing/mock/glue/MockInvoiceModule.java
index 90e41c4..6fd3f57 100644
--- a/util/src/test/java/com/ning/billing/mock/glue/MockInvoiceModule.java
+++ b/util/src/test/java/com/ning/billing/mock/glue/MockInvoiceModule.java
@@ -21,11 +21,9 @@ import com.ning.billing.glue.InvoiceModule;
 import com.ning.billing.invoice.api.InvoiceMigrationApi;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.api.InvoiceUserApi;
-import com.ning.billing.invoice.api.test.InvoiceTestApi;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 
 public class MockInvoiceModule extends AbstractModule implements InvoiceModule {
-
     @Override
     public void installInvoiceUserApi() {
         bind(InvoiceUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(InvoiceUserApi.class));
@@ -42,15 +40,9 @@ public class MockInvoiceModule extends AbstractModule implements InvoiceModule {
     }
 
     @Override
-    public void installInvoiceTestApi() {
-        bind(InvoiceTestApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(InvoiceTestApi.class));
-    }
-
-    @Override
     protected void configure() {
         installInvoiceUserApi();
         installInvoicePaymentApi();
         installInvoiceMigrationApi();
-        installInvoiceTestApi();
     }
 }