killbill-aplcache

invoice: first pass at updating invoice to the new model Signed-off-by:

11/10/2012 1:44:42 AM

Changes

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 5a85244..3acde65 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
@@ -63,9 +63,14 @@ import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.user.ApiEventType;
-import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.user.DefaultInvoiceCreationEvent;
 import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceItemModelDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
+import com.ning.billing.invoice.dao.InvoiceModelDaoHelper;
+import com.ning.billing.invoice.dao.InvoicePaymentModelDao;
 import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.mock.MockAccountBuilder;
@@ -84,6 +89,9 @@ import com.ning.billing.util.events.InvoiceCreationInternalEvent;
 import com.ning.billing.util.events.PaymentInfoInternalEvent;
 import com.ning.billing.util.svcsapi.bus.InternalBus;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
 import static org.testng.Assert.fail;
@@ -229,8 +237,25 @@ public class TestAnalyticsService extends AnalyticsTestSuiteWithEmbeddedDB {
                                                                             INVOICE_AMOUNT, ACCOUNT_CURRENCY);
         invoice.addInvoiceItem(invoiceItem);
 
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        final List<Invoice> invoices = invoiceDao.getInvoicesByAccount(account.getId(), internalCallContext);
+        final InvoiceModelDao invoiceModelDao = new InvoiceModelDao(invoice);
+        final List<InvoiceItemModelDao> invoiceItemModelDaos = ImmutableList.<InvoiceItemModelDao>copyOf(Collections2.transform(invoice.getInvoiceItems(),
+                                                                                                                                new Function<InvoiceItem, InvoiceItemModelDao>() {
+                                                                                                                                    @Override
+                                                                                                                                    public InvoiceItemModelDao apply(final InvoiceItem input) {
+                                                                                                                                        return new InvoiceItemModelDao(input);
+                                                                                                                                    }
+                                                                                                                                }));
+        // Not really needed, there shouldn't be any payment at this stage
+        final List<InvoicePaymentModelDao> invoicePaymentModelDaos = ImmutableList.<InvoicePaymentModelDao>copyOf(Collections2.transform(invoice.getPayments(),
+                                                                                                                                         new Function<InvoicePayment, InvoicePaymentModelDao>() {
+                                                                                                                                             @Override
+                                                                                                                                             public InvoicePaymentModelDao apply(final InvoicePayment input) {
+                                                                                                                                                 return new InvoicePaymentModelDao(input);
+                                                                                                                                             }
+                                                                                                                                         }));
+
+        invoiceDao.createInvoice(invoiceModelDao, invoiceItemModelDaos, invoicePaymentModelDaos, true, internalCallContext);
+        final List<InvoiceModelDao> invoices = invoiceDao.getInvoicesByAccount(account.getId(), internalCallContext);
         Assert.assertEquals(invoices.size(), 1);
         Assert.assertEquals(invoices.get(0).getInvoiceItems().size(), 1);
 
@@ -238,7 +263,7 @@ public class TestAnalyticsService extends AnalyticsTestSuiteWithEmbeddedDB {
         invoiceCreationNotification = new DefaultInvoiceCreationEvent(invoice.getId(), account.getId(),
                                                                       INVOICE_AMOUNT, ACCOUNT_CURRENCY, null, 1L, 1L);
 
-        paymentInfoNotification = new DefaultPaymentInfoEvent(account.getId(), invoices.get(0).getId(), null, invoices.get(0).getBalance(), -1,
+        paymentInfoNotification = new DefaultPaymentInfoEvent(account.getId(), invoices.get(0).getId(), null, InvoiceModelDaoHelper.getBalance(invoices.get(0)), -1,
                                                               PaymentStatus.UNKNOWN, null, null, null, clock.getUTCNow(), 1L, 1L);
 
         final PaymentModelDao paymentInfo = new PaymentModelDao(account.getId(), invoice.getId(), account.getPaymentMethodId(),
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index b694ab2..5b8e22f 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -200,6 +200,7 @@ public enum ErrorCode {
     INVOICE_NO_SUCH_EXTERNAL_CHARGE(4014, "External charge item for id %s does not exist"),
     EXTERNAL_CHARGE_AMOUNT_INVALID(4015, "External charge amount %s should be strictly positive"),
     INVOICE_WOULD_BE_NEGATIVE(4016, "Cannot execute operation, the invoice balance would become negative"),
+    INVOICE_ALREADY_EXISTS(4017, "The invoice already exists %s"),
 
     /*
      *
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java
index c51f344..f6209c3 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java
@@ -19,28 +19,28 @@ package com.ning.billing.invoice.api.invoice;
 
 import java.math.BigDecimal;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
-import org.joda.time.DateTime;
 import org.skife.jdbi.v2.exceptions.TransactionFailedException;
 
-import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
+import com.ning.billing.invoice.dao.InvoicePaymentModelDao;
+import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.DefaultInvoicePayment;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
-import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.callcontext.TenantContext;
 
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
 public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
@@ -58,22 +58,34 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
 
     @Override
     public List<Invoice> getAllInvoicesByAccount(final UUID accountId, final TenantContext context) {
-        return dao.getAllInvoicesByAccount(accountId, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<Invoice>copyOf(Collections2.transform(dao.getAllInvoicesByAccount(accountId, internalCallContextFactory.createInternalTenantContext(context)),
+                                                                    new Function<InvoiceModelDao, Invoice>() {
+                                                                        @Override
+                                                                        public Invoice apply(final InvoiceModelDao input) {
+                                                                            return new DefaultInvoice(input);
+                                                                        }
+                                                                    }));
     }
 
     @Override
     public Invoice getInvoice(final UUID invoiceId, final TenantContext context) throws InvoiceApiException {
-        return dao.getById(invoiceId, internalCallContextFactory.createInternalTenantContext(context));
+        return new DefaultInvoice(dao.getById(invoiceId, internalCallContextFactory.createInternalTenantContext(context)));
     }
 
     @Override
     public List<InvoicePayment> getInvoicePayments(final UUID paymentId, final TenantContext context) {
-        return dao.getInvoicePayments(paymentId, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<InvoicePayment>copyOf(Collections2.transform(dao.getInvoicePayments(paymentId, internalCallContextFactory.createInternalTenantContext(context)),
+                                                                           new Function<InvoicePaymentModelDao, InvoicePayment>() {
+                                                                               @Override
+                                                                               public InvoicePayment apply(final InvoicePaymentModelDao input) {
+                                                                                   return new DefaultInvoicePayment(input);
+                                                                               }
+                                                                           }));
     }
 
     @Override
     public InvoicePayment getInvoicePaymentForAttempt(final UUID paymentId, final TenantContext context) {
-        final List<InvoicePayment> invoicePayments = dao.getInvoicePayments(paymentId, internalCallContextFactory.createInternalTenantContext(context));
+        final List<InvoicePayment> invoicePayments = getInvoicePayments(paymentId, context);
         if (invoicePayments.size() == 0) {
             return null;
         }
@@ -85,7 +97,6 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
         }).iterator().next();
     }
 
-
     @Override
     public BigDecimal getRemainingAmountPaid(final UUID invoicePaymentId, final TenantContext context) {
         return dao.getRemainingAmountPaid(invoicePaymentId, internalCallContextFactory.createInternalTenantContext(context));
@@ -93,17 +104,29 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
 
     @Override
     public List<InvoicePayment> getChargebacksByAccountId(final UUID accountId, final TenantContext context) {
-        return dao.getChargebacksByAccountId(accountId, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<InvoicePayment>copyOf(Collections2.transform(dao.getChargebacksByAccountId(accountId, internalCallContextFactory.createInternalTenantContext(context)),
+                                                                           new Function<InvoicePaymentModelDao, InvoicePayment>() {
+                                                                               @Override
+                                                                               public InvoicePayment apply(final InvoicePaymentModelDao input) {
+                                                                                   return new DefaultInvoicePayment(input);
+                                                                               }
+                                                                           }));
     }
 
     @Override
     public List<InvoicePayment> getChargebacksByPaymentId(final UUID paymentId, final TenantContext context) {
-        return dao.getChargebacksByPaymentId(paymentId, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<InvoicePayment>copyOf(Collections2.transform(dao.getChargebacksByPaymentId(paymentId, internalCallContextFactory.createInternalTenantContext(context)),
+                                                                           new Function<InvoicePaymentModelDao, InvoicePayment>() {
+                                                                               @Override
+                                                                               public InvoicePayment apply(final InvoicePaymentModelDao input) {
+                                                                                   return new DefaultInvoicePayment(input);
+                                                                               }
+                                                                           }));
     }
 
     @Override
     public InvoicePayment getChargebackById(final UUID chargebackId, final TenantContext context) throws InvoiceApiException {
-        return dao.getChargebackById(chargebackId, internalCallContextFactory.createInternalTenantContext(context));
+        return new DefaultInvoicePayment(dao.getChargebackById(chargebackId, internalCallContextFactory.createInternalTenantContext(context)));
     }
 
     @Override
@@ -111,7 +134,6 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
         return dao.getAccountIdFromInvoicePaymentId(invoicePaymentId, internalCallContextFactory.createInternalTenantContext(context));
     }
 
-
     @Override
     public InvoicePayment createChargeback(final UUID invoicePaymentId, final CallContext context) throws InvoiceApiException {
         return createChargeback(invoicePaymentId, null, context);
@@ -125,7 +147,7 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
             public InvoicePayment doHandle() throws InvoiceApiException {
                 // Retrieve the account id for the internal call context
                 final UUID accountId = dao.getAccountIdFromInvoicePaymentId(invoicePaymentId, internalCallContextFactory.createInternalTenantContext(context));
-                return dao.postChargeback(invoicePaymentId, amount, internalCallContextFactory.createInternalCallContext(accountId, context));
+                return new DefaultInvoicePayment(dao.postChargeback(invoicePaymentId, amount, internalCallContextFactory.createInternalCallContext(accountId, context)));
             }
         });
     }
@@ -134,11 +156,13 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
     // Allow to safely catch TransactionFailedException exceptions and rethrow the correct InvoiceApiException exception
     //
     private interface WithInvoiceApiExceptionCallback<T> {
+
         public T doHandle() throws InvoiceApiException;
     }
 
     private static final class WithInvoiceApiException<T> {
-        public T executeAndThrow(final WithInvoiceApiExceptionCallback<T> callback) throws InvoiceApiException  {
+
+        public T executeAndThrow(final WithInvoiceApiExceptionCallback<T> callback) throws InvoiceApiException {
 
             try {
                 return callback.doHandle();
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 be2e650..978da8d 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
@@ -23,32 +23,35 @@ import org.joda.time.LocalDate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.catalog.api.MigrationPlan;
+import com.ning.billing.invoice.api.InvoiceItemType;
 import com.ning.billing.invoice.api.InvoiceMigrationApi;
-import com.ning.billing.invoice.dao.AuditedInvoiceDao;
-import com.ning.billing.invoice.model.MigrationInvoiceItem;
+import com.ning.billing.invoice.dao.DefaultInvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceItemModelDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
+import com.ning.billing.invoice.dao.InvoicePaymentModelDao;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
 public class DefaultInvoiceMigrationApi implements InvoiceMigrationApi {
+
     private static final Logger log = LoggerFactory.getLogger(DefaultInvoiceMigrationApi.class);
 
     private final AccountInternalApi accountUserApi;
-    private final AuditedInvoiceDao dao;
+    private final DefaultInvoiceDao dao;
     private final Clock clock;
     private final InternalCallContextFactory internalCallContextFactory;
 
     @Inject
     public DefaultInvoiceMigrationApi(final AccountInternalApi accountUserApi,
-                                      final AuditedInvoiceDao dao,
+                                      final DefaultInvoiceDao dao,
                                       final Clock clock,
                                       final InternalCallContextFactory internalCallContextFactory) {
         this.accountUserApi = accountUserApi;
@@ -59,19 +62,20 @@ public class DefaultInvoiceMigrationApi implements InvoiceMigrationApi {
 
     @Override
     public UUID createMigrationInvoice(final UUID accountId, final LocalDate targetDate, final BigDecimal balance, final Currency currency, final CallContext context) {
-        final Account account;
         try {
-            account = accountUserApi.getAccountById(accountId, internalCallContextFactory.createInternalTenantContext(context));
+            accountUserApi.getAccountById(accountId, internalCallContextFactory.createInternalTenantContext(context));
         } catch (AccountApiException e) {
             log.warn("Unable to find account for id {}", accountId);
             return null;
         }
 
-        final Invoice migrationInvoice = new MigrationInvoice(accountId, clock.getUTCToday(), targetDate, currency);
-        final InvoiceItem migrationInvoiceItem = new MigrationInvoiceItem(migrationInvoice.getId(), accountId, targetDate, balance, currency);
-        migrationInvoice.addInvoiceItem(migrationInvoiceItem);
+        final InvoiceModelDao migrationInvoice = new InvoiceModelDao(accountId, clock.getUTCToday(), targetDate, currency, true);
+        final InvoiceItemModelDao migrationInvoiceItem = new InvoiceItemModelDao(InvoiceItemType.FIXED, migrationInvoice.getId(), accountId, null, null,
+                                                                                 MigrationPlan.MIGRATION_PLAN_NAME, MigrationPlan.MIGRATION_PLAN_PHASE_NAME,
+                                                                                 targetDate, null, balance, null, currency, null);
+        dao.createInvoice(migrationInvoice, ImmutableList.<InvoiceItemModelDao>of(migrationInvoiceItem),
+                          ImmutableList.<InvoicePaymentModelDao>of(), true, internalCallContextFactory.createInternalCallContext(accountId, context));
 
-        dao.create(migrationInvoice, account.getBillCycleDay().getDayOfMonthUTC(), true, internalCallContextFactory.createInternalCallContext(accountId, context));
         return migrationInvoice.getId();
     }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
index ace0d51..325006b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
@@ -18,7 +18,6 @@ package com.ning.billing.invoice.api.svcs;
 
 import java.math.BigDecimal;
 import java.util.Collection;
-import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
@@ -35,11 +34,15 @@ import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
 import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
+import com.ning.billing.invoice.dao.InvoicePaymentModelDao;
+import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.DefaultInvoicePayment;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 
@@ -56,17 +59,27 @@ public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
 
     @Override
     public Invoice getInvoiceById(final UUID invoiceId, final InternalTenantContext context) throws InvoiceApiException {
-        return dao.getById(invoiceId, context);
+        return new DefaultInvoice(dao.getById(invoiceId, context));
     }
 
     @Override
     public Collection<Invoice> getUnpaidInvoicesByAccountId(final UUID accountId, final LocalDate upToDate, final InternalTenantContext context) {
-        return dao.getUnpaidInvoicesByAccountId(accountId, upToDate, context);
+        return Collections2.transform(dao.getUnpaidInvoicesByAccountId(accountId, upToDate, context), new Function<InvoiceModelDao, Invoice>() {
+            @Override
+            public Invoice apply(final InvoiceModelDao input) {
+                return new DefaultInvoice(input);
+            }
+        });
     }
 
     @Override
     public Collection<Invoice> getInvoicesByAccountId(final UUID accountId, final InternalTenantContext context) {
-        return dao.getInvoicesByAccount(accountId, context);
+        return Collections2.transform(dao.getInvoicesByAccount(accountId, context), new Function<InvoiceModelDao, Invoice>() {
+            @Override
+            public Invoice apply(final InvoiceModelDao input) {
+                return new DefaultInvoice(input);
+            }
+        });
     }
 
     @Override
@@ -77,17 +90,22 @@ public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
     @Override
     public void notifyOfPayment(final UUID invoiceId, final BigDecimal amount, final Currency currency, final UUID paymentId, final DateTime paymentDate, final InternalCallContext context) throws InvoiceApiException {
         final InvoicePayment invoicePayment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoiceId, paymentDate, amount, currency);
-        dao.notifyOfPayment(invoicePayment, context);
+        notifyOfPayment(invoicePayment, context);
     }
 
     @Override
     public void notifyOfPayment(final InvoicePayment invoicePayment, final InternalCallContext context) throws InvoiceApiException {
-        dao.notifyOfPayment(invoicePayment, context);
+        dao.notifyOfPayment(new InvoicePaymentModelDao(invoicePayment), context);
     }
 
     @Override
     public InvoicePayment getInvoicePaymentForAttempt(final UUID paymentId, final InternalTenantContext context) throws InvoiceApiException {
-        final List<InvoicePayment> invoicePayments = dao.getInvoicePayments(paymentId, context);
+        final Collection<InvoicePayment> invoicePayments = Collections2.transform(dao.getInvoicePayments(paymentId, context), new Function<InvoicePaymentModelDao, InvoicePayment>() {
+            @Override
+            public InvoicePayment apply(final InvoicePaymentModelDao input) {
+                return new DefaultInvoicePayment(input);
+            }
+        });
         if (invoicePayments.size() == 0) {
             return null;
         }
@@ -102,7 +120,7 @@ public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
     @Override
     public Invoice getInvoiceForPaymentId(final UUID paymentId, final InternalTenantContext context) throws InvoiceApiException {
         final UUID invoiceIdStr = dao.getInvoiceIdByPaymentId(paymentId, context);
-        return invoiceIdStr == null ? null : dao.getById(invoiceIdStr, context);
+        return invoiceIdStr == null ? null : new DefaultInvoice(dao.getById(invoiceIdStr, context));
     }
 
     @Override
@@ -115,10 +133,15 @@ public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
                     throw new InvoiceApiException(ErrorCode.PAYMENT_REFUND_AMOUNT_NEGATIVE_OR_NULL);
                 }
 
-                final List<InvoicePayment> invoicePayments = dao.getInvoicePayments(paymentId, context);
-                final UUID accountId = dao.getAccountIdFromInvoicePaymentId(invoicePayments.get(0).getId(), context);
+                final Collection<InvoicePayment> invoicePayments = Collections2.transform(dao.getInvoicePayments(paymentId, context), new Function<InvoicePaymentModelDao, InvoicePayment>() {
+                    @Override
+                    public InvoicePayment apply(final InvoicePaymentModelDao input) {
+                        return new DefaultInvoicePayment(input);
+                    }
+                });
+                final UUID accountId = dao.getAccountIdFromInvoicePaymentId(invoicePayments.iterator().next().getId(), context);
 
-                return dao.createRefund(paymentId, amount, isInvoiceAdjusted, invoiceItemIdsWithAmounts, paymentCookieId, context);
+                return new DefaultInvoicePayment(dao.createRefund(paymentId, amount, isInvoiceAdjusted, invoiceItemIdsWithAmounts, paymentCookieId, context));
             }
         });
     }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 71e9036..e978f2f 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -19,7 +19,6 @@ package com.ning.billing.invoice.api.user;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
 import javax.annotation.Nullable;
@@ -38,11 +37,14 @@ import com.ning.billing.invoice.InvoiceDispatcher;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceItemModelDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
 import com.ning.billing.invoice.model.CreditAdjInvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.ExternalChargeInvoiceItem;
+import com.ning.billing.invoice.model.InvoiceItemFactory;
 import com.ning.billing.invoice.template.HtmlInvoiceGenerator;
 import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.CallContext;
@@ -57,6 +59,9 @@ import com.ning.billing.util.svcsapi.bus.InternalBus.EventBusException;
 import com.ning.billing.util.tag.ControlTagType;
 import com.ning.billing.util.tag.Tag;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
 public class DefaultInvoiceUserApi implements InvoiceUserApi {
@@ -85,12 +90,24 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
 
     @Override
     public List<Invoice> getInvoicesByAccount(final UUID accountId, final TenantContext context) {
-        return dao.getInvoicesByAccount(accountId, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<Invoice>copyOf(Collections2.transform(dao.getInvoicesByAccount(accountId, internalCallContextFactory.createInternalTenantContext(context)),
+                                                                    new Function<InvoiceModelDao, Invoice>() {
+                                                                        @Override
+                                                                        public Invoice apply(final InvoiceModelDao input) {
+                                                                            return new DefaultInvoice(input);
+                                                                        }
+                                                                    }));
     }
 
     @Override
     public List<Invoice> getInvoicesByAccount(final UUID accountId, final LocalDate fromDate, final TenantContext context) {
-        return dao.getInvoicesByAccount(accountId, fromDate, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<Invoice>copyOf(Collections2.transform(dao.getInvoicesByAccount(accountId, fromDate, internalCallContextFactory.createInternalTenantContext(context)),
+                                                                    new Function<InvoiceModelDao, Invoice>() {
+                                                                        @Override
+                                                                        public Invoice apply(final InvoiceModelDao input) {
+                                                                            return new DefaultInvoice(input);
+                                                                        }
+                                                                    }));
     }
 
     @Override
@@ -107,17 +124,23 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
 
     @Override
     public Invoice getInvoice(final UUID invoiceId, final TenantContext context) throws InvoiceApiException {
-        return dao.getById(invoiceId, internalCallContextFactory.createInternalTenantContext(context));
+        return new DefaultInvoice(dao.getById(invoiceId, internalCallContextFactory.createInternalTenantContext(context)));
     }
 
     @Override
     public Invoice getInvoiceByNumber(final Integer number, final TenantContext context) throws InvoiceApiException {
-        return dao.getByNumber(number, internalCallContextFactory.createInternalTenantContext(context));
+        return new DefaultInvoice(dao.getByNumber(number, internalCallContextFactory.createInternalTenantContext(context)));
     }
 
     @Override
     public List<Invoice> getUnpaidInvoicesByAccountId(final UUID accountId, final LocalDate upToDate, final TenantContext context) {
-        return dao.getUnpaidInvoicesByAccountId(accountId, upToDate, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<Invoice>copyOf(Collections2.transform(dao.getUnpaidInvoicesByAccountId(accountId, upToDate, internalCallContextFactory.createInternalTenantContext(context)),
+                                                                    new Function<InvoiceModelDao, Invoice>() {
+                                                                        @Override
+                                                                        public Invoice apply(final InvoiceModelDao input) {
+                                                                            return new DefaultInvoice(input);
+                                                                        }
+                                                                    }));
     }
 
     @Override
@@ -149,7 +172,7 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
         tagApi.addTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), internalContext);
 
         // Retrieve the invoice for the account id
-        final Invoice invoice = dao.getById(invoiceId, internalContext);
+        final Invoice invoice = new DefaultInvoice(dao.getById(invoiceId, internalContext));
         // This is for overdue
         notifyBusOfInvoiceAdjustment(invoiceId, invoice.getAccountId(), context.getUserToken(), internalCallContextFactory.createInternalCallContext(invoice.getAccountId(), context));
     }
@@ -161,14 +184,14 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
         tagApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), internalContext);
 
         // Retrieve the invoice for the account id
-        final Invoice invoice = dao.getById(invoiceId, internalContext);
+        final Invoice invoice = new DefaultInvoice(dao.getById(invoiceId, internalContext));
         // This is for overdue
         notifyBusOfInvoiceAdjustment(invoiceId, invoice.getAccountId(), context.getUserToken(), internalCallContextFactory.createInternalCallContext(invoice.getAccountId(), context));
     }
 
     @Override
     public InvoiceItem getExternalChargeById(final UUID externalChargeId, final TenantContext context) throws InvoiceApiException {
-        final InvoiceItem externalChargeItem = dao.getExternalChargeById(externalChargeId, internalCallContextFactory.createInternalTenantContext(context));
+        final InvoiceItem externalChargeItem = InvoiceItemFactory.fromModelDao(dao.getExternalChargeById(externalChargeId, internalCallContextFactory.createInternalTenantContext(context)));
         if (externalChargeItem == null) {
             throw new InvoiceApiException(ErrorCode.INVOICE_NO_SUCH_EXTERNAL_CHARGE, externalChargeId);
         }
@@ -204,12 +227,13 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
             throw new InvoiceApiException(ErrorCode.EXTERNAL_CHARGE_AMOUNT_INVALID, amount);
         }
 
-        return dao.insertExternalCharge(accountId, invoiceId, bundleId, description, amount, effectiveDate, currency, internalCallContextFactory.createInternalCallContext(accountId, context));
+        final InvoiceItemModelDao externalCharge = dao.insertExternalCharge(accountId, invoiceId, bundleId, description, amount, effectiveDate, currency, internalCallContextFactory.createInternalCallContext(accountId, context));
+        return InvoiceItemFactory.fromModelDao(externalCharge);
     }
 
     @Override
     public InvoiceItem getCreditById(final UUID creditId, final TenantContext context) throws InvoiceApiException {
-        final InvoiceItem creditItem = dao.getCreditById(creditId, internalCallContextFactory.createInternalTenantContext(context));
+        final InvoiceItem creditItem = InvoiceItemFactory.fromModelDao(dao.getCreditById(creditId, internalCallContextFactory.createInternalTenantContext(context)));
         if (creditItem == null) {
             throw new InvoiceApiException(ErrorCode.INVOICE_NO_SUCH_CREDIT, creditId);
         }
@@ -231,7 +255,8 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
             throw new InvoiceApiException(ErrorCode.CREDIT_AMOUNT_INVALID, amount);
         }
 
-        return dao.insertCredit(accountId, invoiceId, amount, effectiveDate, currency, internalCallContextFactory.createInternalCallContext(accountId, context));
+        final InvoiceItemModelDao credit = dao.insertCredit(accountId, invoiceId, amount, effectiveDate, currency, internalCallContextFactory.createInternalCallContext(accountId, context));
+        return InvoiceItemFactory.fromModelDao(credit);
     }
 
     @Override
@@ -248,7 +273,8 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
             throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_ADJUSTMENT_AMOUNT_INVALID, amount);
         }
 
-        return dao.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItemId, effectiveDate, amount, currency, internalCallContextFactory.createInternalCallContext(accountId, context));
+        final InvoiceItemModelDao adjustment = dao.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItemId, effectiveDate, amount, currency, internalCallContextFactory.createInternalCallContext(accountId, context));
+        return InvoiceItemFactory.fromModelDao(adjustment);
     }
 
     @Override
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 f9e9b4d..1d51614 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
@@ -26,46 +26,43 @@ import javax.annotation.Nullable;
 import org.joda.time.LocalDate;
 
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 
 public interface InvoiceDao {
 
-    void create(Invoice invoice, int billCycleDayUTC, boolean isRealInvoice, InternalCallContext context);
+    void createInvoice(InvoiceModelDao invoice, List<InvoiceItemModelDao> invoiceItems,
+                       List<InvoicePaymentModelDao> invoicePayments, boolean isRealInvoice, InternalCallContext context);
 
-    Invoice getById(UUID id, InternalTenantContext context) throws InvoiceApiException;
+    InvoiceModelDao getById(UUID id, InternalTenantContext context);
 
-    Invoice getByNumber(Integer number, InternalTenantContext context) throws InvoiceApiException;
+    InvoiceModelDao getByNumber(Integer number, InternalTenantContext context) throws InvoiceApiException;
 
-    List<Invoice> get(InternalTenantContext context);
+    List<InvoiceModelDao> get(InternalTenantContext context);
 
-    List<Invoice> getInvoicesByAccount(UUID accountId, InternalTenantContext context);
+    List<InvoiceModelDao> getInvoicesByAccount(UUID accountId, InternalTenantContext context);
 
-    List<Invoice> getInvoicesByAccount(UUID accountId, LocalDate fromDate, InternalTenantContext context);
+    List<InvoiceModelDao> getInvoicesByAccount(UUID accountId, LocalDate fromDate, InternalTenantContext context);
 
-    List<Invoice> getInvoicesBySubscription(UUID subscriptionId, InternalTenantContext context);
+    List<InvoiceModelDao> getInvoicesBySubscription(UUID subscriptionId, InternalTenantContext context);
 
     UUID getInvoiceIdByPaymentId(UUID paymentId, InternalTenantContext context);
 
-    List<InvoicePayment> getInvoicePayments(UUID paymentId, InternalTenantContext context);
-
-    void notifyOfPayment(InvoicePayment invoicePayment, InternalCallContext context);
+    List<InvoicePaymentModelDao> getInvoicePayments(UUID paymentId, InternalTenantContext context);
 
     BigDecimal getAccountBalance(UUID accountId, InternalTenantContext context);
 
     public BigDecimal getAccountCBA(UUID accountId, InternalTenantContext context);
 
-    List<Invoice> getUnpaidInvoicesByAccountId(UUID accountId, @Nullable LocalDate upToDate, InternalTenantContext context);
+    List<InvoiceModelDao> getUnpaidInvoicesByAccountId(UUID accountId, @Nullable LocalDate upToDate, InternalTenantContext context);
 
     void test(InternalTenantContext context);
 
-    List<Invoice> getAllInvoicesByAccount(UUID accountId, InternalTenantContext context);
+    // Include migrated invoices
+    List<InvoiceModelDao> getAllInvoicesByAccount(UUID accountId, InternalTenantContext context);
 
-    InvoicePayment postChargeback(UUID invoicePaymentId, BigDecimal amount, InternalCallContext context) throws InvoiceApiException;
+    InvoicePaymentModelDao postChargeback(UUID invoicePaymentId, BigDecimal amount, InternalCallContext context) throws InvoiceApiException;
 
     /**
      * Create a refund.
@@ -79,18 +76,18 @@ public interface InvoiceDao {
      * @return the created invoice payment object associated with this refund
      * @throws InvoiceApiException
      */
-    InvoicePayment createRefund(UUID paymentId, BigDecimal amount, boolean isInvoiceAdjusted, Map<UUID, BigDecimal> invoiceItemIdsWithAmounts,
-                                UUID paymentCookieId, InternalCallContext context) throws InvoiceApiException;
+    InvoicePaymentModelDao createRefund(UUID paymentId, BigDecimal amount, boolean isInvoiceAdjusted, Map<UUID, BigDecimal> invoiceItemIdsWithAmounts,
+                                        UUID paymentCookieId, InternalCallContext context) throws InvoiceApiException;
 
     BigDecimal getRemainingAmountPaid(UUID invoicePaymentId, InternalTenantContext context);
 
     UUID getAccountIdFromInvoicePaymentId(UUID invoicePaymentId, InternalTenantContext context) throws InvoiceApiException;
 
-    List<InvoicePayment> getChargebacksByAccountId(UUID accountId, InternalTenantContext context);
+    List<InvoicePaymentModelDao> getChargebacksByAccountId(UUID accountId, InternalTenantContext context);
 
-    List<InvoicePayment> getChargebacksByPaymentId(UUID paymentId, InternalTenantContext context);
+    List<InvoicePaymentModelDao> getChargebacksByPaymentId(UUID paymentId, InternalTenantContext context);
 
-    InvoicePayment getChargebackById(UUID chargebackId, InternalTenantContext context) throws InvoiceApiException;
+    InvoicePaymentModelDao getChargebackById(UUID chargebackId, InternalTenantContext context) throws InvoiceApiException;
 
     /**
      * Retrieve am external charge by id.
@@ -99,7 +96,7 @@ public interface InvoiceDao {
      * @return the external charge invoice item
      * @throws InvoiceApiException
      */
-    InvoiceItem getExternalChargeById(UUID externalChargeId, InternalTenantContext context) throws InvoiceApiException;
+    InvoiceItemModelDao getExternalChargeById(UUID externalChargeId, InternalTenantContext context) throws InvoiceApiException;
 
     /**
      * Add an external charge to a given account and invoice. If invoiceId is null, a new invoice will be created.
@@ -114,8 +111,8 @@ public interface InvoiceDao {
      * @param context       the call context
      * @return the newly created external charge invoice item
      */
-    InvoiceItem insertExternalCharge(UUID accountId, @Nullable UUID invoiceId, @Nullable UUID bundleId, @Nullable String description,
-                                     BigDecimal amount, LocalDate effectiveDate, Currency currency, InternalCallContext context) throws InvoiceApiException;
+    InvoiceItemModelDao insertExternalCharge(UUID accountId, @Nullable UUID invoiceId, @Nullable UUID bundleId, @Nullable String description,
+                                             BigDecimal amount, LocalDate effectiveDate, Currency currency, InternalCallContext context) throws InvoiceApiException;
 
     /**
      * Retrieve a credit by id.
@@ -124,7 +121,7 @@ public interface InvoiceDao {
      * @return the credit invoice item
      * @throws InvoiceApiException
      */
-    InvoiceItem getCreditById(UUID creditId, InternalTenantContext context) throws InvoiceApiException;
+    InvoiceItemModelDao getCreditById(UUID creditId, InternalTenantContext context) throws InvoiceApiException;
 
     /**
      * Add a credit to a given account and invoice. If invoiceId is null, a new invoice will be created.
@@ -137,8 +134,8 @@ public interface InvoiceDao {
      * @param context       the call context
      * @return the newly created credit invoice item
      */
-    InvoiceItem insertCredit(UUID accountId, @Nullable UUID invoiceId, BigDecimal amount,
-                             LocalDate effectiveDate, Currency currency, InternalCallContext context);
+    InvoiceItemModelDao insertCredit(UUID accountId, @Nullable UUID invoiceId, BigDecimal amount,
+                                     LocalDate effectiveDate, Currency currency, InternalCallContext context);
 
     /**
      * Adjust an invoice item.
@@ -152,8 +149,8 @@ public interface InvoiceDao {
      * @param context       the call context
      * @return the newly created adjustment item
      */
-    InvoiceItem insertInvoiceItemAdjustment(UUID accountId, UUID invoiceId, UUID invoiceItemId, LocalDate effectiveDate,
-                                            @Nullable BigDecimal amount, @Nullable Currency currency, InternalCallContext context);
+    InvoiceItemModelDao insertInvoiceItemAdjustment(UUID accountId, UUID invoiceId, UUID invoiceItemId, LocalDate effectiveDate,
+                                                    @Nullable BigDecimal amount, @Nullable Currency currency, InternalCallContext context);
 
     /**
      * Delete a CBA item.
@@ -163,4 +160,6 @@ public interface InvoiceDao {
      * @param invoiceItemId the invoice item id of the cba item to delete
      */
     void deleteCBA(UUID accountId, UUID invoiceId, UUID invoiceItemId, InternalCallContext context) throws InvoiceApiException;
+
+    void notifyOfPayment(InvoicePaymentModelDao invoicePayment, InternalCallContext context);
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemModelDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemModelDao.java
new file mode 100644
index 0000000..762f369
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemModelDao.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2010-2012 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.invoice.dao;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.util.entity.EntityBase;
+
+public class InvoiceItemModelDao extends EntityBase {
+
+    private final InvoiceItemType type;
+    private final UUID invoiceId;
+    private final UUID accountId;
+    private final UUID bundleId;
+    private final UUID subscriptionId;
+    private final String planName;
+    private final String phaseName;
+    private final LocalDate startDate;
+    private final LocalDate endDate;
+    private final BigDecimal amount;
+    private final BigDecimal rate;
+    private final Currency currency;
+    private final UUID linkedItemId;
+
+    public InvoiceItemModelDao(final UUID id, @Nullable final DateTime createdDate, final InvoiceItemType type, final UUID invoiceId,
+                               final UUID accountId, final UUID bundleId, final UUID subscriptionId, final String planName,
+                               final String phaseName, final LocalDate startDate, final LocalDate endDate, final BigDecimal amount,
+                               final BigDecimal rate, final Currency currency, final UUID linkedItemId) {
+        super(id, createdDate, createdDate);
+        this.type = type;
+        this.invoiceId = invoiceId;
+        this.accountId = accountId;
+        this.bundleId = bundleId;
+        this.subscriptionId = subscriptionId;
+        this.planName = planName;
+        this.phaseName = phaseName;
+        this.startDate = startDate;
+        this.endDate = endDate;
+        this.amount = amount;
+        this.rate = rate;
+        this.currency = currency;
+        this.linkedItemId = linkedItemId;
+    }
+
+    public InvoiceItemModelDao(final InvoiceItemType type, final UUID invoiceId, final UUID accountId,
+                               final UUID bundleId, final UUID subscriptionId, final String planName,
+                               final String phaseName, final LocalDate startDate, final LocalDate endDate, final BigDecimal amount,
+                               final BigDecimal rate, final Currency currency, final UUID linkedItemId) {
+        this(UUID.randomUUID(), null, type, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName,
+             startDate, endDate, amount, rate, currency, linkedItemId);
+    }
+
+    public InvoiceItemModelDao(final InvoiceItem invoiceItem) {
+        this(invoiceItem.getInvoiceItemType(), invoiceItem.getId(), invoiceItem.getAccountId(), invoiceItem.getBundleId(),
+             invoiceItem.getSubscriptionId(), invoiceItem.getPlanName(), invoiceItem.getPhaseName(), invoiceItem.getStartDate(), invoiceItem.getEndDate(),
+             invoiceItem.getAmount(), invoiceItem.getRate(), invoiceItem.getCurrency(), invoiceItem.getLinkedItemId());
+    }
+
+    public InvoiceItemType getType() {
+        return type;
+    }
+
+    public UUID getInvoiceId() {
+        return invoiceId;
+    }
+
+    public UUID getAccountId() {
+        return accountId;
+    }
+
+    public UUID getBundleId() {
+        return bundleId;
+    }
+
+    public UUID getSubscriptionId() {
+        return subscriptionId;
+    }
+
+    public String getPlanName() {
+        return planName;
+    }
+
+    public String getPhaseName() {
+        return phaseName;
+    }
+
+    public LocalDate getStartDate() {
+        return startDate;
+    }
+
+    public LocalDate getEndDate() {
+        return endDate;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public BigDecimal getRate() {
+        return rate;
+    }
+
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    public UUID getLinkedItemId() {
+        return linkedItemId;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("InvoiceItemModelDao");
+        sb.append("{type=").append(type);
+        sb.append(", invoiceId=").append(invoiceId);
+        sb.append(", accountId=").append(accountId);
+        sb.append(", bundleId=").append(bundleId);
+        sb.append(", subscriptionId=").append(subscriptionId);
+        sb.append(", planName='").append(planName).append('\'');
+        sb.append(", phaseName='").append(phaseName).append('\'');
+        sb.append(", startDate=").append(startDate);
+        sb.append(", endDate=").append(endDate);
+        sb.append(", amount=").append(amount);
+        sb.append(", rate=").append(rate);
+        sb.append(", currency=").append(currency);
+        sb.append(", linkedItemId=").append(linkedItemId);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final InvoiceItemModelDao that = (InvoiceItemModelDao) o;
+
+        if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+            return false;
+        }
+        if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+            return false;
+        }
+        if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+            return false;
+        }
+        if (currency != that.currency) {
+            return false;
+        }
+        if (endDate != null ? !endDate.equals(that.endDate) : that.endDate != null) {
+            return false;
+        }
+        if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+            return false;
+        }
+        if (linkedItemId != null ? !linkedItemId.equals(that.linkedItemId) : that.linkedItemId != null) {
+            return false;
+        }
+        if (phaseName != null ? !phaseName.equals(that.phaseName) : that.phaseName != null) {
+            return false;
+        }
+        if (planName != null ? !planName.equals(that.planName) : that.planName != null) {
+            return false;
+        }
+        if (rate != null ? !rate.equals(that.rate) : that.rate != null) {
+            return false;
+        }
+        if (startDate != null ? !startDate.equals(that.startDate) : that.startDate != null) {
+            return false;
+        }
+        if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null) {
+            return false;
+        }
+        if (type != that.type) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (type != null ? type.hashCode() : 0);
+        result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
+        result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+        result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+        result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
+        result = 31 * result + (planName != null ? planName.hashCode() : 0);
+        result = 31 * result + (phaseName != null ? phaseName.hashCode() : 0);
+        result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
+        result = 31 * result + (endDate != null ? endDate.hashCode() : 0);
+        result = 31 * result + (amount != null ? amount.hashCode() : 0);
+        result = 31 * result + (rate != null ? rate.hashCode() : 0);
+        result = 31 * result + (currency != null ? currency.hashCode() : 0);
+        result = 31 * result + (linkedItemId != null ? linkedItemId.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
index d64fe91..2789596 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
@@ -34,16 +34,8 @@ import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceItemType;
-import com.ning.billing.invoice.model.CreditAdjInvoiceItem;
-import com.ning.billing.invoice.model.CreditBalanceAdjInvoiceItem;
-import com.ning.billing.invoice.model.ExternalChargeInvoiceItem;
-import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
-import com.ning.billing.invoice.model.ItemAdjInvoiceItem;
-import com.ning.billing.invoice.model.RecurringInvoiceItem;
-import com.ning.billing.invoice.model.RefundAdjInvoiceItem;
-import com.ning.billing.invoice.model.RepairAdjInvoiceItem;
+import com.ning.billing.invoice.dao.InvoiceItemSqlDao.InvoiceItemModelDaoSqlDaoMapper;
 import com.ning.billing.util.audit.ChangeType;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
@@ -53,41 +45,36 @@ import com.ning.billing.util.entity.dao.EntitySqlDao;
 import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
 
 @EntitySqlDaoStringTemplate
-@RegisterMapper(InvoiceItemSqlDao.InvoiceItemSqlDaoMapper.class)
-public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItem> {
+@RegisterMapper(InvoiceItemModelDaoSqlDaoMapper.class)
+public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItemModelDao> {
 
     @SqlQuery
-    List<Long> getRecordIds(@Bind("invoiceId") final String invoiceId,
-                            @BindBean final InternalTenantContext context);
+    List<InvoiceItemModelDao> getInvoiceItemsByInvoice(@Bind("invoiceId") final String invoiceId,
+                                                       @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<InvoiceItem> getInvoiceItemsByInvoice(@Bind("invoiceId") final String invoiceId,
-                                               @BindBean final InternalTenantContext context);
+    List<InvoiceItemModelDao> getInvoiceItemsByAccount(@Bind("accountId") final String accountId,
+                                                       @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<InvoiceItem> getInvoiceItemsByAccount(@Bind("accountId") final String accountId,
-                                               @BindBean final InternalTenantContext context);
-
-    @SqlQuery
-    List<InvoiceItem> getInvoiceItemsBySubscription(@Bind("subscriptionId") final String subscriptionId,
-                                                    @BindBean final InternalTenantContext context);
+    List<InvoiceItemModelDao> getInvoiceItemsBySubscription(@Bind("subscriptionId") final String subscriptionId,
+                                                            @BindBean final InternalTenantContext context);
 
     @Override
     @SqlUpdate
     @Audited(ChangeType.INSERT)
-    void create(@BindBean final InvoiceItem invoiceItem,
+    void create(@BindBean final InvoiceItemModelDao invoiceItem,
                 @BindBean final InternalCallContext context);
 
     @SqlBatch(transactional = false)
     @Audited(ChangeType.INSERT)
-    void batchCreateFromTransaction(@BindBean final List<InvoiceItem> items,
+    void batchCreateFromTransaction(@BindBean final List<InvoiceItemModelDao> items,
                                     @BindBean final InternalCallContext context);
 
-
-    public static class InvoiceItemSqlDaoMapper extends MapperBase implements ResultSetMapper<InvoiceItem> {
+    public static class InvoiceItemModelDaoSqlDaoMapper extends MapperBase implements ResultSetMapper<InvoiceItemModelDao> {
 
         @Override
-        public InvoiceItem map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
+        public InvoiceItemModelDao map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
             final UUID id = getUUID(result, "id");
             final InvoiceItemType type = InvoiceItemType.valueOf(result.getString("type"));
             final UUID invoiceId = getUUID(result, "invoice_id");
@@ -104,36 +91,8 @@ public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItem> {
             final UUID linkedItemId = getUUID(result, "linked_item_id");
             final DateTime createdDate = getDateTime(result, "created_date");
 
-            final InvoiceItem item;
-            switch (type) {
-                case EXTERNAL_CHARGE:
-                    item = new ExternalChargeInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, planName, startDate, amount, currency);
-                    break;
-                case FIXED:
-                    item = new FixedPriceInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, amount, currency);
-                    break;
-                case RECURRING:
-                    item = new RecurringInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount, rate, currency);
-                    break;
-                case CBA_ADJ:
-                    item = new CreditBalanceAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, linkedItemId, amount, currency);
-                    break;
-                case CREDIT_ADJ:
-                    item = new CreditAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, amount, currency);
-                    break;
-                case REFUND_ADJ:
-                    item = new RefundAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, amount, currency);
-                    break;
-                case REPAIR_ADJ:
-                    item = new RepairAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, endDate, amount, currency, linkedItemId);
-                    break;
-                case ITEM_ADJ:
-                    item = new ItemAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, amount, currency, linkedItemId);
-                    break;
-                default:
-                    throw new RuntimeException("Unexpected type of event item " + type);
-            }
-            return item;
+            return new InvoiceItemModelDao(id, createdDate, type, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName,
+                                           startDate, endDate, amount, rate, currency, linkedItemId);
         }
     }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceModelDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceModelDao.java
new file mode 100644
index 0000000..a70d129
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceModelDao.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2010-2012 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.invoice.dao;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.util.entity.EntityBase;
+
+public class InvoiceModelDao extends EntityBase {
+
+    private final UUID accountId;
+    private final Integer invoiceNumber;
+    private final LocalDate invoiceDate;
+    private final LocalDate targetDate;
+    private final Currency currency;
+    private final boolean migrated;
+
+    // Note in the database, for convenience only
+    private List<InvoiceItemModelDao> invoiceItems;
+    private List<InvoicePaymentModelDao> invoicePayments;
+
+    public InvoiceModelDao(final UUID id, @Nullable final DateTime createdDate, final UUID accountId,
+                           @Nullable final Integer invoiceNumber, final LocalDate invoiceDate, final LocalDate targetDate,
+                           final Currency currency, final boolean migrated) {
+        super(id, createdDate, createdDate);
+        this.accountId = accountId;
+        this.invoiceNumber = invoiceNumber;
+        this.invoiceDate = invoiceDate;
+        this.targetDate = targetDate;
+        this.currency = currency;
+        this.migrated = migrated;
+    }
+
+    public InvoiceModelDao(final UUID accountId, final LocalDate invoiceDate, final LocalDate targetDate, final Currency currency, final boolean migrated) {
+        this(UUID.randomUUID(), null, accountId, null, invoiceDate, targetDate, currency, migrated);
+    }
+
+    public InvoiceModelDao(final UUID accountId, final LocalDate invoiceDate, final LocalDate targetDate, final Currency currency) {
+        this(UUID.randomUUID(), null, accountId, null, invoiceDate, targetDate, currency, false);
+    }
+
+    public InvoiceModelDao(final Invoice invoice) {
+        this(invoice.getId(), invoice.getInvoiceDate(), invoice.getTargetDate(), invoice.getCurrency(), invoice.isMigrationInvoice());
+    }
+
+    public void addInvoiceItems(final List<InvoiceItemModelDao> invoiceItems) {
+        this.invoiceItems = invoiceItems;
+    }
+
+    public List<InvoiceItemModelDao> getInvoiceItems() {
+        return invoiceItems;
+    }
+
+    public void addPayments(final List<InvoicePaymentModelDao> invoicePayments) {
+        this.invoicePayments = invoicePayments;
+    }
+
+    public List<InvoicePaymentModelDao> getInvoicePayments() {
+        return invoicePayments;
+    }
+
+    public UUID getAccountId() {
+        return accountId;
+    }
+
+    public Integer getInvoiceNumber() {
+        return invoiceNumber;
+    }
+
+    public LocalDate getInvoiceDate() {
+        return invoiceDate;
+    }
+
+    public LocalDate getTargetDate() {
+        return targetDate;
+    }
+
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    public boolean isMigrated() {
+        return migrated;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("InvoiceModelDao");
+        sb.append("{accountId=").append(accountId);
+        sb.append(", invoiceNumber=").append(invoiceNumber);
+        sb.append(", invoiceDate=").append(invoiceDate);
+        sb.append(", targetDate=").append(targetDate);
+        sb.append(", currency=").append(currency);
+        sb.append(", migrated=").append(migrated);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final InvoiceModelDao that = (InvoiceModelDao) o;
+
+        if (migrated != that.migrated) {
+            return false;
+        }
+        if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+            return false;
+        }
+        if (currency != that.currency) {
+            return false;
+        }
+        if (invoiceDate != null ? !invoiceDate.equals(that.invoiceDate) : that.invoiceDate != null) {
+            return false;
+        }
+        if (invoiceNumber != null ? !invoiceNumber.equals(that.invoiceNumber) : that.invoiceNumber != null) {
+            return false;
+        }
+        if (targetDate != null ? !targetDate.equals(that.targetDate) : that.targetDate != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+        result = 31 * result + (invoiceNumber != null ? invoiceNumber.hashCode() : 0);
+        result = 31 * result + (invoiceDate != null ? invoiceDate.hashCode() : 0);
+        result = 31 * result + (targetDate != null ? targetDate.hashCode() : 0);
+        result = 31 * result + (currency != null ? currency.hashCode() : 0);
+        result = 31 * result + (migrated ? 1 : 0);
+        return result;
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceModelDaoHelper.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceModelDaoHelper.java
new file mode 100644
index 0000000..d66c36b
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceModelDaoHelper.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-2012 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.invoice.dao;
+
+import java.math.BigDecimal;
+
+import com.ning.billing.invoice.model.InvoiceItemList;
+
+public class InvoiceModelDaoHelper {
+
+    private InvoiceModelDaoHelper() {}
+
+    public static BigDecimal getBalance(final InvoiceModelDao invoiceModelDao) {
+        final InvoiceItemList invoiceItems = new InvoiceItemList(invoiceModelDao.getInvoiceItems());
+        return invoiceItems.getBalance(getPaidAmount(invoiceModelDao));
+    }
+
+    public static BigDecimal getCBAAmount(final InvoiceModelDao invoiceModelDao) {
+        final InvoiceItemList invoiceItems = new InvoiceItemList(invoiceModelDao.getInvoiceItems());
+        return invoiceItems.getCBAAmount();
+    }
+
+    public static BigDecimal getPaidAmount(final InvoiceModelDao invoiceModelDao) {
+        // Compute payments
+        BigDecimal amountPaid = BigDecimal.ZERO;
+        for (final InvoicePaymentModelDao payment : invoiceModelDao.getInvoicePayments()) {
+            if (payment.getAmount() != null) {
+                amountPaid = amountPaid.add(payment.getAmount());
+            }
+        }
+
+        return amountPaid;
+    }
+
+    public static BigDecimal getChargedAmount(final InvoiceModelDao invoiceModelDao) {
+        final InvoiceItemList invoiceItems = new InvoiceItemList(invoiceModelDao.getInvoiceItems());
+        return invoiceItems.getChargedAmount();
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentModelDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentModelDao.java
new file mode 100644
index 0000000..b723367
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentModelDao.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2010-2012 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.invoice.dao;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoicePayment;
+import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
+import com.ning.billing.util.entity.EntityBase;
+
+public class InvoicePaymentModelDao extends EntityBase {
+
+    private final InvoicePaymentType type;
+    private final UUID invoiceId;
+    private final UUID paymentId;
+    private final DateTime paymentDate;
+    private final BigDecimal amount;
+    private final Currency currency;
+    private final UUID paymentCookieId;
+    private final UUID linkedInvoicePaymentId;
+
+    public InvoicePaymentModelDao(final UUID id, final DateTime createdDate, final InvoicePaymentType type, final UUID invoiceId,
+                                  final UUID paymentId, final DateTime paymentDate, final BigDecimal amount, final Currency currency,
+                                  final UUID paymentCookieId, final UUID linkedInvoicePaymentId) {
+        super(id, createdDate, createdDate);
+        this.type = type;
+        this.invoiceId = invoiceId;
+        this.paymentId = paymentId;
+        this.paymentDate = paymentDate;
+        this.amount = amount;
+        this.currency = currency;
+        this.paymentCookieId = paymentCookieId;
+        this.linkedInvoicePaymentId = linkedInvoicePaymentId;
+    }
+
+    public InvoicePaymentModelDao(final InvoicePayment invoicePayment) {
+        this(invoicePayment.getId(), invoicePayment.getCreatedDate(), invoicePayment.getType(), invoicePayment.getInvoiceId(), invoicePayment.getPaymentId(),
+             invoicePayment.getPaymentDate(), invoicePayment.getAmount(), invoicePayment.getCurrency(), invoicePayment.getPaymentCookieId(),
+             invoicePayment.getLinkedInvoicePaymentId());
+    }
+
+    public InvoicePaymentType getType() {
+        return type;
+    }
+
+    public UUID getInvoiceId() {
+        return invoiceId;
+    }
+
+    public UUID getPaymentId() {
+        return paymentId;
+    }
+
+    public DateTime getPaymentDate() {
+        return paymentDate;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    public UUID getPaymentCookieId() {
+        return paymentCookieId;
+    }
+
+    public UUID getLinkedInvoicePaymentId() {
+        return linkedInvoicePaymentId;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("InvoicePaymentModelDao");
+        sb.append("{type=").append(type);
+        sb.append(", invoiceId=").append(invoiceId);
+        sb.append(", paymentId=").append(paymentId);
+        sb.append(", paymentDate=").append(paymentDate);
+        sb.append(", amount=").append(amount);
+        sb.append(", currency=").append(currency);
+        sb.append(", paymentCookieId=").append(paymentCookieId);
+        sb.append(", linkedInvoicePaymentId=").append(linkedInvoicePaymentId);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final InvoicePaymentModelDao that = (InvoicePaymentModelDao) o;
+
+        if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+            return false;
+        }
+        if (currency != that.currency) {
+            return false;
+        }
+        if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+            return false;
+        }
+        if (linkedInvoicePaymentId != null ? !linkedInvoicePaymentId.equals(that.linkedInvoicePaymentId) : that.linkedInvoicePaymentId != null) {
+            return false;
+        }
+        if (paymentCookieId != null ? !paymentCookieId.equals(that.paymentCookieId) : that.paymentCookieId != null) {
+            return false;
+        }
+        if (paymentDate != null ? !paymentDate.equals(that.paymentDate) : that.paymentDate != null) {
+            return false;
+        }
+        if (paymentId != null ? !paymentId.equals(that.paymentId) : that.paymentId != null) {
+            return false;
+        }
+        if (type != that.type) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (type != null ? type.hashCode() : 0);
+        result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
+        result = 31 * result + (paymentId != null ? paymentId.hashCode() : 0);
+        result = 31 * result + (paymentDate != null ? paymentDate.hashCode() : 0);
+        result = 31 * result + (amount != null ? amount.hashCode() : 0);
+        result = 31 * result + (currency != null ? currency.hashCode() : 0);
+        result = 31 * result + (paymentCookieId != null ? paymentCookieId.hashCode() : 0);
+        result = 31 * result + (linkedInvoicePaymentId != null ? linkedInvoicePaymentId.hashCode() : 0);
+        return result;
+    }
+}
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 4670035..a6ef56d 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
@@ -28,14 +28,12 @@ import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.BindBean;
 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.tweak.ResultSetMapper;
 
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
-import com.ning.billing.invoice.model.DefaultInvoicePayment;
+import com.ning.billing.invoice.dao.InvoicePaymentSqlDao.InvoicePaymentModelDaoMapper;
 import com.ning.billing.util.audit.ChangeType;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
@@ -46,48 +44,29 @@ import com.ning.billing.util.entity.dao.EntitySqlDao;
 import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
 
 @EntitySqlDaoStringTemplate
-@RegisterMapper(InvoicePaymentSqlDao.InvoicePaymentMapper.class)
-public interface InvoicePaymentSqlDao extends EntitySqlDao<InvoicePayment> {
+@RegisterMapper(InvoicePaymentModelDaoMapper.class)
+public interface InvoicePaymentSqlDao extends EntitySqlDao<InvoicePaymentModelDao> {
 
     @SqlQuery
-    List<Long> getRecordIds(@Bind("invoiceId") final String invoiceId,
-                            @BindBean final InternalTenantContext context);
-
-    @SqlQuery
-    public InvoicePayment getByPaymentId(@Bind("paymentId") final String paymentId,
-                                         @BindBean final InternalTenantContext context);
-
-    @Override
-    @SqlQuery
-    public List<InvoicePayment> get(@BindBean final InternalTenantContext context);
-
-    @Override
-    @SqlUpdate
-    @Audited(ChangeType.INSERT)
-    public void create(@BindBean final InvoicePayment invoicePayment,
-                       @BindBean final InternalCallContext context);
+    public InvoicePaymentModelDao getByPaymentId(@Bind("paymentId") final String paymentId,
+                                                 @BindBean final InternalTenantContext context);
 
     @SqlBatch(transactional = false)
     @Audited(ChangeType.INSERT)
-    void batchCreateFromTransaction(@BindBean final List<InvoicePayment> items,
+    void batchCreateFromTransaction(@BindBean final List<InvoicePaymentModelDao> items,
                                     @BindBean final InternalCallContext context);
 
     @SqlQuery
-    public List<InvoicePayment> getPaymentsForInvoice(@Bind("invoiceId") final String invoiceId,
-                                                      @BindBean final InternalTenantContext context);
+    public List<InvoicePaymentModelDao> getPaymentsForInvoice(@Bind("invoiceId") final String invoiceId,
+                                                              @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<InvoicePayment> getInvoicePayments(@Bind("paymentId") final String paymentId,
-                                            @BindBean final InternalTenantContext context);
+    List<InvoicePaymentModelDao> getInvoicePayments(@Bind("paymentId") final String paymentId,
+                                                    @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    InvoicePayment getPaymentsForCookieId(@Bind("paymentCookieId") final String paymentCookieId,
-                                          @BindBean final InternalTenantContext context);
-
-    @SqlUpdate
-    @Audited(ChangeType.UPDATE)
-    void notifyOfPayment(@BindBean final InvoicePayment invoicePayment,
-                         @BindBean final InternalCallContext context);
+    InvoicePaymentModelDao getPaymentsForCookieId(@Bind("paymentCookieId") final String paymentCookieId,
+                                                  @BindBean final InternalTenantContext context);
 
     @SqlQuery
     BigDecimal getRemainingAmountPaid(@Bind("invoicePaymentId") final String invoicePaymentId,
@@ -99,17 +78,17 @@ public interface InvoicePaymentSqlDao extends EntitySqlDao<InvoicePayment> {
                                           @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<InvoicePayment> getChargeBacksByAccountId(@Bind("accountId") final String accountId,
-                                                   @BindBean final InternalTenantContext context);
+    List<InvoicePaymentModelDao> getChargeBacksByAccountId(@Bind("accountId") final String accountId,
+                                                           @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<InvoicePayment> getChargebacksByPaymentId(@Bind("paymentId") final String paymentId,
-                                                   @BindBean final InternalTenantContext context);
+    List<InvoicePaymentModelDao> getChargebacksByPaymentId(@Bind("paymentId") final String paymentId,
+                                                           @BindBean final InternalTenantContext context);
 
-    public static class InvoicePaymentMapper extends MapperBase implements ResultSetMapper<InvoicePayment> {
+    public static class InvoicePaymentModelDaoMapper extends MapperBase implements ResultSetMapper<InvoicePaymentModelDao> {
 
         @Override
-        public InvoicePayment map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
+        public InvoicePaymentModelDao map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
             final UUID id = getUUID(result, "id");
             final InvoicePaymentType type = InvoicePaymentType.valueOf(result.getString("type"));
             final UUID paymentId = getUUID(result, "payment_id");
@@ -122,8 +101,8 @@ public interface InvoicePaymentSqlDao extends EntitySqlDao<InvoicePayment> {
             final UUID linkedInvoicePaymentId = getUUID(result, "linked_invoice_payment_id");
             final DateTime createdDate = getDateTime(result, "created_date");
 
-            return new DefaultInvoicePayment(id, createdDate, type, paymentId, invoiceId, paymentDate,
-                                             amount, currency, paymentCookieId, linkedInvoicePaymentId);
+            return new InvoicePaymentModelDao(id, createdDate, type, paymentId, invoiceId, paymentDate,
+                                              amount, currency, paymentCookieId, linkedInvoicePaymentId);
         }
     }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
index dae8456..5d4dd09 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
@@ -28,58 +28,46 @@ import org.skife.jdbi.v2.StatementContext;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.BindBean;
 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.tweak.ResultSetMapper;
 
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.model.DefaultInvoice;
-import com.ning.billing.util.audit.ChangeType;
-import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.invoice.dao.InvoiceSqlDao.InvoiceModelDaoMapper;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.dao.MapperBase;
 import com.ning.billing.util.dao.UuidMapper;
-import com.ning.billing.util.entity.dao.Audited;
 import com.ning.billing.util.entity.dao.EntitySqlDao;
 import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
 
 @EntitySqlDaoStringTemplate
-@RegisterMapper({InvoiceSqlDao.InvoiceMapper.class, UuidMapper.class})
-public interface InvoiceSqlDao extends EntitySqlDao<Invoice> {
-
-    @Override
-    @SqlUpdate
-    @Audited(ChangeType.INSERT)
-    void create(@BindBean Invoice invoice,
-                @BindBean final InternalCallContext context);
+@RegisterMapper({InvoiceModelDaoMapper.class, UuidMapper.class})
+public interface InvoiceSqlDao extends EntitySqlDao<InvoiceModelDao> {
 
     @SqlQuery
-    List<Invoice> getInvoicesByAccount(@Bind("accountId") final String accountId,
-                                       @BindBean final InternalTenantContext context);
+    List<InvoiceModelDao> getInvoicesByAccount(@Bind("accountId") final String accountId,
+                                               @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<Invoice> getAllInvoicesByAccount(@Bind("accountId") final String string,
-                                          @BindBean final InternalTenantContext context);
+    List<InvoiceModelDao> getAllInvoicesByAccount(@Bind("accountId") final String string,
+                                                  @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<Invoice> getInvoicesByAccountAfterDate(@Bind("accountId") final String accountId,
-                                                @Bind("fromDate") final Date fromDate,
-                                                @BindBean final InternalTenantContext context);
+    List<InvoiceModelDao> getInvoicesByAccountAfterDate(@Bind("accountId") final String accountId,
+                                                        @Bind("fromDate") final Date fromDate,
+                                                        @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    List<Invoice> getInvoicesBySubscription(@Bind("subscriptionId") final String subscriptionId,
-                                            @BindBean final InternalTenantContext context);
+    List<InvoiceModelDao> getInvoicesBySubscription(@Bind("subscriptionId") final String subscriptionId,
+                                                    @BindBean final InternalTenantContext context);
 
     @SqlQuery
     UUID getInvoiceIdByPaymentId(@Bind("paymentId") final String paymentId,
                                  @BindBean final InternalTenantContext context);
 
-
-    public static class InvoiceMapper extends MapperBase implements ResultSetMapper<Invoice> {
+    public static class InvoiceModelDaoMapper extends MapperBase implements ResultSetMapper<InvoiceModelDao> {
 
         @Override
-        public Invoice map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
+        public InvoiceModelDao map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
             final UUID id = UUID.fromString(result.getString("id"));
             final UUID accountId = UUID.fromString(result.getString("account_id"));
             final int invoiceNumber = result.getInt("invoice_number");
@@ -89,7 +77,7 @@ public interface InvoiceSqlDao extends EntitySqlDao<Invoice> {
             final boolean isMigrationInvoice = result.getBoolean("migrated");
             final DateTime createdDate = getDateTime(result, "created_date");
 
-            return new DefaultInvoice(id, createdDate, accountId, invoiceNumber, invoiceDate, targetDate, currency, isMigrationInvoice);
+            return new InvoiceModelDao(id, createdDate, accountId, invoiceNumber, invoiceDate, targetDate, currency, isMigrationInvoice);
         }
     }
 }
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 a163515..8f2d64a 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
@@ -18,6 +18,7 @@ package com.ning.billing.invoice.glue;
 
 import org.skife.config.ConfigurationObjectFactory;
 
+import com.ning.billing.invoice.dao.DefaultInvoiceDao;
 import com.ning.billing.util.config.InvoiceConfig;
 import com.ning.billing.glue.InvoiceModule;
 import com.ning.billing.invoice.InvoiceListener;
@@ -33,7 +34,6 @@ import com.ning.billing.invoice.api.invoice.DefaultInvoicePaymentApi;
 import com.ning.billing.invoice.api.migration.DefaultInvoiceMigrationApi;
 import com.ning.billing.invoice.api.svcs.DefaultInvoiceInternalApi;
 import com.ning.billing.invoice.api.user.DefaultInvoiceUserApi;
-import com.ning.billing.invoice.dao.AuditedInvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.generator.DefaultInvoiceGenerator;
 import com.ning.billing.invoice.generator.InvoiceGenerator;
@@ -53,7 +53,7 @@ public class DefaultInvoiceModule extends AbstractModule implements InvoiceModul
     InvoiceConfig config;
 
     protected void installInvoiceDao() {
-        bind(InvoiceDao.class).to(AuditedInvoiceDao.class).asEagerSingleton();
+        bind(InvoiceDao.class).to(DefaultInvoiceDao.class).asEagerSingleton();
     }
 
     @Override
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 47b5edb..84c96b8 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -39,15 +39,19 @@ import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceNotifier;
+import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.user.DefaultInvoiceCreationEvent;
 import com.ning.billing.invoice.api.user.DefaultNullInvoiceEvent;
 import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceItemModelDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
+import com.ning.billing.invoice.dao.InvoicePaymentModelDao;
 import com.ning.billing.invoice.generator.InvoiceDateUtils;
 import com.ning.billing.invoice.generator.InvoiceGenerator;
+import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.util.callcontext.InternalCallContext;
-import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.events.BusInternalEvent;
 import com.ning.billing.util.events.EffectiveSubscriptionInternalEvent;
@@ -63,8 +67,10 @@ import com.ning.billing.util.svcapi.junction.BillingInternalApi;
 import com.ning.billing.util.svcsapi.bus.InternalBus;
 import com.ning.billing.util.svcsapi.bus.InternalBus.EventBusException;
 
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
 public class InvoiceDispatcher {
@@ -81,7 +87,6 @@ public class InvoiceDispatcher {
     private final GlobalLocker locker;
     private final InternalBus eventBus;
     private final Clock clock;
-    private final InternalCallContextFactory internalCallContextFactory;
 
     @Inject
     public InvoiceDispatcher(final InvoiceGenerator generator, final AccountInternalApi accountApi,
@@ -91,8 +96,7 @@ public class InvoiceDispatcher {
                              final InvoiceNotifier invoiceNotifier,
                              final GlobalLocker locker,
                              final InternalBus eventBus,
-                             final Clock clock,
-                             final InternalCallContextFactory internalCallContextFactory) {
+                             final Clock clock) {
         this.generator = generator;
         this.billingApi = billingApi;
         this.entitlementApi = entitlementApi;
@@ -102,7 +106,6 @@ public class InvoiceDispatcher {
         this.locker = locker;
         this.eventBus = eventBus;
         this.clock = clock;
-        this.internalCallContextFactory = internalCallContextFactory;
     }
 
     public void processSubscription(final EffectiveSubscriptionInternalEvent transition,
@@ -153,10 +156,16 @@ public class InvoiceDispatcher {
             // Make sure to first set the BCD if needed then get the account object (to have the BCD set)
             final BillingEventSet billingEvents = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId, context);
 
-            final Account account = accountApi.getAccountById(accountId,  context);
+            final Account account = accountApi.getAccountById(accountId, context);
             List<Invoice> invoices = new ArrayList<Invoice>();
             if (!billingEvents.isAccountAutoInvoiceOff()) {
-                invoices = invoiceDao.getInvoicesByAccount(accountId, context); //no need to fetch, invoicing is off on this account
+                invoices = ImmutableList.<Invoice>copyOf(Collections2.transform(invoiceDao.getInvoicesByAccount(accountId, context),
+                                                                                new Function<InvoiceModelDao, Invoice>() {
+                                                                                    @Override
+                                                                                    public Invoice apply(final InvoiceModelDao input) {
+                                                                                        return new DefaultInvoice(input);
+                                                                                    }
+                                                                                })); //no need to fetch, invoicing is off on this account
             }
 
             final Currency targetCurrency = account.getCurrency();
@@ -169,7 +178,7 @@ public class InvoiceDispatcher {
                 log.info("Generated null invoice.");
                 if (!dryRun) {
                     final BusInternalEvent event = new DefaultNullInvoiceEvent(accountId, clock.getUTCToday(), context.getUserToken(),
-                            context.getAccountRecordId(), context.getTenantRecordId());
+                                                                               context.getAccountRecordId(), context.getTenantRecordId());
                     postEvent(event, accountId, context);
                 }
             } else {
@@ -183,17 +192,33 @@ public class InvoiceDispatcher {
                         }
                     }).size() > 0;
 
-                    invoiceDao.create(invoice, account.getBillCycleDay().getDayOfMonthUTC(), isRealInvoiceWithItems, context);
+                    final InvoiceModelDao invoiceModelDao = new InvoiceModelDao(invoice);
+                    final List<InvoiceItemModelDao> invoiceItemModelDaos = ImmutableList.<InvoiceItemModelDao>copyOf(Collections2.transform(invoice.getInvoiceItems(),
+                                                                                                                                            new Function<InvoiceItem, InvoiceItemModelDao>() {
+                                                                                                                                                @Override
+                                                                                                                                                public InvoiceItemModelDao apply(final InvoiceItem input) {
+                                                                                                                                                    return new InvoiceItemModelDao(input);
+                                                                                                                                                }
+                                                                                                                                            }));
+                    // Not really needed, there shouldn't be any payment at this stage
+                    final List<InvoicePaymentModelDao> invoicePaymentModelDaos = ImmutableList.<InvoicePaymentModelDao>copyOf(Collections2.transform(invoice.getPayments(),
+                                                                                                                                                     new Function<InvoicePayment, InvoicePaymentModelDao>() {
+                                                                                                                                                         @Override
+                                                                                                                                                         public InvoicePaymentModelDao apply(final InvoicePayment input) {
+                                                                                                                                                             return new InvoicePaymentModelDao(input);
+                                                                                                                                                         }
+                                                                                                                                                     }));
+                    invoiceDao.createInvoice(invoiceModelDao, invoiceItemModelDaos, invoicePaymentModelDaos, isRealInvoiceWithItems, context);
 
                     final List<InvoiceItem> fixedPriceInvoiceItems = invoice.getInvoiceItems(FixedPriceInvoiceItem.class);
                     final List<InvoiceItem> recurringInvoiceItems = invoice.getInvoiceItems(RecurringInvoiceItem.class);
                     setChargedThroughDates(account.getBillCycleDay(), account.getTimeZone(), fixedPriceInvoiceItems, recurringInvoiceItems, context);
 
                     final InvoiceCreationInternalEvent event = new DefaultInvoiceCreationEvent(invoice.getId(), invoice.getAccountId(),
-                                                                                       invoice.getBalance(), invoice.getCurrency(),
-                                                                                       context.getUserToken(),
-                                                                                       context.getAccountRecordId(),
-                                                                                       context.getTenantRecordId());
+                                                                                               invoice.getBalance(), invoice.getCurrency(),
+                                                                                               context.getUserToken(),
+                                                                                               context.getAccountRecordId(),
+                                                                                               context.getTenantRecordId());
 
                     if (isRealInvoiceWithItems) {
                         postEvent(event, accountId, context);
@@ -204,7 +229,7 @@ public class InvoiceDispatcher {
             if (account.isNotifiedForInvoices() && invoice != null && !dryRun) {
                 // Need to re-hydrate the invoice object to get the invoice number (record id)
                 // API_FIX InvoiceNotifier public API?
-                invoiceNotifier.notify(account, invoiceDao.getById(invoice.getId(), context), context.toTenantContext());
+                invoiceNotifier.notify(account, new DefaultInvoice(invoiceDao.getById(invoice.getId(), context)), context.toTenantContext());
             }
 
             return invoice;
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoice.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoice.java
index 8231cf3..803bfd9 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoice.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoice.java
@@ -30,6 +30,7 @@ import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoicePayment;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
 import com.ning.billing.util.entity.EntityBase;
 
 public class DefaultInvoice extends EntityBase implements Invoice {
@@ -66,6 +67,12 @@ public class DefaultInvoice extends EntityBase implements Invoice {
         this.migrationInvoice = isMigrationInvoice;
     }
 
+    public DefaultInvoice(final InvoiceModelDao invoiceModelDao) {
+        this(invoiceModelDao.getId(), invoiceModelDao.getCreatedDate(), invoiceModelDao.getAccountId(),
+             invoiceModelDao.getInvoiceNumber(), invoiceModelDao.getInvoiceDate(), invoiceModelDao.getTargetDate(),
+             invoiceModelDao.getCurrency(), invoiceModelDao.isMigrated());
+    }
+
     @Override
     public boolean addInvoiceItem(final InvoiceItem item) {
         return invoiceItems.add(item);
@@ -190,7 +197,7 @@ public class DefaultInvoice extends EntityBase implements Invoice {
 
     @Override
     public BigDecimal getBalance() {
-        return getChargedAmount().add(getTotalAdjAmount()).add(getCBAAmount()).subtract(getPaidAmount());
+        return invoiceItems.getBalance(getPaidAmount());
     }
 
     @Override
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoicePayment.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoicePayment.java
index 2805276..ff8c157 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoicePayment.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoicePayment.java
@@ -25,6 +25,7 @@ import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.InvoicePayment;
+import com.ning.billing.invoice.dao.InvoicePaymentModelDao;
 import com.ning.billing.util.entity.EntityBase;
 
 public class DefaultInvoicePayment extends EntityBase implements InvoicePayment {
@@ -63,6 +64,13 @@ public class DefaultInvoicePayment extends EntityBase implements InvoicePayment 
         this.linkedInvoicePaymentId = linkedInvoicePaymentId;
     }
 
+    public DefaultInvoicePayment(final InvoicePaymentModelDao invoicePaymentModelDao) {
+        this(invoicePaymentModelDao.getId(), invoicePaymentModelDao.getCreatedDate(), invoicePaymentModelDao.getType(),
+             invoicePaymentModelDao.getPaymentId(), invoicePaymentModelDao.getInvoiceId(), invoicePaymentModelDao.getPaymentDate(),
+             invoicePaymentModelDao.getAmount(), invoicePaymentModelDao.getCurrency(), invoicePaymentModelDao.getPaymentCookieId(),
+             invoicePaymentModelDao.getLinkedInvoicePaymentId());
+    }
+
     @Override
     public InvoicePaymentType getType() {
         return type;
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemFactory.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemFactory.java
new file mode 100644
index 0000000..51bf702
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemFactory.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010-2012 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.invoice.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.invoice.dao.InvoiceItemModelDao;
+
+public class InvoiceItemFactory {
+
+    private InvoiceItemFactory() {}
+
+    public static InvoiceItem fromModelDao(final InvoiceItemModelDao invoiceItemModelDao) {
+        final UUID id = invoiceItemModelDao.getId();
+        final DateTime createdDate = invoiceItemModelDao.getCreatedDate();
+        final UUID invoiceId = invoiceItemModelDao.getInvoiceId();
+        final UUID accountId = invoiceItemModelDao.getAccountId();
+        final UUID bundleId = invoiceItemModelDao.getBundleId();
+        final UUID subscriptionId = invoiceItemModelDao.getSubscriptionId();
+        final String planName = invoiceItemModelDao.getPlanName();
+        final String phaseName = invoiceItemModelDao.getPhaseName();
+        final LocalDate startDate = invoiceItemModelDao.getStartDate();
+        final LocalDate endDate = invoiceItemModelDao.getEndDate();
+        final BigDecimal amount = invoiceItemModelDao.getAmount();
+        final BigDecimal rate = invoiceItemModelDao.getRate();
+        final Currency currency = invoiceItemModelDao.getCurrency();
+        final UUID linkedItemId = invoiceItemModelDao.getLinkedItemId();
+
+        final InvoiceItem item;
+        final InvoiceItemType type = invoiceItemModelDao.getType();
+        switch (type) {
+            case EXTERNAL_CHARGE:
+                item = new ExternalChargeInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, planName, startDate, amount, currency);
+                break;
+            case FIXED:
+                item = new FixedPriceInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, amount, currency);
+                break;
+            case RECURRING:
+                item = new RecurringInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount, rate, currency);
+                break;
+            case CBA_ADJ:
+                item = new CreditBalanceAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, linkedItemId, amount, currency);
+                break;
+            case CREDIT_ADJ:
+                item = new CreditAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, amount, currency);
+                break;
+            case REFUND_ADJ:
+                item = new RefundAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, amount, currency);
+                break;
+            case REPAIR_ADJ:
+                item = new RepairAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, endDate, amount, currency, linkedItemId);
+                break;
+            case ITEM_ADJ:
+                item = new ItemAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, amount, currency, linkedItemId);
+                break;
+            default:
+                throw new RuntimeException("Unexpected type of event item " + type);
+        }
+
+        return item;
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
index e505d9e..94b6f2a 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
@@ -18,11 +18,11 @@ package com.ning.billing.invoice.model;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.invoice.dao.InvoiceItemModelDao;
 
 public class InvoiceItemList extends ArrayList<InvoiceItem> {
 
@@ -35,9 +35,15 @@ public class InvoiceItemList extends ArrayList<InvoiceItem> {
         super();
     }
 
-    public InvoiceItemList(final List<InvoiceItem> invoiceItems) {
+    public InvoiceItemList(final List<InvoiceItemModelDao> invoiceItems) {
         super();
-        this.addAll(invoiceItems);
+        for (final InvoiceItemModelDao invoiceItemModelDao : invoiceItems) {
+            this.add(InvoiceItemFactory.fromModelDao(invoiceItemModelDao));
+        }
+    }
+
+    public BigDecimal getBalance(final BigDecimal paidAmount) {
+        return getChargedAmount().add(getTotalAdjAmount()).add(getCBAAmount()).subtract(paidAmount);
     }
 
     public BigDecimal getTotalAdjAmount() {
@@ -60,8 +66,7 @@ public class InvoiceItemList extends ArrayList<InvoiceItem> {
         return getAmoutForItems(InvoiceItemType.CBA_ADJ);
     }
 
-
-    private BigDecimal getAmoutForItems(InvoiceItemType...types) {
+    private BigDecimal getAmoutForItems(InvoiceItemType... types) {
         BigDecimal total = BigDecimal.ZERO.setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
         for (final InvoiceItem item : this) {
             if (isFromType(item, types)) {
@@ -73,7 +78,7 @@ public class InvoiceItemList extends ArrayList<InvoiceItem> {
         return total.setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
     }
 
-    private boolean isFromType(InvoiceItem item, InvoiceItemType...types) {
+    private boolean isFromType(InvoiceItem item, InvoiceItemType... types) {
         for (InvoiceItemType cur : types) {
             if (item.getInvoiceItemType() == cur) {
                 return true;
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
index 209a3af..5c762b9 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
@@ -1,5 +1,7 @@
 group InvoiceItemSqlDao: EntitySqlDao;
 
+tableName() ::= "invoice_items"
+
 tableFields(prefix) ::= <<
   <prefix>type
 , <prefix>invoice_id
@@ -38,24 +40,24 @@ tableValues() ::= <<
 
 
 getInvoiceItemsByInvoice() ::= <<
-  SELECT <fields()>
-  FROM invoice_items
+  SELECT <allTableFields()>
+  FROM <tableName()>
   WHERE invoice_id = :invoiceId
   <AND_CHECK_TENANT()>
   ;
 >>
 
 getInvoiceItemsByAccount() ::= <<
-  SELECT <fields()>
-  FROM invoice_items
+  SELECT <allTableFields()>
+  FROM <tableName()>
   WHERE account_id = :accountId
   <AND_CHECK_TENANT()>
   ;
 >>
 
 getInvoiceItemsBySubscription() ::= <<
-  SELECT <fields()>
-  FROM invoice_items
+  SELECT <allTableFields()>
+  FROM <tableName()>
   WHERE subscription_id = :subscriptionId
   <AND_CHECK_TENANT()>
   ;
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg
index 335974b..86bfd1b 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg
@@ -1,5 +1,6 @@
 group InvoicePayment: EntitySqlDao;
 
+tableName() ::= "invoice_payments"
 
 tableFields(prefix) ::= <<
   <prefix>type
@@ -28,39 +29,32 @@ tableValues() ::= <<
 >>
 
 getByPaymentId() ::= <<
-  SELECT <invoicePaymentFields()>
-  FROM invoice_payments
+  SELECT <allTableFields()>
+  FROM <tableName()>
   WHERE payment_id = :paymentId
   <AND_CHECK_TENANT()>
   ;
 >>
 
-
 getPaymentsForCookieId() ::= <<
-  SELECT <invoicePaymentFields()>
-  FROM invoice_payments
+  SELECT <allTableFields()>
+  FROM <tableName()>
   WHERE payment_cookie_id = :paymentCookieId
   <AND_CHECK_TENANT()>
   ;
 >>
 
 getPaymentsForInvoice() ::= <<
-  SELECT <invoicePaymentFields()>
-  FROM invoice_payments
+  SELECT <allTableFields()>
+  FROM <tableName()>
   WHERE invoice_id = :invoiceId
   <AND_CHECK_TENANT()>
   ;
 >>
 
-notifyOfPayment() ::= <<
-  INSERT INTO invoice_payments(<invoicePaymentFields()>)
-  VALUES(:id, :type, :invoiceId, :paymentId, :paymentDate, :amount, :currency,
-         :paymentCookieId, :linkedInvoicePaymentId, :userName, :createdDate, :accountRecordId, :tenantRecordId);
->>
-
 getInvoicePayments() ::= <<
-    SELECT <invoicePaymentFields()>
-    FROM invoice_payments
+    SELECT <allTableFields()>
+    FROM <tableName()>
     WHERE payment_id = :paymentId
     <AND_CHECK_TENANT()>
     ;
@@ -68,15 +62,15 @@ getInvoicePayments() ::= <<
 
 getRemainingAmountPaid() ::= <<
     SELECT SUM(amount)
-    FROM invoice_payments
+    FROM <tableName()>
     WHERE (id = :invoicePaymentId OR linked_invoice_payment_id = :invoicePaymentId)
     <AND_CHECK_TENANT()>
     ;
 >>
 
 getAccountIdFromInvoicePaymentId() ::= <<
-    SELECT account_id
-    FROM invoice_payments ip
+    SELECT <tableName()>
+    FROM <tableName()> ip
     INNER JOIN invoices i ON i.id = ip.invoice_id
     WHERE ip.id = :invoicePaymentId
     <AND_CHECK_TENANT("i.")>
@@ -85,8 +79,8 @@ getAccountIdFromInvoicePaymentId() ::= <<
 >>
 
 getChargeBacksByAccountId() ::= <<
-    SELECT <invoicePaymentFields("ip.")>
-    FROM invoice_payments ip
+    SELECT <allTableFields("ip.")>
+    FROM <tableName()> ip
     INNER JOIN invoices i ON i.id = ip.invoice_id
     WHERE ip.type = 'CHARGED_BACK' AND i.account_id = :accountId
     <AND_CHECK_TENANT("i.")>
@@ -95,8 +89,8 @@ getChargeBacksByAccountId() ::= <<
 >>
 
 getChargebacksByPaymentId() ::= <<
-    SELECT <invoicePaymentFields()>
-    FROM invoice_payments
+    SELECT <allTableFields()>
+    FROM <tableName()>
     WHERE type = 'CHARGED_BACK'
     AND linked_invoice_payment_id IN (SELECT id FROM invoice_payments WHERE payment_id = :paymentId)
     <AND_CHECK_TENANT()>
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
index 65a683f..860cc53 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
@@ -1,5 +1,6 @@
 group InvoiceDao: EntitySqlDao;
 
+tableName() ::= "invoices"
 
 tableFields(prefix) ::= <<
   <prefix>account_id
@@ -13,42 +14,42 @@ tableFields(prefix) ::= <<
 
 
 tableValues(prefix) ::= <<
-    <prefix>account_id
-    <prefix>invoice_date
-    <prefix>target_date
-    <prefix>currency
-    <prefix>migrated
-    <prefix>created_by
-    <prefix>created_date
+  accountId
+, :invoiceDate
+, :targetDate
+, :currency
+, :migrated
+, :createdBy
+, :createdDate
 >>
 
 getInvoicesByAccount() ::= <<
-  SELECT record_id as invoice_number, <invoiceFields()>
-  FROM invoices
+  SELECT record_id as invoice_number, <allTableFields()>
+  FROM <tableName()>
   WHERE account_id = :accountId AND migrated = '0'
   <AND_CHECK_TENANT()>
   ORDER BY target_date ASC;
 >>
 
 getAllInvoicesByAccount() ::= <<
-  SELECT record_id as invoice_number, <invoiceFields()>
-  FROM invoices
+  SELECT record_id as invoice_number, <allTableFields()>
+  FROM <tableName()>
   WHERE account_id = :accountId
   <AND_CHECK_TENANT()>
   ORDER BY target_date ASC;
 >>
 
 getInvoicesByAccountAfterDate() ::= <<
-  SELECT record_id as invoice_number, <invoiceFields()>
-  FROM invoices
+  SELECT record_id as invoice_number, <allTableFields()>
+  FROM <tableName()>
   WHERE account_id = :accountId AND target_date >= :fromDate AND migrated = '0'
   <AND_CHECK_TENANT()>
   ORDER BY target_date ASC;
 >>
 
 getInvoicesBySubscription() ::= <<
-  SELECT i.record_id as invoice_number, <invoiceFields("i.")>
-  FROM invoices i
+  SELECT i.record_id as invoice_number, <allTableFields("i.")>
+  FROM <tableName()> i
   JOIN invoice_items ii ON i.id = ii.invoice_id
   WHERE ii.subscription_id = :subscriptionId AND i.migrated = '0'
   <AND_CHECK_TENANT("i.")>
@@ -58,7 +59,7 @@ getInvoicesBySubscription() ::= <<
 
 getInvoiceIdByPaymentId() ::= <<
   SELECT i.id
-    FROM invoices i, invoice_payments ip
+    FROM <tableName()> i, invoice_payments ip
    WHERE ip.invoice_id = i.id
      AND ip.payment_id = :paymentId
    <AND_CHECK_TENANT("i.")>
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/invoice/TestDefaultInvoicePaymentApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/invoice/TestDefaultInvoicePaymentApi.java
index ccd01ae..4d2ee81 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/invoice/TestDefaultInvoicePaymentApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/invoice/TestDefaultInvoicePaymentApi.java
@@ -39,7 +39,7 @@ import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.api.svcs.DefaultInvoiceInternalApi;
-import com.ning.billing.invoice.dao.AuditedInvoiceDao;
+import com.ning.billing.invoice.dao.DefaultInvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceItemSqlDao;
 import com.ning.billing.invoice.dao.InvoiceSqlDao;
@@ -83,7 +83,7 @@ public class TestDefaultInvoicePaymentApi extends InvoiceTestSuiteWithEmbeddedDB
 
         final NextBillingDatePoster nextBillingDatePoster = new MockNextBillingDatePoster();
         internalCallContextFactory = new InternalCallContextFactory(dbi, clock);
-        final InvoiceDao invoiceDao = new AuditedInvoiceDao(dbi, nextBillingDatePoster, clock, Mockito.mock(InternalBus.class));
+        final InvoiceDao invoiceDao = new DefaultInvoiceDao(dbi, nextBillingDatePoster, Mockito.mock(InternalBus.class));
         invoicePaymentApi = new DefaultInvoicePaymentApi(invoiceDao, internalCallContextFactory);
         invoiceInternalApi = new DefaultInvoiceInternalApi(invoiceDao);
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java
index 6f6d465..42518d7 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java
@@ -45,6 +45,7 @@ import com.ning.billing.invoice.api.InvoiceNotifier;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
 import com.ning.billing.invoice.generator.InvoiceGenerator;
 import com.ning.billing.invoice.notification.NullInvoiceNotifier;
 import com.ning.billing.invoice.tests.InvoicingTestBase;
@@ -141,12 +142,12 @@ public abstract class InvoiceApiTestBase extends InvoicingTestBase {
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
         final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, entitlementApi,
                                                                    invoiceDao, invoiceNotifier, locker, busService.getBus(),
-                                                                   clock, internalCallContextFactory);
+                                                                   clock);
 
         Invoice invoice = dispatcher.processAccount(account.getId(), targetDate, true, internalCallContext);
         Assert.assertNotNull(invoice);
 
-        List<Invoice> invoices = invoiceDao.getInvoicesByAccount(account.getId(), internalCallContext);
+        List<InvoiceModelDao> invoices = invoiceDao.getInvoicesByAccount(account.getId(), internalCallContext);
         Assert.assertEquals(invoices.size(), 0);
 
         invoice = dispatcher.processAccount(account.getId(), targetDate, false, internalCallContext);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
index ab8afe5..6aaa407 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
@@ -33,6 +33,8 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
+import com.ning.billing.invoice.dao.InvoiceModelDaoHelper;
 
 public class TestDefaultInvoiceMigrationApi extends InvoiceApiTestBase {
 
@@ -65,17 +67,17 @@ public class TestDefaultInvoiceMigrationApi extends InvoiceApiTestBase {
         Assert.assertNotNull(migrationInvoiceId);
         //Double check it was created and values are correct
 
-        final Invoice invoice = invoiceDao.getById(migrationInvoiceId, internalCallContext);
+        final InvoiceModelDao invoice = invoiceDao.getById(migrationInvoiceId, internalCallContext);
         Assert.assertNotNull(invoice);
 
         Assert.assertEquals(invoice.getAccountId(), accountId);
         Assert.assertEquals(invoice.getTargetDate().compareTo(date_migrated), 0); //temp to avoid tz test artifact
         //		Assert.assertEquals(invoice.getTargetDate(),now);
-        Assert.assertEquals(invoice.getNumberOfItems(), 1);
+        Assert.assertEquals(invoice.getInvoiceItems().size(), 1);
         Assert.assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(MIGRATION_INVOICE_AMOUNT), 0);
-        Assert.assertEquals(invoice.getBalance().compareTo(MIGRATION_INVOICE_AMOUNT), 0);
+        Assert.assertEquals(InvoiceModelDaoHelper.getBalance(invoice).compareTo(MIGRATION_INVOICE_AMOUNT), 0);
         Assert.assertEquals(invoice.getCurrency(), MIGRATION_INVOICE_CURRENCY);
-        Assert.assertTrue(invoice.isMigrationInvoice());
+        Assert.assertTrue(invoice.isMigrated());
 
         return migrationInvoiceId;
     }
@@ -105,10 +107,10 @@ public class TestDefaultInvoiceMigrationApi extends InvoiceApiTestBase {
 
     // ACCOUNT balance should reflect total of migration and non-migration invoices
     @Test(groups = "slow")
-    public void testBalance() throws InvoiceApiException{
-        final Invoice migrationInvoice = invoiceDao.getById(migrationInvoiceId, internalCallContext);
-        final Invoice regularInvoice = invoiceDao.getById(regularInvoiceId, internalCallContext);
-        final BigDecimal balanceOfAllInvoices = migrationInvoice.getBalance().add(regularInvoice.getBalance());
+    public void testBalance() throws InvoiceApiException {
+        final InvoiceModelDao migrationInvoice = invoiceDao.getById(migrationInvoiceId, internalCallContext);
+        final InvoiceModelDao regularInvoice = invoiceDao.getById(regularInvoiceId, internalCallContext);
+        final BigDecimal balanceOfAllInvoices = InvoiceModelDaoHelper.getBalance(migrationInvoice).add(InvoiceModelDaoHelper.getBalance(regularInvoice));
 
         final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
         log.info("ACCOUNT balance: " + accountBalance + " should equal the Balance Of All Invoices: " + balanceOfAllInvoices);
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 75919ac..6ed7402 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
@@ -16,19 +16,22 @@
 
 package com.ning.billing.invoice.dao;
 
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
 import java.io.IOException;
 import java.net.URL;
+import java.util.List;
+import java.util.UUID;
 
 import org.skife.jdbi.v2.IDBI;
+import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 
 import com.ning.billing.KillbillTestSuiteWithEmbeddedDB;
-import com.ning.billing.util.config.InvoiceConfig;
 import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.generator.DefaultInvoiceGenerator;
 import com.ning.billing.invoice.generator.InvoiceGenerator;
 import com.ning.billing.invoice.glue.InvoiceModuleWithEmbeddedDb;
@@ -36,12 +39,23 @@ import com.ning.billing.invoice.notification.MockNextBillingDatePoster;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
 import com.ning.billing.invoice.tests.InvoicingTestBase;
 import com.ning.billing.util.bus.InMemoryInternalBus;
+import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.config.InvoiceConfig;
+import com.ning.billing.util.entity.EntityPersistenceException;
 import com.ning.billing.util.svcsapi.bus.InternalBus;
 import com.ning.billing.util.tag.api.user.TagEventBuilder;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
 public class InvoiceDaoTestBase extends InvoicingTestBase {
+
     protected final TagEventBuilder tagEventBuilder = new TagEventBuilder();
 
     protected IDBI dbi;
@@ -98,7 +112,7 @@ public class InvoiceDaoTestBase extends InvoicingTestBase {
         bus.start();
 
         final NextBillingDatePoster nextBillingDatePoster = new MockNextBillingDatePoster();
-        invoiceDao = new AuditedInvoiceDao(dbi, nextBillingDatePoster, clock, bus);
+        invoiceDao = new DefaultInvoiceDao(dbi, nextBillingDatePoster, bus);
         invoiceDao.test(internalCallContext);
 
         invoiceItemSqlDao = dbi.onDemand(InvoiceItemSqlDao.class);
@@ -114,4 +128,43 @@ public class InvoiceDaoTestBase extends InvoicingTestBase {
         bus.stop();
         assertTrue(true);
     }
+
+    protected void createPayment(final InvoicePayment invoicePayment, final InternalCallContext internalCallContext) {
+        try {
+            invoicePaymentDao.create(new InvoicePaymentModelDao(invoicePayment), internalCallContext);
+        } catch (EntityPersistenceException e) {
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    protected void createInvoiceItem(final InvoiceItem invoiceItem, final InternalCallContext internalCallContext) {
+        invoiceItemSqlDao.create(new InvoiceItemModelDao(invoiceItem), internalCallContext);
+    }
+
+    protected void createInvoice(final Invoice invoice, final boolean isRealInvoiceWithItems, final InternalCallContext internalCallContext) {
+        final InvoiceModelDao invoiceModelDao = new InvoiceModelDao(invoice);
+        final List<InvoiceItemModelDao> invoiceItemModelDaos = ImmutableList.<InvoiceItemModelDao>copyOf(Collections2.transform(invoice.getInvoiceItems(),
+                                                                                                                                new Function<InvoiceItem, InvoiceItemModelDao>() {
+                                                                                                                                    @Override
+                                                                                                                                    public InvoiceItemModelDao apply(final InvoiceItem input) {
+                                                                                                                                        return new InvoiceItemModelDao(input);
+                                                                                                                                    }
+                                                                                                                                }));
+        // Not really needed, there shouldn't be any payment at this stage
+        final List<InvoicePaymentModelDao> invoicePaymentModelDaos = ImmutableList.<InvoicePaymentModelDao>copyOf(Collections2.transform(invoice.getPayments(),
+                                                                                                                                         new Function<InvoicePayment, InvoicePaymentModelDao>() {
+                                                                                                                                             @Override
+                                                                                                                                             public InvoicePaymentModelDao apply(final InvoicePayment input) {
+                                                                                                                                                 return new InvoicePaymentModelDao(input);
+                                                                                                                                             }
+                                                                                                                                         }));
+
+        invoiceDao.createInvoice(invoiceModelDao, invoiceItemModelDaos, invoicePaymentModelDaos, isRealInvoiceWithItems, internalCallContext);
+    }
+
+    protected void verifyInvoice(final UUID invoiceId, final double balance, final double cbaAmount) throws InvoiceApiException {
+        final InvoiceModelDao invoice = invoiceDao.getById(invoiceId, internalCallContext);
+        Assert.assertEquals(InvoiceModelDaoHelper.getBalance(invoice).doubleValue(), balance);
+        Assert.assertEquals(InvoiceModelDaoHelper.getCBAAmount(invoice).doubleValue(), cbaAmount);
+    }
 }
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 3f67067..cdcc683 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
@@ -29,10 +29,7 @@ import javax.annotation.Nullable;
 import org.joda.time.LocalDate;
 
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.user.DefaultInvoiceCreationEvent;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
@@ -44,7 +41,9 @@ public class MockInvoiceDao implements InvoiceDao {
 
     private final InternalBus eventBus;
     private final Object monitor = new Object();
-    private final Map<UUID, Invoice> invoices = new LinkedHashMap<UUID, Invoice>();
+    private final Map<UUID, InvoiceModelDao> invoices = new LinkedHashMap<UUID, InvoiceModelDao>();
+    private final Map<UUID, InvoiceItemModelDao> items = new LinkedHashMap<UUID, InvoiceItemModelDao>();
+    private final Map<UUID, InvoicePaymentModelDao> payments = new LinkedHashMap<UUID, InvoicePaymentModelDao>();
 
     @Inject
     public MockInvoiceDao(final InternalBus eventBus) {
@@ -52,13 +51,20 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void create(final Invoice invoice, final int billCycleDay, final boolean isRealInvoice, final InternalCallContext context) {
+    public void createInvoice(final InvoiceModelDao invoice, final List<InvoiceItemModelDao> invoiceItems,
+                              final List<InvoicePaymentModelDao> invoicePayments, final boolean isRealInvoice, final InternalCallContext context) {
         synchronized (monitor) {
             invoices.put(invoice.getId(), invoice);
+            for (final InvoiceItemModelDao invoiceItemModelDao : invoiceItems) {
+                items.put(invoiceItemModelDao.getId(), invoiceItemModelDao);
+            }
+            for (final InvoicePaymentModelDao paymentModelDao : invoicePayments) {
+                payments.put(paymentModelDao.getId(), paymentModelDao);
+            }
         }
         try {
             eventBus.post(new DefaultInvoiceCreationEvent(invoice.getId(), invoice.getAccountId(),
-                                                          invoice.getBalance(), invoice.getCurrency(),
+                                                          InvoiceModelDaoHelper.getBalance(invoice), invoice.getCurrency(),
                                                           null, 1L, 1L), context);
         } catch (InternalBus.EventBusException ex) {
             throw new RuntimeException(ex);
@@ -66,16 +72,16 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public Invoice getById(final UUID id, final InternalTenantContext context) {
+    public InvoiceModelDao getById(final UUID id, final InternalTenantContext context) {
         synchronized (monitor) {
             return invoices.get(id);
         }
     }
 
     @Override
-    public Invoice getByNumber(final Integer number, final InternalTenantContext context) {
+    public InvoiceModelDao getByNumber(final Integer number, final InternalTenantContext context) {
         synchronized (monitor) {
-            for (final Invoice invoice : invoices.values()) {
+            for (final InvoiceModelDao invoice : invoices.values()) {
                 if (invoice.getInvoiceNumber().equals(number)) {
                     return invoice;
                 }
@@ -86,19 +92,19 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public List<Invoice> get(final InternalTenantContext context) {
+    public List<InvoiceModelDao> get(final InternalTenantContext context) {
         synchronized (monitor) {
-            return new ArrayList<Invoice>(invoices.values());
+            return new ArrayList<InvoiceModelDao>(invoices.values());
         }
     }
 
     @Override
-    public List<Invoice> getInvoicesByAccount(final UUID accountId, final InternalTenantContext context) {
-        final List<Invoice> result = new ArrayList<Invoice>();
+    public List<InvoiceModelDao> getInvoicesByAccount(final UUID accountId, final InternalTenantContext context) {
+        final List<InvoiceModelDao> result = new ArrayList<InvoiceModelDao>();
 
         synchronized (monitor) {
-            for (final Invoice invoice : invoices.values()) {
-                if (accountId.equals(invoice.getAccountId()) && !invoice.isMigrationInvoice()) {
+            for (final InvoiceModelDao invoice : invoices.values()) {
+                if (accountId.equals(invoice.getAccountId()) && !invoice.isMigrated()) {
                     result.add(invoice);
                 }
             }
@@ -107,12 +113,12 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public List<Invoice> getInvoicesByAccount(final UUID accountId, final LocalDate fromDate, final InternalTenantContext context) {
-        final List<Invoice> invoicesForAccount = new ArrayList<Invoice>();
+    public List<InvoiceModelDao> getInvoicesByAccount(final UUID accountId, final LocalDate fromDate, final InternalTenantContext context) {
+        final List<InvoiceModelDao> invoicesForAccount = new ArrayList<InvoiceModelDao>();
 
         synchronized (monitor) {
-            for (final Invoice invoice : get(context)) {
-                if (accountId.equals(invoice.getAccountId()) && !invoice.getTargetDate().isBefore(fromDate) && !invoice.isMigrationInvoice()) {
+            for (final InvoiceModelDao invoice : get(context)) {
+                if (accountId.equals(invoice.getAccountId()) && !invoice.getTargetDate().isBefore(fromDate) && !invoice.isMigrated()) {
                     invoicesForAccount.add(invoice);
                 }
             }
@@ -122,13 +128,13 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public List<Invoice> getInvoicesBySubscription(final UUID subscriptionId, final InternalTenantContext context) {
-        final List<Invoice> result = new ArrayList<Invoice>();
+    public List<InvoiceModelDao> getInvoicesBySubscription(final UUID subscriptionId, final InternalTenantContext context) {
+        final List<InvoiceModelDao> result = new ArrayList<InvoiceModelDao>();
 
         synchronized (monitor) {
-            for (final Invoice invoice : invoices.values()) {
-                for (final InvoiceItem item : invoice.getInvoiceItems()) {
-                    if (subscriptionId.equals(item.getSubscriptionId()) && !invoice.isMigrationInvoice()) {
+            for (final InvoiceModelDao invoice : invoices.values()) {
+                for (final InvoiceItemModelDao item : invoice.getInvoiceItems()) {
+                    if (subscriptionId.equals(item.getSubscriptionId()) && !invoice.isMigrated()) {
                         result.add(invoice);
                         break;
                     }
@@ -145,11 +151,9 @@ public class MockInvoiceDao implements InvoiceDao {
     @Override
     public UUID getInvoiceIdByPaymentId(final UUID paymentId, final InternalTenantContext context) {
         synchronized (monitor) {
-            for (final Invoice invoice : invoices.values()) {
-                for (final InvoicePayment payment : invoice.getPayments()) {
-                    if (paymentId.equals(payment.getPaymentId())) {
-                        return invoice.getId();
-                    }
+            for (final InvoicePaymentModelDao payment : payments.values()) {
+                if (paymentId.equals(payment.getPaymentId())) {
+                    return payment.getInvoiceId();
                 }
             }
         }
@@ -157,14 +161,12 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public List<InvoicePayment> getInvoicePayments(final UUID paymentId, final InternalTenantContext context) {
-        final List<InvoicePayment> result = new LinkedList<InvoicePayment>();
+    public List<InvoicePaymentModelDao> getInvoicePayments(final UUID paymentId, final InternalTenantContext context) {
+        final List<InvoicePaymentModelDao> result = new LinkedList<InvoicePaymentModelDao>();
         synchronized (monitor) {
-            for (final Invoice invoice : invoices.values()) {
-                for (final InvoicePayment payment : invoice.getPayments()) {
-                    if (paymentId.equals(payment.getPaymentId())) {
-                        result.add(payment);
-                    }
+            for (final InvoicePaymentModelDao payment : payments.values()) {
+                if (paymentId.equals(payment.getPaymentId())) {
+                    result.add(payment);
                 }
             }
         }
@@ -172,12 +174,9 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void notifyOfPayment(final InvoicePayment invoicePayment, final InternalCallContext context) {
+    public void notifyOfPayment(final InvoicePaymentModelDao invoicePayment, final InternalCallContext context) {
         synchronized (monitor) {
-            final Invoice invoice = invoices.get(invoicePayment.getInvoiceId());
-            if (invoice != null) {
-                invoice.addPayment(invoicePayment);
-            }
+            payments.put(invoicePayment.getId(), invoicePayment);
         }
     }
 
@@ -185,9 +184,9 @@ public class MockInvoiceDao implements InvoiceDao {
     public BigDecimal getAccountBalance(final UUID accountId, final InternalTenantContext context) {
         BigDecimal balance = BigDecimal.ZERO;
 
-        for (final Invoice invoice : get(context)) {
+        for (final InvoiceModelDao invoice : get(context)) {
             if (accountId.equals(invoice.getAccountId())) {
-                balance = balance.add(invoice.getBalance());
+                balance = balance.add(InvoiceModelDaoHelper.getBalance(invoice));
             }
         }
 
@@ -195,11 +194,11 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public List<Invoice> getUnpaidInvoicesByAccountId(final UUID accountId, final LocalDate upToDate, final InternalTenantContext context) {
-        final List<Invoice> unpaidInvoices = new ArrayList<Invoice>();
+    public List<InvoiceModelDao> getUnpaidInvoicesByAccountId(final UUID accountId, final LocalDate upToDate, final InternalTenantContext context) {
+        final List<InvoiceModelDao> unpaidInvoices = new ArrayList<InvoiceModelDao>();
 
-        for (final Invoice invoice : get(context)) {
-            if (accountId.equals(invoice.getAccountId()) && (invoice.getBalance().compareTo(BigDecimal.ZERO) > 0) && !invoice.isMigrationInvoice()) {
+        for (final InvoiceModelDao invoice : get(context)) {
+            if (accountId.equals(invoice.getAccountId()) && (InvoiceModelDaoHelper.getBalance(invoice).compareTo(BigDecimal.ZERO) > 0) && !invoice.isMigrated()) {
                 unpaidInvoices.add(invoice);
             }
         }
@@ -208,11 +207,11 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public List<Invoice> getAllInvoicesByAccount(final UUID accountId, final InternalTenantContext context) {
-        final List<Invoice> result = new ArrayList<Invoice>();
+    public List<InvoiceModelDao> getAllInvoicesByAccount(final UUID accountId, final InternalTenantContext context) {
+        final List<InvoiceModelDao> result = new ArrayList<InvoiceModelDao>();
 
         synchronized (monitor) {
-            for (final Invoice invoice : invoices.values()) {
+            for (final InvoiceModelDao invoice : invoices.values()) {
                 if (accountId.equals(invoice.getAccountId())) {
                     result.add(invoice);
                 }
@@ -222,7 +221,7 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public InvoicePayment postChargeback(final UUID invoicePaymentId, final BigDecimal amount, final InternalCallContext context) throws InvoiceApiException {
+    public InvoicePaymentModelDao postChargeback(final UUID invoicePaymentId, final BigDecimal amount, final InternalCallContext context) throws InvoiceApiException {
         throw new UnsupportedOperationException();
     }
 
@@ -237,47 +236,47 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public List<InvoicePayment> getChargebacksByAccountId(final UUID accountId, final InternalTenantContext context) {
+    public List<InvoicePaymentModelDao> getChargebacksByAccountId(final UUID accountId, final InternalTenantContext context) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public List<InvoicePayment> getChargebacksByPaymentId(final UUID paymentId, final InternalTenantContext context) {
+    public List<InvoicePaymentModelDao> getChargebacksByPaymentId(final UUID paymentId, final InternalTenantContext context) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public InvoicePayment getChargebackById(final UUID chargebackId, final InternalTenantContext context) throws InvoiceApiException {
+    public InvoicePaymentModelDao getChargebackById(final UUID chargebackId, final InternalTenantContext context) throws InvoiceApiException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public InvoiceItem getExternalChargeById(final UUID externalChargeId, final InternalTenantContext context) throws InvoiceApiException {
+    public InvoiceItemModelDao getExternalChargeById(final UUID externalChargeId, final InternalTenantContext context) throws InvoiceApiException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public InvoiceItem insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final UUID bundleId,
-                                            @Nullable final String description, final BigDecimal amount, final LocalDate effectiveDate,
-                                            final Currency currency, final InternalCallContext context) {
+    public InvoiceItemModelDao insertExternalCharge(final UUID accountId, @Nullable final UUID invoiceId, @Nullable final UUID bundleId,
+                                                    @Nullable final String description, final BigDecimal amount, final LocalDate effectiveDate,
+                                                    final Currency currency, final InternalCallContext context) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public InvoiceItem getCreditById(final UUID creditId, final InternalTenantContext context) throws InvoiceApiException {
+    public InvoiceItemModelDao getCreditById(final UUID creditId, final InternalTenantContext context) throws InvoiceApiException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public InvoiceItem insertCredit(final UUID accountId, final UUID invoiceId, final BigDecimal amount, final LocalDate effectiveDate,
-                                    final Currency currency, final InternalCallContext context) {
+    public InvoiceItemModelDao insertCredit(final UUID accountId, final UUID invoiceId, final BigDecimal amount, final LocalDate effectiveDate,
+                                            final Currency currency, final InternalCallContext context) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public InvoiceItem insertInvoiceItemAdjustment(final UUID accountId, final UUID invoiceId, final UUID invoiceItemId,
-                                                   final LocalDate effectiveDate, @Nullable final BigDecimal amount,
-                                                   @Nullable final Currency currency, final InternalCallContext context) {
+    public InvoiceItemModelDao insertInvoiceItemAdjustment(final UUID accountId, final UUID invoiceId, final UUID invoiceItemId,
+                                                           final LocalDate effectiveDate, @Nullable final BigDecimal amount,
+                                                           @Nullable final Currency currency, final InternalCallContext context) {
         throw new UnsupportedOperationException();
     }
 
@@ -287,9 +286,9 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public InvoicePayment createRefund(final UUID paymentId, final BigDecimal amount, final boolean isInvoiceAdjusted,
-                                       final Map<UUID, BigDecimal> invoiceItemIdsWithAmounts, final UUID paymentCookieId,
-                                       final InternalCallContext context)
+    public InvoicePaymentModelDao createRefund(final UUID paymentId, final BigDecimal amount, final boolean isInvoiceAdjusted,
+                                               final Map<UUID, BigDecimal> invoiceItemIdsWithAmounts, final UUID paymentCookieId,
+                                               final InternalCallContext context)
             throws InvoiceApiException {
         return null;
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
index 073c8e5..4b277e5 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
@@ -31,12 +31,9 @@ import org.testng.annotations.Test;
 
 import com.ning.billing.ErrorCode;
 import com.ning.billing.invoice.InvoiceTestSuite;
-import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
-import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
 import com.ning.billing.util.callcontext.InternalTenantContext;
-import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.entity.dao.EntitySqlDao;
 import com.ning.billing.util.svcsapi.bus.InternalBus;
 import com.ning.billing.util.tag.dao.MockTagDao;
@@ -49,15 +46,15 @@ import com.google.common.collect.ImmutableMap;
 public class TestDefaultInvoiceDao extends InvoiceTestSuite {
 
     private InvoiceSqlDao invoiceSqlDao;
-    private AuditedInvoiceDao dao;
+    private DefaultInvoiceDao dao;
 
     @BeforeMethod(groups = "fast")
     public void setUp() throws Exception {
         final IDBI idbi = Mockito.mock(IDBI.class);
         invoiceSqlDao = Mockito.mock(InvoiceSqlDao.class);
         Mockito.when(idbi.onDemand(InvoiceSqlDao.class)).thenReturn(invoiceSqlDao);
-        Mockito.when(invoiceSqlDao.getById(Mockito.anyString(), Mockito.<InternalTenantContext>any())).thenReturn(Mockito.mock(Invoice.class));
-        Mockito.when(invoiceSqlDao.inTransaction(Mockito.<Transaction<Void, EntitySqlDao<Invoice>>>any())).thenAnswer(new Answer() {
+        Mockito.when(invoiceSqlDao.getById(Mockito.anyString(), Mockito.<InternalTenantContext>any())).thenReturn(Mockito.mock(InvoiceModelDao.class));
+        Mockito.when(invoiceSqlDao.inTransaction(Mockito.<Transaction<Void, EntitySqlDao<InvoiceModelDao>>>any())).thenAnswer(new Answer() {
             @Override
             public Object answer(final InvocationOnMock invocation) {
                 final Object[] args = invocation.getArguments();
@@ -73,7 +70,7 @@ public class TestDefaultInvoiceDao extends InvoiceTestSuite {
         final NextBillingDatePoster poster = Mockito.mock(NextBillingDatePoster.class);
         final TagDefinitionDao tagDefinitionDao = new MockTagDefinitionDao();
         final TagDao tagDao = new MockTagDao();
-        dao = new AuditedInvoiceDao(idbi, poster, Mockito.mock(Clock.class), Mockito.mock(InternalBus.class));
+        dao = new DefaultInvoiceDao(idbi, poster, Mockito.mock(InternalBus.class));
     }
 
     @Test(groups = "fast")
@@ -106,7 +103,7 @@ public class TestDefaultInvoiceDao extends InvoiceTestSuite {
 
     private void verifyComputedRefundAmount(final BigDecimal paymentAmount, final BigDecimal requestedAmount,
                                             final Map<UUID, BigDecimal> invoiceItemIdsWithAmounts, final BigDecimal expectedRefundAmount) throws InvoiceApiException {
-        final InvoicePayment invoicePayment = Mockito.mock(InvoicePayment.class);
+        final InvoicePaymentModelDao invoicePayment = Mockito.mock(InvoicePaymentModelDao.class);
         Mockito.when(invoicePayment.getAmount()).thenReturn(paymentAmount);
 
         final BigDecimal actualRefundAmount = dao.computePositiveRefundAmount(invoicePayment, requestedAmount, invoiceItemIdsWithAmounts);
@@ -116,7 +113,7 @@ public class TestDefaultInvoiceDao extends InvoiceTestSuite {
     @Test(groups = "fast")
     public void testFindByNumber() throws Exception {
         final Integer number = Integer.MAX_VALUE;
-        final Invoice invoice = Mockito.mock(Invoice.class);
+        final InvoiceModelDao invoice = Mockito.mock(InvoiceModelDao.class);
         Mockito.when(invoiceSqlDao.getByRecordId(number.longValue(), internalCallContext)).thenReturn(invoice);
 
         Assert.assertEquals(dao.getByNumber(number, internalCallContext), 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 dd8c0ce..29f0d13 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
@@ -16,11 +16,6 @@
 
 package com.ning.billing.invoice.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 java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -72,6 +67,11 @@ import com.ning.billing.util.svcapi.junction.BillingModeType;
 
 import com.google.common.collect.ImmutableMap;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 public class TestInvoiceDao extends InvoiceDaoTestBase {
 
     @Test(groups = "slow")
@@ -80,17 +80,17 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final Invoice invoice = new DefaultInvoice(accountId, clock.getUTCToday(), clock.getUTCToday(), Currency.USD);
         final LocalDate invoiceDate = invoice.getInvoiceDate();
 
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
-        final List<Invoice> invoices = invoiceDao.getInvoicesByAccount(accountId, internalCallContext);
+        final List<InvoiceModelDao> invoices = invoiceDao.getInvoicesByAccount(accountId, internalCallContext);
         assertNotNull(invoices);
         assertEquals(invoices.size(), 1);
-        final Invoice thisInvoice = invoices.get(0);
+        final InvoiceModelDao thisInvoice = invoices.get(0);
         assertEquals(invoice.getAccountId(), accountId);
         assertTrue(thisInvoice.getInvoiceDate().compareTo(invoiceDate) == 0);
         assertEquals(thisInvoice.getCurrency(), Currency.USD);
-        assertEquals(thisInvoice.getNumberOfItems(), 0);
-        assertTrue(thisInvoice.getBalance().compareTo(BigDecimal.ZERO) == 0);
+        assertEquals(thisInvoice.getInvoiceItems().size(), 0);
+        assertTrue(InvoiceModelDaoHelper.getBalance(thisInvoice).compareTo(BigDecimal.ZERO) == 0);
     }
 
     @Test(groups = "slow")
@@ -106,37 +106,32 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                                                                  new BigDecimal("21.00"), new BigDecimal("7.00"), Currency.USD);
 
         invoice.addInvoiceItem(invoiceItem);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
-        final Invoice savedInvoice = invoiceDao.getById(invoiceId, internalCallContext);
+        final InvoiceModelDao savedInvoice = invoiceDao.getById(invoiceId, internalCallContext);
         assertNotNull(savedInvoice);
-        assertEquals(savedInvoice.getBalance().compareTo(new BigDecimal("21.00")), 0);
-        assertEquals(savedInvoice.getPaidAmount(), BigDecimal.ZERO);
+        assertEquals(InvoiceModelDaoHelper.getBalance(savedInvoice).compareTo(new BigDecimal("21.00")), 0);
+        assertEquals(InvoiceModelDaoHelper.getPaidAmount(savedInvoice), BigDecimal.ZERO);
         assertEquals(savedInvoice.getInvoiceItems().size(), 1);
 
         final BigDecimal paymentAmount = new BigDecimal("11.00");
         final UUID paymentId = UUID.randomUUID();
 
-        invoiceDao.notifyOfPayment(new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoiceId, clock.getUTCNow().plusDays(12), paymentAmount, Currency.USD), internalCallContext);
+        final DefaultInvoicePayment defaultInvoicePayment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoiceId, clock.getUTCNow().plusDays(12), paymentAmount, Currency.USD);
+        invoiceDao.notifyOfPayment(new InvoicePaymentModelDao(defaultInvoicePayment), internalCallContext);
 
-        final Invoice retrievedInvoice = invoiceDao.getById(invoiceId, internalCallContext);
+        final InvoiceModelDao retrievedInvoice = invoiceDao.getById(invoiceId, internalCallContext);
         assertNotNull(retrievedInvoice);
         assertEquals(retrievedInvoice.getInvoiceItems().size(), 1);
-        assertEquals(retrievedInvoice.getChargedAmount().compareTo(new BigDecimal("21.00")), 0);
-        assertEquals(retrievedInvoice.getBalance().compareTo(new BigDecimal("10.00")), 0);
-        assertEquals(retrievedInvoice.getPaidAmount().compareTo(new BigDecimal("11.00")), 0);
+        assertEquals(InvoiceModelDaoHelper.getChargedAmount(retrievedInvoice).compareTo(new BigDecimal("21.00")), 0);
+        assertEquals(InvoiceModelDaoHelper.getBalance(retrievedInvoice).compareTo(new BigDecimal("10.00")), 0);
+        assertEquals(InvoiceModelDaoHelper.getPaidAmount(retrievedInvoice).compareTo(new BigDecimal("11.00")), 0);
     }
 
     @Test(groups = "slow")
     public void testRetrievalForNonExistentInvoiceId() throws InvoiceApiException {
-        try {
-            invoiceDao.getById(UUID.randomUUID(), internalCallContext);
-            Assert.fail();
-        } catch (InvoiceApiException e) {
-            if (e.getCode() != ErrorCode.INVOICE_NOT_FOUND.getCode()) {
-                Assert.fail();
-            }
-        }
+        invoiceDao.getById(UUID.randomUUID(), internalCallContext);
+        Assert.fail();
     }
 
     @Test(groups = "slow")
@@ -157,7 +152,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -166,23 +161,23 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId1, "test plan", "test A", startDate, endDate,
                                                                     rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId2, "test plan", "test B", startDate, endDate,
                                                                     rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
 
         final RecurringInvoiceItem item3 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId3, "test plan", "test C", startDate, endDate,
                                                                     rate3, rate3, Currency.USD);
-        invoiceItemSqlDao.create(item3, internalCallContext);
+        createInvoiceItem(item3, internalCallContext);
 
         final RecurringInvoiceItem item4 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId4, "test plan", "test D", startDate, endDate,
                                                                     rate4, rate4, Currency.USD);
-        invoiceItemSqlDao.create(item4, internalCallContext);
+        createInvoiceItem(item4, internalCallContext);
 
         // Create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -191,27 +186,27 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item5 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId1, "test plan", "test phase A", startDate, endDate,
                                                                     rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item5, internalCallContext);
+        createInvoiceItem(item5, internalCallContext);
 
         final RecurringInvoiceItem item6 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId2, "test plan", "test phase B", startDate, endDate,
                                                                     rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(item6, internalCallContext);
+        createInvoiceItem(item6, internalCallContext);
 
         final RecurringInvoiceItem item7 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId3, "test plan", "test phase C", startDate, endDate,
                                                                     rate3, rate3, Currency.USD);
-        invoiceItemSqlDao.create(item7, internalCallContext);
+        createInvoiceItem(item7, internalCallContext);
 
         // Check that each subscription returns the correct number of invoices
-        final List<Invoice> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1, internalCallContext);
+        final List<InvoiceModelDao> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1, internalCallContext);
         assertEquals(items1.size(), 2);
 
-        final List<Invoice> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2, internalCallContext);
+        final List<InvoiceModelDao> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2, internalCallContext);
         assertEquals(items2.size(), 2);
 
-        final List<Invoice> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3, internalCallContext);
+        final List<InvoiceModelDao> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3, internalCallContext);
         assertEquals(items3.size(), 2);
 
-        final List<Invoice> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4, internalCallContext);
+        final List<InvoiceModelDao> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4, internalCallContext);
         assertEquals(items4.size(), 1);
     }
 
@@ -233,7 +228,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -242,23 +237,23 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final FixedPriceInvoiceItem item1 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId1, "test plan", "test A", startDate,
                                                                       rate1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         final FixedPriceInvoiceItem item2 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId2, "test plan", "test B", startDate,
                                                                       rate2, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
 
         final FixedPriceInvoiceItem item3 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId3, "test plan", "test C", startDate,
                                                                       rate3, Currency.USD);
-        invoiceItemSqlDao.create(item3, internalCallContext);
+        createInvoiceItem(item3, internalCallContext);
 
         final FixedPriceInvoiceItem item4 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId4, "test plan", "test D", startDate,
                                                                       rate4, Currency.USD);
-        invoiceItemSqlDao.create(item4, internalCallContext);
+        createInvoiceItem(item4, internalCallContext);
 
         // create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -267,27 +262,27 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final FixedPriceInvoiceItem item5 = new FixedPriceInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId1, "test plan", "test phase A", startDate,
                                                                       rate1, Currency.USD);
-        invoiceItemSqlDao.create(item5, internalCallContext);
+        createInvoiceItem(item5, internalCallContext);
 
         final FixedPriceInvoiceItem item6 = new FixedPriceInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId2, "test plan", "test phase B", startDate,
                                                                       rate2, Currency.USD);
-        invoiceItemSqlDao.create(item6, internalCallContext);
+        createInvoiceItem(item6, internalCallContext);
 
         final FixedPriceInvoiceItem item7 = new FixedPriceInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId3, "test plan", "test phase C", startDate,
                                                                       rate3, Currency.USD);
-        invoiceItemSqlDao.create(item7, internalCallContext);
+        createInvoiceItem(item7, internalCallContext);
 
         // check that each subscription returns the correct number of invoices
-        final List<Invoice> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1, internalCallContext);
+        final List<InvoiceModelDao> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1, internalCallContext);
         assertEquals(items1.size(), 2);
 
-        final List<Invoice> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2, internalCallContext);
+        final List<InvoiceModelDao> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2, internalCallContext);
         assertEquals(items2.size(), 2);
 
-        final List<Invoice> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3, internalCallContext);
+        final List<InvoiceModelDao> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3, internalCallContext);
         assertEquals(items3.size(), 2);
 
-        final List<Invoice> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4, internalCallContext);
+        final List<InvoiceModelDao> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4, internalCallContext);
         assertEquals(items4.size(), 1);
     }
 
@@ -309,7 +304,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -318,39 +313,39 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem recurringItem1 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId1, "test plan", "test A", startDate, endDate,
                                                                              rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(recurringItem1, internalCallContext);
+        createInvoiceItem(recurringItem1, internalCallContext);
 
         final RecurringInvoiceItem recurringItem2 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId2, "test plan", "test B", startDate, endDate,
                                                                              rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(recurringItem2, internalCallContext);
+        createInvoiceItem(recurringItem2, internalCallContext);
 
         final RecurringInvoiceItem recurringItem3 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId3, "test plan", "test C", startDate, endDate,
                                                                              rate3, rate3, Currency.USD);
-        invoiceItemSqlDao.create(recurringItem3, internalCallContext);
+        createInvoiceItem(recurringItem3, internalCallContext);
 
         final RecurringInvoiceItem recurringItem4 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId4, "test plan", "test D", startDate, endDate,
                                                                              rate4, rate4, Currency.USD);
-        invoiceItemSqlDao.create(recurringItem4, internalCallContext);
+        createInvoiceItem(recurringItem4, internalCallContext);
 
         final FixedPriceInvoiceItem fixedItem1 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId1, "test plan", "test A", startDate,
                                                                            rate1, Currency.USD);
-        invoiceItemSqlDao.create(fixedItem1, internalCallContext);
+        createInvoiceItem(fixedItem1, internalCallContext);
 
         final FixedPriceInvoiceItem fixedItem2 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId2, "test plan", "test B", startDate,
                                                                            rate2, Currency.USD);
-        invoiceItemSqlDao.create(fixedItem2, internalCallContext);
+        createInvoiceItem(fixedItem2, internalCallContext);
 
         final FixedPriceInvoiceItem fixedItem3 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId3, "test plan", "test C", startDate,
                                                                            rate3, Currency.USD);
-        invoiceItemSqlDao.create(fixedItem3, internalCallContext);
+        createInvoiceItem(fixedItem3, internalCallContext);
 
         final FixedPriceInvoiceItem fixedItem4 = new FixedPriceInvoiceItem(invoiceId1, accountId, bundleId, subscriptionId4, "test plan", "test D", startDate,
                                                                            rate4, Currency.USD);
-        invoiceItemSqlDao.create(fixedItem4, internalCallContext);
+        createInvoiceItem(fixedItem4, internalCallContext);
 
         // create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -359,38 +354,38 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem recurringItem5 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId1, "test plan", "test phase A", startDate, endDate,
                                                                              rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(recurringItem5, internalCallContext);
+        createInvoiceItem(recurringItem5, internalCallContext);
 
         final RecurringInvoiceItem recurringItem6 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId2, "test plan", "test phase B", startDate, endDate,
                                                                              rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(recurringItem6, internalCallContext);
+        createInvoiceItem(recurringItem6, internalCallContext);
 
         final RecurringInvoiceItem recurringItem7 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId3, "test plan", "test phase C", startDate, endDate,
                                                                              rate3, rate3, Currency.USD);
-        invoiceItemSqlDao.create(recurringItem7, internalCallContext);
+        createInvoiceItem(recurringItem7, internalCallContext);
         final FixedPriceInvoiceItem fixedItem5 = new FixedPriceInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId1, "test plan", "test phase A", startDate,
                                                                            rate1, Currency.USD);
-        invoiceItemSqlDao.create(fixedItem5, internalCallContext);
+        createInvoiceItem(fixedItem5, internalCallContext);
 
         final FixedPriceInvoiceItem fixedItem6 = new FixedPriceInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId2, "test plan", "test phase B", startDate,
                                                                            rate2, Currency.USD);
-        invoiceItemSqlDao.create(fixedItem6, internalCallContext);
+        createInvoiceItem(fixedItem6, internalCallContext);
 
         final FixedPriceInvoiceItem fixedItem7 = new FixedPriceInvoiceItem(invoiceId2, accountId, bundleId, subscriptionId3, "test plan", "test phase C", startDate,
                                                                            rate3, Currency.USD);
-        invoiceItemSqlDao.create(fixedItem7, internalCallContext);
+        createInvoiceItem(fixedItem7, internalCallContext);
 
         // check that each subscription returns the correct number of invoices
-        final List<Invoice> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1, internalCallContext);
+        final List<InvoiceModelDao> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1, internalCallContext);
         assertEquals(items1.size(), 4);
 
-        final List<Invoice> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2, internalCallContext);
+        final List<InvoiceModelDao> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2, internalCallContext);
         assertEquals(items2.size(), 4);
 
-        final List<Invoice> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3, internalCallContext);
+        final List<InvoiceModelDao> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3, internalCallContext);
         assertEquals(items3.size(), 4);
 
-        final List<Invoice> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4, internalCallContext);
+        final List<InvoiceModelDao> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4, internalCallContext);
         assertEquals(items4.size(), 2);
     }
 
@@ -399,13 +394,13 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID accountId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate targetDate2 = new LocalDate(2011, 12, 6);
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate2, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
 
-        List<Invoice> invoices;
+        List<InvoiceModelDao> invoices;
         invoices = invoiceDao.getInvoicesByAccount(accountId, new LocalDate(2011, 1, 1), internalCallContext);
         assertEquals(invoices.size(), 2);
 
@@ -428,7 +423,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -438,15 +433,15 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate,
                                                                     endDate, rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate,
                                                                     endDate, rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
 
         final BigDecimal payment1 = new BigDecimal("48.0");
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice1.getId(), new DateTime(), payment1, Currency.USD);
-        invoicePaymentDao.create(payment, internalCallContext);
+        createPayment(payment, internalCallContext);
 
         final BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(rate1.add(rate2).subtract(payment1)), 0);
@@ -458,7 +453,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -467,10 +462,10 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate,
                                                                     endDate, rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         final CreditAdjInvoiceItem creditItem = new CreditAdjInvoiceItem(invoice1.getId(), accountId, new LocalDate(), rate1.negate(), Currency.USD);
-        invoiceItemSqlDao.create(creditItem, internalCallContext);
+        createInvoiceItem(creditItem, internalCallContext);
 
         final BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(BigDecimal.ZERO), 0);
@@ -482,7 +477,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -492,11 +487,11 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate, endDate,
                                                                     rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate,
                                                                     rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
 
         final BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(rate1.add(rate2)), 0);
@@ -507,11 +502,11 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID accountId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final BigDecimal payment1 = new BigDecimal("48.0");
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice1.getId(), new DateTime(), payment1, Currency.USD);
-        invoicePaymentDao.create(payment, internalCallContext);
+        createPayment(payment, internalCallContext);
 
         final BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(BigDecimal.ZERO.subtract(payment1)), 0);
@@ -533,7 +528,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -545,7 +540,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Recurring item
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate,
                                                                     endDate, rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
         BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("20.00")), 0);
 
@@ -553,7 +548,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID paymentId = UUID.randomUUID();
         final BigDecimal payment1 = rate1;
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoice1.getId(), new DateTime(), payment1, Currency.USD);
-        invoicePaymentDao.create(payment, internalCallContext);
+        createPayment(payment, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
 
@@ -567,24 +562,24 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
     }
 
     @Test(groups = "slow")
-    private void testFullRefundWithRepairAndInvoiceItemAdjustment() throws InvoiceApiException {
+    public void testFullRefundWithRepairAndInvoiceItemAdjustment() throws InvoiceApiException, EntityPersistenceException {
         final BigDecimal refundAmount = new BigDecimal("20.00");
         testRefundWithRepairAndInvoiceItemAdjustmentInternal(refundAmount);
     }
 
     @Test(groups = "slow")
-    private void testPartialRefundWithRepairAndInvoiceItemAdjustment() throws InvoiceApiException {
+    public void testPartialRefundWithRepairAndInvoiceItemAdjustment() throws InvoiceApiException, EntityPersistenceException {
         final BigDecimal refundAmount = new BigDecimal("7.00");
         testRefundWithRepairAndInvoiceItemAdjustmentInternal(refundAmount);
     }
 
-    private void testRefundWithRepairAndInvoiceItemAdjustmentInternal(final BigDecimal refundAmount) throws InvoiceApiException {
+    private void testRefundWithRepairAndInvoiceItemAdjustmentInternal(final BigDecimal refundAmount) throws InvoiceApiException, EntityPersistenceException {
         final UUID accountId = UUID.randomUUID();
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
 
         final Invoice invoice = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -594,7 +589,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Recurring item
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate,
                                                                     endDate, amount, amount, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
         BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("20.00")), 0);
 
@@ -602,16 +597,16 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID paymentId = UUID.randomUUID();
         final BigDecimal payment1 = amount;
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoice.getId(), new DateTime(), payment1, Currency.USD);
-        invoicePaymentDao.create(payment, internalCallContext);
+        createPayment(payment, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
 
         // Repair the item (And add CBA item that should be generated)
         final InvoiceItem repairItem = new RepairAdjInvoiceItem(invoice.getId(), accountId, startDate, endDate, amount.negate(), Currency.USD, item2.getId());
-        invoiceItemSqlDao.create(repairItem, internalCallContext);
+        createInvoiceItem(repairItem, internalCallContext);
 
         final InvoiceItem cbaItem = new CreditBalanceAdjInvoiceItem(invoice.getId(), accountId, startDate, amount, Currency.USD);
-        invoiceItemSqlDao.create(cbaItem, internalCallContext);
+        createInvoiceItem(cbaItem, internalCallContext);
 
         Map<UUID, BigDecimal> itemAdjustment = new HashMap<UUID, BigDecimal>();
         itemAdjustment.put(item2.getId(), refundAmount);
@@ -621,7 +616,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final boolean partialRefund = refundAmount.compareTo(amount) < 0;
         final BigDecimal cba = invoiceDao.getAccountCBA(accountId, internalCallContext);
-        final Invoice savedInvoice = invoiceDao.getById(invoice.getId(), internalCallContext);
+        final InvoiceModelDao savedInvoice = invoiceDao.getById(invoice.getId(), internalCallContext);
         assertEquals(cba.compareTo(new BigDecimal("20.0")), 0);
         if (partialRefund) {
             // IB = 20 (rec) - 20 (repair) + 20 (cba) - (20 -7) = 7;  AB = IB - CBA = 7 - 20 = -13
@@ -666,7 +661,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -678,7 +673,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Fixed Item
         final FixedPriceInvoiceItem item1 = new FixedPriceInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate,
                                                                       amount1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("5.00")), 0);
@@ -686,7 +681,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Recurring item
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate,
                                                                     endDate, rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("25.00")), 0);
 
@@ -694,7 +689,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID paymentId = UUID.randomUUID();
         final BigDecimal payment1 = amount1.add(rate1);
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoice1.getId(), new DateTime(), payment1, Currency.USD);
-        invoicePaymentDao.create(payment, internalCallContext);
+        createPayment(payment, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
 
@@ -702,14 +697,14 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final RepairAdjInvoiceItem item2Repair = new RepairAdjInvoiceItem(invoice1.getId(), accountId, startDate, endDate, rate1.negate(), Currency.USD, item2.getId());
         final RecurringInvoiceItem item2Replace = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate,
                                                                            endDate, rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(item2Repair, internalCallContext);
-        invoiceItemSqlDao.create(item2Replace, internalCallContext);
+        createInvoiceItem(item2Repair, internalCallContext);
+        createInvoiceItem(item2Replace, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("-10.00")), 0);
 
         // CBA
         final CreditBalanceAdjInvoiceItem cbaItem = new CreditBalanceAdjInvoiceItem(invoice1.getId(), accountId, new LocalDate(), balance.negate(), Currency.USD);
-        invoiceItemSqlDao.create(cbaItem, internalCallContext);
+        createInvoiceItem(cbaItem, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("-10.00")), 0);
         BigDecimal cba = invoiceDao.getAccountCBA(accountId, internalCallContext);
@@ -731,20 +726,20 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         // CREATE INVOICE WITH A (just) CBA. Should not happen, but that does not matter for that test
         final CreditBalanceAdjInvoiceItem cbaItem = new CreditBalanceAdjInvoiceItem(invoice1.getId(), accountId, new LocalDate(), new BigDecimal("20.0"), Currency.USD);
-        invoiceItemSqlDao.create(cbaItem, internalCallContext);
+        createInvoiceItem(cbaItem, internalCallContext);
 
-        final InvoiceItem charge = invoiceDao.insertExternalCharge(accountId, null, bundleId, "bla", new BigDecimal("15.0"), clock.getUTCNow().toLocalDate(), Currency.USD, internalCallContext);
+        final InvoiceItemModelDao charge = invoiceDao.insertExternalCharge(accountId, null, bundleId, "bla", new BigDecimal("15.0"), clock.getUTCNow().toLocalDate(), Currency.USD, internalCallContext);
 
-        final Invoice newInvoice = invoiceDao.getById(charge.getInvoiceId(), internalCallContext);
-        List<InvoiceItem> items = newInvoice.getInvoiceItems();
+        final InvoiceModelDao newInvoice = invoiceDao.getById(charge.getInvoiceId(), internalCallContext);
+        List<InvoiceItemModelDao> items = newInvoice.getInvoiceItems();
         assertEquals(items.size(), 2);
-        for (InvoiceItem cur : items) {
+        for (InvoiceItemModelDao cur : items) {
             if (!cur.getId().equals(charge.getId())) {
-                assertEquals(cur.getInvoiceItemType(), InvoiceItemType.CBA_ADJ);
+                assertEquals(cur.getType(), InvoiceItemType.CBA_ADJ);
                 assertTrue(cur.getAmount().compareTo(new BigDecimal("-15.00")) == 0);
                 break;
             }
@@ -757,7 +752,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -769,7 +764,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Fixed Item
         final FixedPriceInvoiceItem item1 = new FixedPriceInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate,
                                                                       amount1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         BigDecimal balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("5.00")), 0);
@@ -777,14 +772,14 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Recurring item
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate,
                                                                     endDate, rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("25.00")), 0);
 
         // Pay the whole thing
         final BigDecimal payment1 = amount1.add(rate1);
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice1.getId(), new DateTime(), payment1, Currency.USD);
-        invoicePaymentDao.create(payment, internalCallContext);
+        createPayment(payment, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
 
@@ -792,14 +787,14 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final RepairAdjInvoiceItem item2Repair = new RepairAdjInvoiceItem(invoice1.getId(), accountId, startDate, endDate, rate1.negate(), Currency.USD, item2.getId());
         final RecurringInvoiceItem item2Replace = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate,
                                                                            endDate, rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(item2Repair, internalCallContext);
-        invoiceItemSqlDao.create(item2Replace, internalCallContext);
+        createInvoiceItem(item2Repair, internalCallContext);
+        createInvoiceItem(item2Replace, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("-10.00")), 0);
 
         // CBA
         final CreditBalanceAdjInvoiceItem cbaItem = new CreditBalanceAdjInvoiceItem(invoice1.getId(), accountId, new LocalDate(), balance.negate(), Currency.USD);
-        invoiceItemSqlDao.create(cbaItem, internalCallContext);
+        createInvoiceItem(cbaItem, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("-10.00")), 0);
         BigDecimal cba = invoiceDao.getAccountCBA(accountId, internalCallContext);
@@ -807,9 +802,9 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // partial REFUND on the payment (along with CBA generated by the system)
         final InvoicePayment refund = new DefaultInvoicePayment(UUID.randomUUID(), InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice1.getId(), new DateTime(), rate2.negate(), Currency.USD, null, payment.getId());
-        invoicePaymentDao.create(refund, internalCallContext);
+        createPayment(refund, internalCallContext);
         final CreditBalanceAdjInvoiceItem cbaItem2 = new CreditBalanceAdjInvoiceItem(invoice1.getId(), accountId, new LocalDate(), rate2.negate(), Currency.USD);
-        invoiceItemSqlDao.create(cbaItem2, internalCallContext);
+        createInvoiceItem(cbaItem2, internalCallContext);
 
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(BigDecimal.ZERO), 0);
@@ -819,11 +814,11 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // NEXT RECURRING on invoice 2
 
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1.plusMonths(1), Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
 
         final RecurringInvoiceItem nextItem = new RecurringInvoiceItem(invoice2.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test bla", startDate.plusMonths(1),
                                                                        endDate.plusMonths(1), rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(nextItem, internalCallContext);
+        createInvoiceItem(nextItem, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("10.00")), 0);
         cba = invoiceDao.getAccountCBA(accountId, internalCallContext);
@@ -831,7 +826,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // FINALLY ISSUE A CREDIT ADJ
         final CreditAdjInvoiceItem creditItem = new CreditAdjInvoiceItem(invoice2.getId(), accountId, new LocalDate(), rate2.negate(), Currency.USD);
-        invoiceItemSqlDao.create(creditItem, internalCallContext);
+        createInvoiceItem(creditItem, internalCallContext);
         balance = invoiceDao.getAccountBalance(accountId, internalCallContext);
         assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
         cba = invoiceDao.getAccountCBA(accountId, internalCallContext);
@@ -850,20 +845,20 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         invoiceDao.insertCredit(accountId, null, creditAmount, effectiveDate, Currency.USD, internalCallContext);
 
-        final List<Invoice> invoices = invoiceDao.getAllInvoicesByAccount(accountId, internalCallContext);
+        final List<InvoiceModelDao> invoices = invoiceDao.getAllInvoicesByAccount(accountId, internalCallContext);
         assertEquals(invoices.size(), 1);
 
-        final Invoice invoice = invoices.get(0);
-        assertTrue(invoice.getBalance().compareTo(BigDecimal.ZERO) == 0);
-        final List<InvoiceItem> invoiceItems = invoice.getInvoiceItems();
+        final InvoiceModelDao invoice = invoices.get(0);
+        assertTrue(InvoiceModelDaoHelper.getBalance(invoice).compareTo(BigDecimal.ZERO) == 0);
+        final List<InvoiceItemModelDao> invoiceItems = invoice.getInvoiceItems();
         assertEquals(invoiceItems.size(), 2);
         boolean foundCredit = false;
         boolean foundCBA = false;
-        for (final InvoiceItem cur : invoiceItems) {
-            if (cur.getInvoiceItemType() == InvoiceItemType.CREDIT_ADJ) {
+        for (final InvoiceItemModelDao cur : invoiceItems) {
+            if (cur.getType() == InvoiceItemType.CREDIT_ADJ) {
                 foundCredit = true;
                 assertTrue(cur.getAmount().compareTo(creditAmount.negate()) == 0);
-            } else if (cur.getInvoiceItemType() == InvoiceItemType.CBA_ADJ) {
+            } else if (cur.getType() == InvoiceItemType.CBA_ADJ) {
                 foundCBA = true;
                 assertTrue(cur.getAmount().compareTo(creditAmount) == 0);
             }
@@ -904,7 +899,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Create one invoice with a fixed invoice item
         final LocalDate targetDate = new LocalDate(2011, 2, 15);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
 
@@ -913,27 +908,27 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Fixed Item
         final FixedPriceInvoiceItem item1 = new FixedPriceInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate,
                                                                       amount1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         // Create the credit item
         final LocalDate effectiveDate = new LocalDate(2011, 3, 1);
 
         invoiceDao.insertCredit(accountId, invoice1.getId(), creditAmount, effectiveDate, Currency.USD, internalCallContext);
 
-        final List<Invoice> invoices = invoiceDao.getAllInvoicesByAccount(accountId, internalCallContext);
+        final List<InvoiceModelDao> invoices = invoiceDao.getAllInvoicesByAccount(accountId, internalCallContext);
         assertEquals(invoices.size(), 1);
 
-        final Invoice invoice = invoices.get(0);
-        assertTrue(invoice.getBalance().compareTo(expectedBalance) == 0);
-        final List<InvoiceItem> invoiceItems = invoice.getInvoiceItems();
+        final InvoiceModelDao invoice = invoices.get(0);
+        assertTrue(InvoiceModelDaoHelper.getBalance(invoice).compareTo(expectedBalance) == 0);
+        final List<InvoiceItemModelDao> invoiceItems = invoice.getInvoiceItems();
         assertEquals(invoiceItems.size(), expectCBA ? 3 : 2);
         boolean foundCredit = false;
         boolean foundCBA = false;
-        for (final InvoiceItem cur : invoiceItems) {
-            if (cur.getInvoiceItemType() == InvoiceItemType.CREDIT_ADJ) {
+        for (final InvoiceItemModelDao cur : invoiceItems) {
+            if (cur.getType() == InvoiceItemType.CREDIT_ADJ) {
                 foundCredit = true;
                 assertTrue(cur.getAmount().compareTo(creditAmount.negate()) == 0);
-            } else if (cur.getInvoiceItemType() == InvoiceItemType.CBA_ADJ) {
+            } else if (cur.getType() == InvoiceItemType.CBA_ADJ) {
                 foundCBA = true;
             }
         }
@@ -947,7 +942,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -957,14 +952,14 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate, endDate,
                                                                     rate1, rate1, Currency.USD);
-        invoiceItemSqlDao.create(item1, internalCallContext);
+        createInvoiceItem(item1, internalCallContext);
 
         final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate,
                                                                     rate2, rate2, Currency.USD);
-        invoiceItemSqlDao.create(item2, internalCallContext);
+        createInvoiceItem(item2, internalCallContext);
 
         LocalDate upToDate;
-        Collection<Invoice> invoices;
+        Collection<InvoiceModelDao> invoices;
 
         upToDate = new LocalDate(2011, 1, 1);
         invoices = invoiceDao.getUnpaidInvoicesByAccountId(accountId, upToDate, internalCallContext);
@@ -976,7 +971,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final LocalDate targetDate2 = new LocalDate(2011, 7, 1);
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate2, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
 
         final LocalDate startDate2 = new LocalDate(2011, 6, 1);
         final LocalDate endDate2 = startDate2.plusMonths(3);
@@ -985,7 +980,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item3 = new RecurringInvoiceItem(invoice2.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase C", startDate2, endDate2,
                                                                     rate3, rate3, Currency.USD);
-        invoiceItemSqlDao.create(item3, internalCallContext);
+        createInvoiceItem(item3, internalCallContext);
 
         upToDate = new LocalDate(2011, 1, 1);
         invoices = invoiceDao.getUnpaidInvoicesByAccountId(accountId, upToDate, internalCallContext);
@@ -1046,14 +1041,14 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice2.getBalance(), FIVE);
         invoiceList.add(invoice2);
 
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
 
-        final Invoice savedInvoice1 = invoiceDao.getById(invoice1.getId(), internalCallContext);
-        assertEquals(savedInvoice1.getBalance(), ZERO);
+        final InvoiceModelDao savedInvoice1 = invoiceDao.getById(invoice1.getId(), internalCallContext);
+        assertEquals(InvoiceModelDaoHelper.getBalance(savedInvoice1), ZERO);
 
-        final Invoice savedInvoice2 = invoiceDao.getById(invoice2.getId(), internalCallContext);
-        assertEquals(savedInvoice2.getBalance(), FIFTEEN);
+        final InvoiceModelDao savedInvoice2 = invoiceDao.getById(invoice2.getId(), internalCallContext);
+        assertEquals(InvoiceModelDaoHelper.getBalance(savedInvoice2), FIFTEEN);
     }
 
     @Test(groups = "slow")
@@ -1121,7 +1116,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final List<Invoice> invoiceList = new ArrayList<Invoice>();
         invoiceList.add(invoice1);
 
-        //invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), internalCallContext);
+        //createInvoice(invoice1, invoice1.getTargetDate().getDayOfMonth(), internalCallContext);
 
         final DateTime effectiveDate2 = effectiveDate1.plusDays(30);
         final BillingEvent event2 = createMockBillingEvent(null, subscription, effectiveDate2, plan, phase2, null,
@@ -1136,7 +1131,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         invoiceList.add(invoice2);
 
-        //invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), internalCallContext);
+        //createInvoice(invoice2, invoice2.getTargetDate().getDayOfMonth(), internalCallContext);
 
         final DateTime effectiveDate3 = effectiveDate2.plusMonths(1);
         final Invoice invoice3 = generator.generateInvoice(accountId, events, invoiceList, new LocalDate(effectiveDate3), DateTimeZone.UTC, Currency.USD);
@@ -1144,7 +1139,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice3.getNumberOfItems(), 1);
         assertEquals(invoice3.getBalance().compareTo(cheapAmount), 0);
 
-        //invoiceDao.create(invoice3, invoice3.getTargetDate().getDayOfMonth(), internalCallContext);
+        //createInvoice(invoice3, invoice3.getTargetDate().getDayOfMonth(), internalCallContext);
     }
 
     @Test(groups = "slow")
@@ -1189,12 +1184,12 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice.getNumberOfItems(), 2);
         assertEquals(invoice.getBalance().compareTo(cheapAmount), 0);
 
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        final Invoice savedInvoice = invoiceDao.getById(invoice.getId(), internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
+        final InvoiceModelDao savedInvoice = invoiceDao.getById(invoice.getId(), internalCallContext);
 
         assertNotNull(savedInvoice);
-        assertEquals(savedInvoice.getNumberOfItems(), 2);
-        assertEquals(savedInvoice.getBalance().compareTo(cheapAmount), 0);
+        assertEquals(savedInvoice.getInvoiceItems().size(), 2);
+        assertEquals(InvoiceModelDaoHelper.getBalance(savedInvoice).compareTo(cheapAmount), 0);
     }
 
     @Test(groups = "slow")
@@ -1219,26 +1214,27 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                                                                  recuringStartDate, recuringEndDate, new BigDecimal("239.00"), new BigDecimal("239.00"), Currency.USD);
 
         invoice.addInvoiceItem(invoiceItem);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
         ((ClockMock) clock).addDays(1);
 
         // SECOND CREATE THE PAYMENT
         final BigDecimal paymentAmount = new BigDecimal("239.00");
         final UUID paymentId = UUID.randomUUID();
-        invoiceDao.notifyOfPayment(new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoiceId, clock.getUTCNow(), paymentAmount, Currency.USD), internalCallContext);
+        final DefaultInvoicePayment defaultInvoicePayment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoiceId, clock.getUTCNow(), paymentAmount, Currency.USD);
+        invoiceDao.notifyOfPayment(new InvoicePaymentModelDao(defaultInvoicePayment), internalCallContext);
 
         // AND THEN THIRD THE REFUND
         final Map<UUID, BigDecimal> invoiceItemMap = new HashMap<UUID, BigDecimal>();
         invoiceItemMap.put(invoiceItem.getId(), new BigDecimal("239.00"));
         invoiceDao.createRefund(paymentId, paymentAmount, true, invoiceItemMap, UUID.randomUUID(), internalCallContext);
 
-        final Invoice savedInvoice = invoiceDao.getById(invoiceId, internalCallContext);
+        final InvoiceModelDao savedInvoice = invoiceDao.getById(invoiceId, internalCallContext);
         assertNotNull(savedInvoice);
         assertEquals(savedInvoice.getInvoiceItems().size(), 2);
 
         final List<Invoice> invoices = new ArrayList<Invoice>();
-        invoices.add(savedInvoice);
+        invoices.add(new DefaultInvoice(savedInvoice));
 
         // NOW COMPUTE A DIFFERENT ITEM TO TRIGGER REPAIR
         final BillingEventSet events = new MockBillingEventSet();
@@ -1259,10 +1255,10 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                                                            "new-event", 1L, SubscriptionTransitionType.CREATE);
         events.add(event1);
         final Invoice newInvoice = generator.generateInvoice(UUID.randomUUID(), events, invoices, targetDate, DateTimeZone.UTC, Currency.USD);
-        invoiceDao.create(newInvoice, newInvoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
+        createInvoice(newInvoice, true, internalCallContext);
 
         // VERIFY THAT WE STILL HAVE ONLY 2 ITEMS, MENAING THERE WERE NO REPAIR AND NO CBA GENERATED
-        final Invoice firstInvoice = invoiceDao.getById(invoiceId, internalCallContext);
+        final Invoice firstInvoice = new DefaultInvoice(invoiceDao.getById(invoiceId, internalCallContext));
         assertNotNull(firstInvoice);
         assertEquals(firstInvoice.getInvoiceItems().size(), 2);
     }
@@ -1295,8 +1291,8 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         Invoice invoice1 = generator.generateInvoice(UUID.randomUUID(), events, invoices, new LocalDate(targetDate1), DateTimeZone.UTC, Currency.USD);
         invoices.add(invoice1);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoice1 = invoiceDao.getById(invoice1.getId(), internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
+        invoice1 = new DefaultInvoice(invoiceDao.getById(invoice1.getId(), internalCallContext));
         assertNotNull(invoice1.getInvoiceNumber());
 
         final BillingEvent event2 = createMockBillingEvent(null, subscription, targetDate1, plan, phase2, null,
@@ -1305,8 +1301,8 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                                                            "testEvent2", 2L, SubscriptionTransitionType.CHANGE);
         events.add(event2);
         Invoice invoice2 = generator.generateInvoice(UUID.randomUUID(), events, invoices, new LocalDate(targetDate2), DateTimeZone.UTC, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoice2 = invoiceDao.getById(invoice2.getId(), internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
+        invoice2 = new DefaultInvoice(invoiceDao.getById(invoice2.getId(), internalCallContext));
         assertNotNull(invoice2.getInvoiceNumber());
     }
 
@@ -1330,10 +1326,10 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final CreditBalanceAdjInvoiceItem creditBalanceAdjInvoiceItem1 = new CreditBalanceAdjInvoiceItem(fixedItem1.getInvoiceId(), fixedItem1.getAccountId(),
                                                                                                          fixedItem1.getStartDate(), fixedItem1.getAmount(),
                                                                                                          fixedItem1.getCurrency());
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceItemSqlDao.create(fixedItem1, internalCallContext);
-        invoiceItemSqlDao.create(repairAdjInvoiceItem, internalCallContext);
-        invoiceItemSqlDao.create(creditBalanceAdjInvoiceItem1, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
+        createInvoiceItem(fixedItem1, internalCallContext);
+        createInvoiceItem(repairAdjInvoiceItem, internalCallContext);
+        createInvoiceItem(creditBalanceAdjInvoiceItem1, internalCallContext);
 
         // Verify scenario - no CBA should have been used
         Assert.assertEquals(invoiceDao.getAccountCBA(accountId, internalCallContext).doubleValue(), 10.00);
@@ -1367,10 +1363,10 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final CreditBalanceAdjInvoiceItem creditBalanceAdjInvoiceItem1 = new CreditBalanceAdjInvoiceItem(fixedItem1.getInvoiceId(), fixedItem1.getAccountId(),
                                                                                                          fixedItem1.getStartDate(), fixedItem1.getAmount(),
                                                                                                          fixedItem1.getCurrency());
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceItemSqlDao.create(fixedItem1, internalCallContext);
-        invoiceItemSqlDao.create(repairAdjInvoiceItem, internalCallContext);
-        invoiceItemSqlDao.create(creditBalanceAdjInvoiceItem1, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
+        createInvoiceItem(fixedItem1, internalCallContext);
+        createInvoiceItem(repairAdjInvoiceItem, internalCallContext);
+        createInvoiceItem(creditBalanceAdjInvoiceItem1, internalCallContext);
 
         // Create invoice 2
         // Scenario: single item
@@ -1382,9 +1378,9 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final CreditBalanceAdjInvoiceItem creditBalanceAdjInvoiceItem2 = new CreditBalanceAdjInvoiceItem(fixedItem2.getInvoiceId(), fixedItem2.getAccountId(),
                                                                                                          fixedItem2.getStartDate(), fixedItem2.getAmount().negate(),
                                                                                                          fixedItem2.getCurrency());
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceItemSqlDao.create(fixedItem2, internalCallContext);
-        invoiceItemSqlDao.create(creditBalanceAdjInvoiceItem2, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
+        createInvoiceItem(fixedItem2, internalCallContext);
+        createInvoiceItem(creditBalanceAdjInvoiceItem2, internalCallContext);
 
         // Verify scenario - half of the CBA should have been used
         Assert.assertEquals(invoiceDao.getAccountCBA(accountId, internalCallContext).doubleValue(), 5.00);
@@ -1420,10 +1416,10 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final CreditBalanceAdjInvoiceItem creditBalanceAdjInvoiceItem1 = new CreditBalanceAdjInvoiceItem(fixedItem1.getInvoiceId(), fixedItem1.getAccountId(),
                                                                                                          fixedItem1.getStartDate(), fixedItem1.getAmount(),
                                                                                                          fixedItem1.getCurrency());
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceItemSqlDao.create(fixedItem1, internalCallContext);
-        invoiceItemSqlDao.create(repairAdjInvoiceItem, internalCallContext);
-        invoiceItemSqlDao.create(creditBalanceAdjInvoiceItem1, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
+        createInvoiceItem(fixedItem1, internalCallContext);
+        createInvoiceItem(repairAdjInvoiceItem, internalCallContext);
+        createInvoiceItem(creditBalanceAdjInvoiceItem1, internalCallContext);
 
         // Create invoice 2
         // Scenario: single item
@@ -1435,9 +1431,9 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final CreditBalanceAdjInvoiceItem creditBalanceAdjInvoiceItem2 = new CreditBalanceAdjInvoiceItem(fixedItem2.getInvoiceId(), fixedItem2.getAccountId(),
                                                                                                          fixedItem2.getStartDate(), fixedItem2.getAmount().negate(),
                                                                                                          fixedItem2.getCurrency());
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceItemSqlDao.create(fixedItem2, internalCallContext);
-        invoiceItemSqlDao.create(creditBalanceAdjInvoiceItem2, internalCallContext);
+        createInvoice(invoice2, true, internalCallContext);
+        createInvoiceItem(fixedItem2, internalCallContext);
+        createInvoiceItem(creditBalanceAdjInvoiceItem2, internalCallContext);
 
         // Create invoice 3
         // Scenario: single item
@@ -1449,9 +1445,9 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final CreditBalanceAdjInvoiceItem creditBalanceAdjInvoiceItem3 = new CreditBalanceAdjInvoiceItem(fixedItem3.getInvoiceId(), fixedItem3.getAccountId(),
                                                                                                          fixedItem3.getStartDate(), fixedItem3.getAmount().negate(),
                                                                                                          fixedItem3.getCurrency());
-        invoiceDao.create(invoice3, invoice3.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceItemSqlDao.create(fixedItem3, internalCallContext);
-        invoiceItemSqlDao.create(creditBalanceAdjInvoiceItem3, internalCallContext);
+        createInvoice(invoice3, true, internalCallContext);
+        createInvoiceItem(fixedItem3, internalCallContext);
+        createInvoiceItem(creditBalanceAdjInvoiceItem3, internalCallContext);
 
         // Verify scenario - all CBA should have been used
         Assert.assertEquals(invoiceDao.getAccountCBA(accountId, internalCallContext).doubleValue(), 0.00);
@@ -1485,9 +1481,9 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final CreditBalanceAdjInvoiceItem creditBalanceAdjInvoiceItem1 = new CreditBalanceAdjInvoiceItem(invoice1.getId(), invoice1.getAccountId(),
                                                                                                          invoice1.getInvoiceDate(), repairAdjInvoiceItem.getAmount().negate(),
                                                                                                          invoice1.getCurrency());
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceItemSqlDao.create(repairAdjInvoiceItem, internalCallContext);
-        invoiceItemSqlDao.create(creditBalanceAdjInvoiceItem1, internalCallContext);
+        createInvoice(invoice1, true, internalCallContext);
+        createInvoiceItem(repairAdjInvoiceItem, internalCallContext);
+        createInvoiceItem(creditBalanceAdjInvoiceItem1, internalCallContext);
 
         // Verify scenario
         Assert.assertEquals(invoiceDao.getAccountCBA(accountId, internalCallContext).doubleValue(), 10.00);
@@ -1506,10 +1502,4 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         Assert.assertEquals(invoiceDao.getAccountCBA(accountId, internalCallContext).doubleValue(), 10.00);
         verifyInvoice(invoice1.getId(), 0.00, 10.00);
     }
-
-    private void verifyInvoice(final UUID invoiceId, final double balance, final double cbaAmount) throws InvoiceApiException {
-        final Invoice invoice = invoiceDao.getById(invoiceId, internalCallContext);
-        Assert.assertEquals(invoice.getBalance().doubleValue(), balance);
-        Assert.assertEquals(invoice.getCBAAmount().doubleValue(), cbaAmount);
-    }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDaoForItemAdjustment.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDaoForItemAdjustment.java
index 8182355..feb49b4 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDaoForItemAdjustment.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDaoForItemAdjustment.java
@@ -63,7 +63,7 @@ public class TestInvoiceDaoForItemAdjustment extends InvoiceDaoTestBase {
                                                                  new LocalDate(2010, 1, 1), new LocalDate(2010, 4, 1),
                                                                  INVOICE_ITEM_AMOUNT, new BigDecimal("7.00"), Currency.USD);
         invoice.addInvoiceItem(invoiceItem);
-        invoiceDao.create(invoice, 1, true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
         try {
             invoiceDao.insertInvoiceItemAdjustment(invoice.getAccountId(), UUID.randomUUID(), invoiceItem.getId(), new LocalDate(2010, 1, 1), null, null, internalCallContext);
@@ -81,9 +81,9 @@ public class TestInvoiceDaoForItemAdjustment extends InvoiceDaoTestBase {
                                                                  new LocalDate(2010, 1, 1), new LocalDate(2010, 4, 1),
                                                                  INVOICE_ITEM_AMOUNT, new BigDecimal("7.00"), Currency.USD);
         invoice.addInvoiceItem(invoiceItem);
-        invoiceDao.create(invoice, 1, true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
-        final InvoiceItem adjustedInvoiceItem = createAndCheckAdjustment(invoice, invoiceItem, null);
+        final InvoiceItemModelDao adjustedInvoiceItem = createAndCheckAdjustment(invoice, invoiceItem, null);
         Assert.assertEquals(adjustedInvoiceItem.getAmount().compareTo(invoiceItem.getAmount().negate()), 0);
     }
 
@@ -95,23 +95,22 @@ public class TestInvoiceDaoForItemAdjustment extends InvoiceDaoTestBase {
                                                                  new LocalDate(2010, 1, 1), new LocalDate(2010, 4, 1),
                                                                  INVOICE_ITEM_AMOUNT, new BigDecimal("7.00"), Currency.USD);
         invoice.addInvoiceItem(invoiceItem);
-        invoiceDao.create(invoice, 1, true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
-        final InvoiceItem adjustedInvoiceItem = createAndCheckAdjustment(invoice, invoiceItem, BigDecimal.TEN);
+        final InvoiceItemModelDao adjustedInvoiceItem = createAndCheckAdjustment(invoice, invoiceItem, BigDecimal.TEN);
         Assert.assertEquals(adjustedInvoiceItem.getAmount().compareTo(BigDecimal.TEN.negate()), 0);
     }
 
-    private InvoiceItem createAndCheckAdjustment(final Invoice invoice, final InvoiceItem invoiceItem, final BigDecimal amount) throws InvoiceApiException {
+    private InvoiceItemModelDao createAndCheckAdjustment(final Invoice invoice, final InvoiceItem invoiceItem, final BigDecimal amount) throws InvoiceApiException {
         final LocalDate effectiveDate = new LocalDate(2010, 1, 1);
-        final InvoiceItem adjustedInvoiceItem = invoiceDao.insertInvoiceItemAdjustment(invoice.getAccountId(), invoice.getId(), invoiceItem.getId(),
+        final InvoiceItemModelDao adjustedInvoiceItem = invoiceDao.insertInvoiceItemAdjustment(invoice.getAccountId(), invoice.getId(), invoiceItem.getId(),
                                                                                        effectiveDate, amount, null, internalCallContext);
         Assert.assertEquals(adjustedInvoiceItem.getAccountId(), invoiceItem.getAccountId());
         Assert.assertNull(adjustedInvoiceItem.getBundleId());
         Assert.assertEquals(adjustedInvoiceItem.getCurrency(), invoiceItem.getCurrency());
-        Assert.assertEquals(adjustedInvoiceItem.getDescription(), "Invoice item adjustment");
         Assert.assertEquals(adjustedInvoiceItem.getEndDate(), effectiveDate);
         Assert.assertEquals(adjustedInvoiceItem.getInvoiceId(), invoiceItem.getInvoiceId());
-        Assert.assertEquals(adjustedInvoiceItem.getInvoiceItemType(), InvoiceItemType.ITEM_ADJ);
+        Assert.assertEquals(adjustedInvoiceItem.getType(), InvoiceItemType.ITEM_ADJ);
         Assert.assertEquals(adjustedInvoiceItem.getLinkedItemId(), invoiceItem.getId());
         Assert.assertNull(adjustedInvoiceItem.getPhaseName());
         Assert.assertNull(adjustedInvoiceItem.getPlanName());
@@ -120,14 +119,14 @@ public class TestInvoiceDaoForItemAdjustment extends InvoiceDaoTestBase {
         Assert.assertNull(adjustedInvoiceItem.getSubscriptionId());
 
         // Retrieve the item by id
-        final InvoiceItem retrievedInvoiceItem = invoiceItemSqlDao.getById(adjustedInvoiceItem.getId().toString(), internalCallContext);
+        final InvoiceItemModelDao retrievedInvoiceItem = invoiceItemSqlDao.getById(adjustedInvoiceItem.getId().toString(), internalCallContext);
         Assert.assertEquals(retrievedInvoiceItem, adjustedInvoiceItem);
 
         // Retrieve the item by invoice id
-        final Invoice retrievedInvoice = invoiceDao.getById(adjustedInvoiceItem.getInvoiceId(), internalCallContext);
-        final List<InvoiceItem> invoiceItems = retrievedInvoice.getInvoiceItems();
+        final InvoiceModelDao retrievedInvoice = invoiceDao.getById(adjustedInvoiceItem.getInvoiceId(), internalCallContext);
+        final List<InvoiceItemModelDao> invoiceItems = retrievedInvoice.getInvoiceItems();
         Assert.assertEquals(invoiceItems.size(), 2);
-        final InvoiceItem retrievedByInvoiceInvoiceItem;
+        final InvoiceItemModelDao retrievedByInvoiceInvoiceItem;
         if (invoiceItems.get(0).getId().equals(adjustedInvoiceItem.getId())) {
             retrievedByInvoiceInvoiceItem = invoiceItems.get(0);
         } else {
@@ -137,9 +136,9 @@ public class TestInvoiceDaoForItemAdjustment extends InvoiceDaoTestBase {
 
         // Verify the invoice balance
         if (amount == null) {
-            Assert.assertEquals(retrievedInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+            Assert.assertEquals(InvoiceModelDaoHelper.getBalance(retrievedInvoice).compareTo(BigDecimal.ZERO), 0);
         } else {
-            Assert.assertEquals(retrievedInvoice.getBalance().compareTo(INVOICE_ITEM_AMOUNT.add(amount.negate())), 0);
+            Assert.assertEquals(InvoiceModelDaoHelper.getBalance(retrievedInvoice).compareTo(INVOICE_ITEM_AMOUNT.add(amount.negate())), 0);
         }
 
         return adjustedInvoiceItem;
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 59ae006..c3129ef 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
@@ -50,9 +50,9 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
 
         final RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "test plan", "test phase", startDate, endDate,
                                                                    rate, rate, Currency.USD);
-        invoiceItemSqlDao.create(item, internalCallContext);
+        createInvoiceItem(item, internalCallContext);
 
-        final RecurringInvoiceItem thisItem = (RecurringInvoiceItem) invoiceItemSqlDao.getById(item.getId().toString(), internalCallContext);
+        final InvoiceItemModelDao thisItem = invoiceItemSqlDao.getById(item.getId().toString(), internalCallContext);
         assertNotNull(thisItem);
         assertEquals(thisItem.getId(), item.getId());
         assertEquals(thisItem.getInvoiceId(), item.getInvoiceId());
@@ -80,10 +80,10 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
             final RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId,
                                                                        "test plan", "test phase", startDate.plusMonths(i), startDate.plusMonths(i + 1),
                                                                        rate, rate, Currency.USD);
-            invoiceItemSqlDao.create(item, internalCallContext);
+            createInvoiceItem(item, internalCallContext);
         }
 
-        final List<InvoiceItem> items = invoiceItemSqlDao.getInvoiceItemsBySubscription(subscriptionId.toString(), internalCallContext);
+        final List<InvoiceItemModelDao> items = invoiceItemSqlDao.getInvoiceItemsBySubscription(subscriptionId.toString(), internalCallContext);
         assertEquals(items.size(), 3);
     }
 
@@ -102,10 +102,10 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
             final RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId,
                                                                        "test plan", "test phase", startDate, startDate.plusMonths(1),
                                                                        amount, amount, Currency.USD);
-            invoiceItemSqlDao.create(item, internalCallContext);
+            createInvoiceItem(item, internalCallContext);
         }
 
-        final List<InvoiceItem> items = invoiceItemSqlDao.getInvoiceItemsByInvoice(invoiceId.toString(), internalCallContext);
+        final List<InvoiceItemModelDao> items = invoiceItemSqlDao.getInvoiceItemsByInvoice(invoiceId.toString(), internalCallContext);
         assertEquals(items.size(), 5);
     }
 
@@ -116,7 +116,7 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
         final LocalDate targetDate = new LocalDate(2011, 5, 23);
         final DefaultInvoice invoice = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
 
-        invoiceDao.create(invoice, targetDate.getDayOfMonth(), true, internalCallContext);
+        createInvoice(invoice, true, internalCallContext);
 
         final UUID invoiceId = invoice.getId();
         final LocalDate startDate = new LocalDate(2011, 3, 1);
@@ -127,9 +127,9 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
         final RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId,
                                                                    "test plan", "test phase", startDate, startDate.plusMonths(1),
                                                                    rate, rate, Currency.USD);
-        invoiceItemSqlDao.create(item, internalCallContext);
+        createInvoiceItem(item, internalCallContext);
 
-        final List<InvoiceItem> items = invoiceItemSqlDao.getInvoiceItemsByAccount(accountId.toString(), internalCallContext);
+        final List<InvoiceItemModelDao> items = invoiceItemSqlDao.getInvoiceItemsByAccount(accountId.toString(), internalCallContext);
         assertEquals(items.size(), 1);
     }
 
@@ -140,9 +140,9 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
         final LocalDate creditDate = new LocalDate(2012, 4, 1);
 
         final InvoiceItem creditInvoiceItem = new CreditBalanceAdjInvoiceItem(invoiceId, accountId, creditDate, TEN, Currency.USD);
-        invoiceItemSqlDao.create(creditInvoiceItem, internalCallContext);
+        createInvoiceItem(creditInvoiceItem, internalCallContext);
 
-        final InvoiceItem savedItem = invoiceItemSqlDao.getById(creditInvoiceItem.getId().toString(), internalCallContext);
+        final InvoiceItemModelDao savedItem = invoiceItemSqlDao.getById(creditInvoiceItem.getId().toString(), internalCallContext);
         assertEquals(savedItem, creditInvoiceItem);
     }
 
@@ -154,9 +154,9 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
 
         final InvoiceItem fixedPriceInvoiceItem = new FixedPriceInvoiceItem(invoiceId, accountId, UUID.randomUUID(),
                                                                             UUID.randomUUID(), "test plan", "test phase", startDate, TEN, Currency.USD);
-        invoiceItemSqlDao.create(fixedPriceInvoiceItem, internalCallContext);
+        createInvoiceItem(fixedPriceInvoiceItem, internalCallContext);
 
-        final InvoiceItem savedItem = invoiceItemSqlDao.getById(fixedPriceInvoiceItem.getId().toString(), internalCallContext);
+        final InvoiceItemModelDao savedItem = invoiceItemSqlDao.getById(fixedPriceInvoiceItem.getId().toString(), internalCallContext);
         assertEquals(savedItem, fixedPriceInvoiceItem);
     }
 
@@ -169,9 +169,9 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
         final LocalDate startDate = new LocalDate(2012, 4, 1);
         final InvoiceItem externalChargeInvoiceItem = new ExternalChargeInvoiceItem(invoiceId, accountId, bundleId, description,
                                                                                     startDate, TEN, Currency.USD);
-        invoiceItemSqlDao.create(externalChargeInvoiceItem, internalCallContext);
+        createInvoiceItem(externalChargeInvoiceItem, internalCallContext);
 
-        final InvoiceItem savedItem = invoiceItemSqlDao.getById(externalChargeInvoiceItem.getId().toString(), internalCallContext);
+        final InvoiceItemModelDao savedItem = invoiceItemSqlDao.getById(externalChargeInvoiceItem.getId().toString(), internalCallContext);
         assertEquals(savedItem, externalChargeInvoiceItem);
     }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
index 87de546..94030bb 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -49,6 +49,7 @@ import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceItemType;
 import com.ning.billing.invoice.api.InvoiceNotifier;
 import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
 import com.ning.billing.invoice.generator.InvoiceGenerator;
 import com.ning.billing.invoice.notification.NextBillingDateNotifier;
 import com.ning.billing.invoice.notification.NullInvoiceNotifier;
@@ -168,13 +169,13 @@ public class TestInvoiceDispatcher extends InvoicingTestBase {
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
         final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountInternalApi, billingApi, entitlementInternalApi, invoiceDao,
                                                                    invoiceNotifier, locker, busService.getBus(),
-                                                                   clock, new InternalCallContextFactory(getMysqlTestingHelper().getDBI(), clock));
+                                                                   clock);
 
         Invoice invoice = dispatcher.processAccount(accountId, target, true, internalCallContext);
         Assert.assertNotNull(invoice);
 
         final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(callContext);
-        List<Invoice> invoices = invoiceDao.getInvoicesByAccount(accountId, internalTenantContext);
+        List<InvoiceModelDao> invoices = invoiceDao.getInvoicesByAccount(accountId, internalTenantContext);
         Assert.assertEquals(invoices.size(), 0);
 
         // Try it again to double check
@@ -222,7 +223,7 @@ public class TestInvoiceDispatcher extends InvoicingTestBase {
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
         final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountInternalApi, billingApi, entitlementInternalApi, invoiceDao,
                                                                    invoiceNotifier, locker, busService.getBus(),
-                                                                   clock, internalCallContextFactory);
+                                                                   clock);
 
         final Invoice invoice = dispatcher.processAccount(account.getId(), new DateTime("2012-07-30T00:00:00.000Z"), false, internalCallContext);
         Assert.assertNotNull(invoice);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/InvoiceTestUtils.java b/invoice/src/test/java/com/ning/billing/invoice/tests/InvoiceTestUtils.java
index 574457f..e281c2b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/InvoiceTestUtils.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/InvoiceTestUtils.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.UUID;
 
 import org.mockito.Mockito;
+import org.testng.Assert;
 
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
@@ -29,13 +30,16 @@ import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
+import com.ning.billing.invoice.dao.InvoiceItemModelDao;
 import com.ning.billing.invoice.dao.InvoiceItemSqlDao;
+import com.ning.billing.invoice.dao.InvoiceModelDao;
 import com.ning.billing.invoice.dao.InvoiceSqlDao;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.entity.EntityPersistenceException;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 
 import com.google.common.collect.ImmutableList;
@@ -76,12 +80,16 @@ public class InvoiceTestUtils {
         final List<InvoiceItem> invoiceItems = new ArrayList<InvoiceItem>();
         for (final BigDecimal amount : amounts) {
             final InvoiceItem invoiceItem = createInvoiceItem(clock, invoiceId, accountId, amount, currency);
-            invoiceItemSqlDao.create(invoiceItem, internalCallContextFactory.createInternalCallContext(accountId, callContext));
+            invoiceItemSqlDao.create(new InvoiceItemModelDao(invoiceItem), internalCallContextFactory.createInternalCallContext(accountId, callContext));
             invoiceItems.add(invoiceItem);
         }
         Mockito.when(invoice.getInvoiceItems()).thenReturn(invoiceItems);
 
-        invoiceSqlDao.create(invoice, internalCallContextFactory.createInternalCallContext(accountId, callContext));
+        try {
+            invoiceSqlDao.create(new InvoiceModelDao(invoice), internalCallContextFactory.createInternalCallContext(accountId, callContext));
+        } catch (EntityPersistenceException e) {
+            Assert.fail(e.getMessage());
+        }
 
         return invoice;
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/TestChargeBacks.java b/invoice/src/test/java/com/ning/billing/invoice/tests/TestChargeBacks.java
index 78904ec..d1003f3 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/TestChargeBacks.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/TestChargeBacks.java
@@ -38,7 +38,7 @@ import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.api.invoice.DefaultInvoicePaymentApi;
 import com.ning.billing.invoice.api.svcs.DefaultInvoiceInternalApi;
-import com.ning.billing.invoice.dao.AuditedInvoiceDao;
+import com.ning.billing.invoice.dao.DefaultInvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceItemSqlDao;
 import com.ning.billing.invoice.dao.InvoiceSqlDao;
@@ -86,7 +86,7 @@ public class TestChargeBacks extends InvoiceTestSuiteWithEmbeddedDB {
         invoiceItemSqlDao.test(internalCallContext);
         final NextBillingDatePoster nextBillingDatePoster = new MockNextBillingDatePoster();
         internalCallContextFactory = new InternalCallContextFactory(dbi, clock);
-        final InvoiceDao invoiceDao = new AuditedInvoiceDao(dbi, nextBillingDatePoster, clock, Mockito.mock(InternalBus.class));
+        final InvoiceDao invoiceDao = new DefaultInvoiceDao(dbi, nextBillingDatePoster, Mockito.mock(InternalBus.class));
         invoicePaymentApi = new DefaultInvoicePaymentApi(invoiceDao, internalCallContextFactory);
         invoiceApi = new DefaultInvoiceInternalApi(invoiceDao);
     }