killbill-memoizeit

analytics: add tests for most POJOs Signed-off-by: Pierre-Alexandre

4/4/2013 7:36:51 PM

Changes

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoice.java 71(+0 -71)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoiceItem.java 81(+0 -81)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoicePayment.java 87(+0 -87)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionTransition.java 164(+0 -164)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionTransitionField.java 56(+0 -56)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionTransitionTag.java 52(+0 -52)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockDuration.java 50(+0 -50)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockPhase.java 124(+0 -124)

osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockProduct.java 74(+0 -74)

Details

diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessAccount.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessAccount.java
index 594a312..e6439c5 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessAccount.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessAccount.java
@@ -71,4 +71,198 @@ public class BusinessAccount extends BusinessEntityBase {
         this.lastPaymentDate = businessAccountModelDao.getLastPaymentDate();
         this.lastPaymentStatus = businessAccountModelDao.getLastPaymentStatus();
     }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public Integer getFirstNameLength() {
+        return firstNameLength;
+    }
+
+    public String getCurrency() {
+        return currency;
+    }
+
+    public Integer getBillingCycleDayLocal() {
+        return billingCycleDayLocal;
+    }
+
+    public String getAddress1() {
+        return address1;
+    }
+
+    public String getAddress2() {
+        return address2;
+    }
+
+    public String getCompanyName() {
+        return companyName;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public String getStateOrProvince() {
+        return stateOrProvince;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public String getPostalCode() {
+        return postalCode;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public Boolean getMigrated() {
+        return isMigrated;
+    }
+
+    public Boolean getNotifiedForInvoices() {
+        return isNotifiedForInvoices;
+    }
+
+    public BigDecimal getBalance() {
+        return balance;
+    }
+
+    public LocalDate getLastInvoiceDate() {
+        return lastInvoiceDate;
+    }
+
+    public DateTime getLastPaymentDate() {
+        return lastPaymentDate;
+    }
+
+    public String getLastPaymentStatus() {
+        return lastPaymentStatus;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessAccount");
+        sb.append("{email='").append(email).append('\'');
+        sb.append(", firstNameLength=").append(firstNameLength);
+        sb.append(", currency='").append(currency).append('\'');
+        sb.append(", billingCycleDayLocal=").append(billingCycleDayLocal);
+        sb.append(", address1='").append(address1).append('\'');
+        sb.append(", address2='").append(address2).append('\'');
+        sb.append(", companyName='").append(companyName).append('\'');
+        sb.append(", city='").append(city).append('\'');
+        sb.append(", stateOrProvince='").append(stateOrProvince).append('\'');
+        sb.append(", country='").append(country).append('\'');
+        sb.append(", postalCode='").append(postalCode).append('\'');
+        sb.append(", phone='").append(phone).append('\'');
+        sb.append(", isMigrated=").append(isMigrated);
+        sb.append(", isNotifiedForInvoices=").append(isNotifiedForInvoices);
+        sb.append(", balance=").append(balance);
+        sb.append(", lastInvoiceDate=").append(lastInvoiceDate);
+        sb.append(", lastPaymentDate=").append(lastPaymentDate);
+        sb.append(", lastPaymentStatus='").append(lastPaymentStatus).append('\'');
+        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 BusinessAccount that = (BusinessAccount) o;
+
+        if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) {
+            return false;
+        }
+        if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) {
+            return false;
+        }
+        if (balance != null ? !balance.equals(that.balance) : that.balance != null) {
+            return false;
+        }
+        if (billingCycleDayLocal != null ? !billingCycleDayLocal.equals(that.billingCycleDayLocal) : that.billingCycleDayLocal != null) {
+            return false;
+        }
+        if (city != null ? !city.equals(that.city) : that.city != null) {
+            return false;
+        }
+        if (companyName != null ? !companyName.equals(that.companyName) : that.companyName != null) {
+            return false;
+        }
+        if (country != null ? !country.equals(that.country) : that.country != null) {
+            return false;
+        }
+        if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
+            return false;
+        }
+        if (email != null ? !email.equals(that.email) : that.email != null) {
+            return false;
+        }
+        if (firstNameLength != null ? !firstNameLength.equals(that.firstNameLength) : that.firstNameLength != null) {
+            return false;
+        }
+        if (isMigrated != null ? !isMigrated.equals(that.isMigrated) : that.isMigrated != null) {
+            return false;
+        }
+        if (isNotifiedForInvoices != null ? !isNotifiedForInvoices.equals(that.isNotifiedForInvoices) : that.isNotifiedForInvoices != null) {
+            return false;
+        }
+        if (lastInvoiceDate != null ? !lastInvoiceDate.equals(that.lastInvoiceDate) : that.lastInvoiceDate != null) {
+            return false;
+        }
+        if (lastPaymentDate != null ? !lastPaymentDate.equals(that.lastPaymentDate) : that.lastPaymentDate != null) {
+            return false;
+        }
+        if (lastPaymentStatus != null ? !lastPaymentStatus.equals(that.lastPaymentStatus) : that.lastPaymentStatus != null) {
+            return false;
+        }
+        if (phone != null ? !phone.equals(that.phone) : that.phone != null) {
+            return false;
+        }
+        if (postalCode != null ? !postalCode.equals(that.postalCode) : that.postalCode != null) {
+            return false;
+        }
+        if (stateOrProvince != null ? !stateOrProvince.equals(that.stateOrProvince) : that.stateOrProvince != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (email != null ? email.hashCode() : 0);
+        result = 31 * result + (firstNameLength != null ? firstNameLength.hashCode() : 0);
+        result = 31 * result + (currency != null ? currency.hashCode() : 0);
+        result = 31 * result + (billingCycleDayLocal != null ? billingCycleDayLocal.hashCode() : 0);
+        result = 31 * result + (address1 != null ? address1.hashCode() : 0);
+        result = 31 * result + (address2 != null ? address2.hashCode() : 0);
+        result = 31 * result + (companyName != null ? companyName.hashCode() : 0);
+        result = 31 * result + (city != null ? city.hashCode() : 0);
+        result = 31 * result + (stateOrProvince != null ? stateOrProvince.hashCode() : 0);
+        result = 31 * result + (country != null ? country.hashCode() : 0);
+        result = 31 * result + (postalCode != null ? postalCode.hashCode() : 0);
+        result = 31 * result + (phone != null ? phone.hashCode() : 0);
+        result = 31 * result + (isMigrated != null ? isMigrated.hashCode() : 0);
+        result = 31 * result + (isNotifiedForInvoices != null ? isNotifiedForInvoices.hashCode() : 0);
+        result = 31 * result + (balance != null ? balance.hashCode() : 0);
+        result = 31 * result + (lastInvoiceDate != null ? lastInvoiceDate.hashCode() : 0);
+        result = 31 * result + (lastPaymentDate != null ? lastPaymentDate.hashCode() : 0);
+        result = 31 * result + (lastPaymentStatus != null ? lastPaymentStatus.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessEntityBase.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessEntityBase.java
index 3751ec4..f98522d 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessEntityBase.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessEntityBase.java
@@ -41,4 +41,95 @@ public abstract class BusinessEntityBase {
         this.accountName = accountName;
         this.accountExternalKey = accountExternalKey;
     }
+
+    public DateTime getCreatedDate() {
+        return createdDate;
+    }
+
+    public String getCreatedBy() {
+        return createdBy;
+    }
+
+    public String getCreatedReasonCode() {
+        return createdReasonCode;
+    }
+
+    public String getCreatedComments() {
+        return createdComments;
+    }
+
+    public UUID getAccountId() {
+        return accountId;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public String getAccountExternalKey() {
+        return accountExternalKey;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessEntityBase");
+        sb.append("{createdDate=").append(createdDate);
+        sb.append(", createdBy='").append(createdBy).append('\'');
+        sb.append(", createdReasonCode='").append(createdReasonCode).append('\'');
+        sb.append(", createdComments='").append(createdComments).append('\'');
+        sb.append(", accountId=").append(accountId);
+        sb.append(", accountName='").append(accountName).append('\'');
+        sb.append(", accountExternalKey='").append(accountExternalKey).append('\'');
+        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;
+        }
+
+        final BusinessEntityBase that = (BusinessEntityBase) o;
+
+        if (accountExternalKey != null ? !accountExternalKey.equals(that.accountExternalKey) : that.accountExternalKey != null) {
+            return false;
+        }
+        if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+            return false;
+        }
+        if (accountName != null ? !accountName.equals(that.accountName) : that.accountName != null) {
+            return false;
+        }
+        if (createdBy != null ? !createdBy.equals(that.createdBy) : that.createdBy != null) {
+            return false;
+        }
+        if (createdComments != null ? !createdComments.equals(that.createdComments) : that.createdComments != null) {
+            return false;
+        }
+        if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
+            return false;
+        }
+        if (createdReasonCode != null ? !createdReasonCode.equals(that.createdReasonCode) : that.createdReasonCode != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = createdDate != null ? createdDate.hashCode() : 0;
+        result = 31 * result + (createdBy != null ? createdBy.hashCode() : 0);
+        result = 31 * result + (createdReasonCode != null ? createdReasonCode.hashCode() : 0);
+        result = 31 * result + (createdComments != null ? createdComments.hashCode() : 0);
+        result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+        result = 31 * result + (accountName != null ? accountName.hashCode() : 0);
+        result = 31 * result + (accountExternalKey != null ? accountExternalKey.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessField.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessField.java
index 211774d..15821d5 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessField.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessField.java
@@ -28,7 +28,7 @@ public class BusinessField extends BusinessEntityBase {
     private final String name;
     private final String value;
 
-    BusinessField(final ObjectType objectType, final BusinessFieldModelDao businessFieldModelDao) {
+    private BusinessField(final ObjectType objectType, final BusinessFieldModelDao businessFieldModelDao) {
         super(businessFieldModelDao.getCreatedDate(),
               businessFieldModelDao.getCreatedBy(),
               businessFieldModelDao.getCreatedReasonCode(),
@@ -41,16 +41,16 @@ public class BusinessField extends BusinessEntityBase {
         this.value = businessFieldModelDao.getValue();
     }
 
-    public BusinessField(final BusinessAccountFieldModelDao businessAccountFieldModelDao) {
-        this(ObjectType.ACCOUNT, businessAccountFieldModelDao);
-    }
-
-    public BusinessField(final BusinessInvoiceFieldModelDao businessInvoiceFieldModelDao) {
-        this(ObjectType.INVOICE, businessInvoiceFieldModelDao);
-    }
-
-    public BusinessField(final BusinessInvoicePaymentFieldModelDao businessInvoicePaymentFieldModelDao) {
-        this(ObjectType.PAYMENT, businessInvoicePaymentFieldModelDao);
+    public static BusinessField create(final BusinessFieldModelDao businessFieldModelDao) {
+        if (businessFieldModelDao instanceof BusinessAccountFieldModelDao) {
+            return new BusinessField(ObjectType.ACCOUNT, businessFieldModelDao);
+        } else if (businessFieldModelDao instanceof BusinessInvoiceFieldModelDao) {
+            return new BusinessField(ObjectType.INVOICE, businessFieldModelDao);
+        } else if (businessFieldModelDao instanceof BusinessInvoicePaymentFieldModelDao) {
+            return new BusinessField(ObjectType.INVOICE_PAYMENT, businessFieldModelDao);
+        } else {
+            return null;
+        }
     }
 
     public ObjectType getObjectType() {
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoice.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoice.java
index 80290e1..6e4feda 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoice.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoice.java
@@ -64,4 +64,135 @@ public class BusinessInvoice extends BusinessEntityBase {
             invoiceItems.add(new BusinessInvoiceItem(businessInvoiceItemModelDao));
         }
     }
+
+    public UUID getInvoiceId() {
+        return invoiceId;
+    }
+
+    public Integer getInvoiceNumber() {
+        return invoiceNumber;
+    }
+
+    public LocalDate getInvoiceDate() {
+        return invoiceDate;
+    }
+
+    public LocalDate getTargetDate() {
+        return targetDate;
+    }
+
+    public String getCurrency() {
+        return currency;
+    }
+
+    public BigDecimal getBalance() {
+        return balance;
+    }
+
+    public BigDecimal getAmountPaid() {
+        return amountPaid;
+    }
+
+    public BigDecimal getAmountCharged() {
+        return amountCharged;
+    }
+
+    public BigDecimal getOriginalAmountCharged() {
+        return originalAmountCharged;
+    }
+
+    public BigDecimal getAmountCredited() {
+        return amountCredited;
+    }
+
+    public List<BusinessInvoiceItem> getInvoiceItems() {
+        return invoiceItems;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessInvoice");
+        sb.append("{invoiceId=").append(invoiceId);
+        sb.append(", invoiceNumber=").append(invoiceNumber);
+        sb.append(", invoiceDate=").append(invoiceDate);
+        sb.append(", targetDate=").append(targetDate);
+        sb.append(", currency='").append(currency).append('\'');
+        sb.append(", balance=").append(balance);
+        sb.append(", amountPaid=").append(amountPaid);
+        sb.append(", amountCharged=").append(amountCharged);
+        sb.append(", originalAmountCharged=").append(originalAmountCharged);
+        sb.append(", amountCredited=").append(amountCredited);
+        sb.append(", invoiceItems=").append(invoiceItems);
+        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 BusinessInvoice that = (BusinessInvoice) o;
+
+        if (amountCharged != null ? !amountCharged.equals(that.amountCharged) : that.amountCharged != null) {
+            return false;
+        }
+        if (amountCredited != null ? !amountCredited.equals(that.amountCredited) : that.amountCredited != null) {
+            return false;
+        }
+        if (amountPaid != null ? !amountPaid.equals(that.amountPaid) : that.amountPaid != null) {
+            return false;
+        }
+        if (balance != null ? !balance.equals(that.balance) : that.balance != null) {
+            return false;
+        }
+        if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
+            return false;
+        }
+        if (invoiceDate != null ? !invoiceDate.equals(that.invoiceDate) : that.invoiceDate != null) {
+            return false;
+        }
+        if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+            return false;
+        }
+        if (invoiceItems != null ? !invoiceItems.equals(that.invoiceItems) : that.invoiceItems != null) {
+            return false;
+        }
+        if (invoiceNumber != null ? !invoiceNumber.equals(that.invoiceNumber) : that.invoiceNumber != null) {
+            return false;
+        }
+        if (originalAmountCharged != null ? !originalAmountCharged.equals(that.originalAmountCharged) : that.originalAmountCharged != 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 + (invoiceId != null ? invoiceId.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 + (balance != null ? balance.hashCode() : 0);
+        result = 31 * result + (amountPaid != null ? amountPaid.hashCode() : 0);
+        result = 31 * result + (amountCharged != null ? amountCharged.hashCode() : 0);
+        result = 31 * result + (originalAmountCharged != null ? originalAmountCharged.hashCode() : 0);
+        result = 31 * result + (amountCredited != null ? amountCredited.hashCode() : 0);
+        result = 31 * result + (invoiceItems != null ? invoiceItems.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoiceItem.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoiceItem.java
index 25aca32..f47415d 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoiceItem.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoiceItem.java
@@ -22,7 +22,6 @@ 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.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao;
 
 public class BusinessInvoiceItem extends BusinessEntityBase {
@@ -51,7 +50,7 @@ public class BusinessInvoiceItem extends BusinessEntityBase {
     private final LocalDate startDate;
     private final LocalDate endDate;
     private final BigDecimal amount;
-    private final Currency currency;
+    private final String currency;
     private final UUID linkedItemId;
 
     public BusinessInvoiceItem(final BusinessInvoiceItemBaseModelDao businessInvoiceItemBaseModelDao) {
@@ -75,7 +74,7 @@ public class BusinessInvoiceItem extends BusinessEntityBase {
         this.invoiceOriginalAmountCharged = businessInvoiceItemBaseModelDao.getInvoiceOriginalAmountCharged();
         this.invoiceAmountCredited = businessInvoiceItemBaseModelDao.getInvoiceAmountCredited();
         this.itemType = businessInvoiceItemBaseModelDao.getItemType();
-        this.recognizable = businessInvoiceItemBaseModelDao.getRecognizable();
+        this.recognizable = businessInvoiceItemBaseModelDao.getRevenueRecognizable();
         this.bundleExternalKey = businessInvoiceItemBaseModelDao.getBundleExternalKey();
         this.productName = businessInvoiceItemBaseModelDao.getProductName();
         this.productType = businessInvoiceItemBaseModelDao.getProductType();
@@ -89,4 +88,270 @@ public class BusinessInvoiceItem extends BusinessEntityBase {
         this.currency = businessInvoiceItemBaseModelDao.getCurrency();
         this.linkedItemId = businessInvoiceItemBaseModelDao.getLinkedItemId();
     }
+
+    public UUID getItemId() {
+        return itemId;
+    }
+
+    public UUID getInvoiceId() {
+        return invoiceId;
+    }
+
+    public Integer getInvoiceNumber() {
+        return invoiceNumber;
+    }
+
+    public DateTime getInvoiceCreatedDate() {
+        return invoiceCreatedDate;
+    }
+
+    public LocalDate getInvoiceDate() {
+        return invoiceDate;
+    }
+
+    public LocalDate getInvoiceTargetDate() {
+        return invoiceTargetDate;
+    }
+
+    public String getInvoiceCurrency() {
+        return invoiceCurrency;
+    }
+
+    public BigDecimal getInvoiceBalance() {
+        return invoiceBalance;
+    }
+
+    public BigDecimal getInvoiceAmountPaid() {
+        return invoiceAmountPaid;
+    }
+
+    public BigDecimal getInvoiceAmountCharged() {
+        return invoiceAmountCharged;
+    }
+
+    public BigDecimal getInvoiceOriginalAmountCharged() {
+        return invoiceOriginalAmountCharged;
+    }
+
+    public BigDecimal getInvoiceAmountCredited() {
+        return invoiceAmountCredited;
+    }
+
+    public String getItemType() {
+        return itemType;
+    }
+
+    public Boolean getRecognizable() {
+        return recognizable;
+    }
+
+    public String getBundleExternalKey() {
+        return bundleExternalKey;
+    }
+
+    public String getProductName() {
+        return productName;
+    }
+
+    public String getProductType() {
+        return productType;
+    }
+
+    public String getProductCategory() {
+        return productCategory;
+    }
+
+    public String getSlug() {
+        return slug;
+    }
+
+    public String getPhase() {
+        return phase;
+    }
+
+    public String getBillingPeriod() {
+        return billingPeriod;
+    }
+
+    public LocalDate getStartDate() {
+        return startDate;
+    }
+
+    public LocalDate getEndDate() {
+        return endDate;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public String getCurrency() {
+        return currency;
+    }
+
+    public UUID getLinkedItemId() {
+        return linkedItemId;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessInvoiceItem");
+        sb.append("{itemId=").append(itemId);
+        sb.append(", invoiceId=").append(invoiceId);
+        sb.append(", invoiceNumber=").append(invoiceNumber);
+        sb.append(", invoiceCreatedDate=").append(invoiceCreatedDate);
+        sb.append(", invoiceDate=").append(invoiceDate);
+        sb.append(", invoiceTargetDate=").append(invoiceTargetDate);
+        sb.append(", invoiceCurrency='").append(invoiceCurrency).append('\'');
+        sb.append(", invoiceBalance=").append(invoiceBalance);
+        sb.append(", invoiceAmountPaid=").append(invoiceAmountPaid);
+        sb.append(", invoiceAmountCharged=").append(invoiceAmountCharged);
+        sb.append(", invoiceOriginalAmountCharged=").append(invoiceOriginalAmountCharged);
+        sb.append(", invoiceAmountCredited=").append(invoiceAmountCredited);
+        sb.append(", itemType='").append(itemType).append('\'');
+        sb.append(", recognizable=").append(recognizable);
+        sb.append(", bundleExternalKey='").append(bundleExternalKey).append('\'');
+        sb.append(", productName='").append(productName).append('\'');
+        sb.append(", productType='").append(productType).append('\'');
+        sb.append(", productCategory='").append(productCategory).append('\'');
+        sb.append(", slug='").append(slug).append('\'');
+        sb.append(", phase='").append(phase).append('\'');
+        sb.append(", billingPeriod='").append(billingPeriod).append('\'');
+        sb.append(", startDate=").append(startDate);
+        sb.append(", endDate=").append(endDate);
+        sb.append(", amount=").append(amount);
+        sb.append(", currency='").append(currency).append('\'');
+        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 BusinessInvoiceItem that = (BusinessInvoiceItem) o;
+
+        if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+            return false;
+        }
+        if (billingPeriod != null ? !billingPeriod.equals(that.billingPeriod) : that.billingPeriod != null) {
+            return false;
+        }
+        if (bundleExternalKey != null ? !bundleExternalKey.equals(that.bundleExternalKey) : that.bundleExternalKey != null) {
+            return false;
+        }
+        if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
+            return false;
+        }
+        if (endDate != null ? !endDate.equals(that.endDate) : that.endDate != null) {
+            return false;
+        }
+        if (invoiceAmountCharged != null ? !invoiceAmountCharged.equals(that.invoiceAmountCharged) : that.invoiceAmountCharged != null) {
+            return false;
+        }
+        if (invoiceAmountCredited != null ? !invoiceAmountCredited.equals(that.invoiceAmountCredited) : that.invoiceAmountCredited != null) {
+            return false;
+        }
+        if (invoiceAmountPaid != null ? !invoiceAmountPaid.equals(that.invoiceAmountPaid) : that.invoiceAmountPaid != null) {
+            return false;
+        }
+        if (invoiceBalance != null ? !invoiceBalance.equals(that.invoiceBalance) : that.invoiceBalance != null) {
+            return false;
+        }
+        if (invoiceCreatedDate != null ? !invoiceCreatedDate.equals(that.invoiceCreatedDate) : that.invoiceCreatedDate != null) {
+            return false;
+        }
+        if (invoiceCurrency != null ? !invoiceCurrency.equals(that.invoiceCurrency) : that.invoiceCurrency != null) {
+            return false;
+        }
+        if (invoiceDate != null ? !invoiceDate.equals(that.invoiceDate) : that.invoiceDate != null) {
+            return false;
+        }
+        if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+            return false;
+        }
+        if (invoiceNumber != null ? !invoiceNumber.equals(that.invoiceNumber) : that.invoiceNumber != null) {
+            return false;
+        }
+        if (invoiceOriginalAmountCharged != null ? !invoiceOriginalAmountCharged.equals(that.invoiceOriginalAmountCharged) : that.invoiceOriginalAmountCharged != null) {
+            return false;
+        }
+        if (invoiceTargetDate != null ? !invoiceTargetDate.equals(that.invoiceTargetDate) : that.invoiceTargetDate != null) {
+            return false;
+        }
+        if (itemId != null ? !itemId.equals(that.itemId) : that.itemId != null) {
+            return false;
+        }
+        if (itemType != null ? !itemType.equals(that.itemType) : that.itemType != null) {
+            return false;
+        }
+        if (linkedItemId != null ? !linkedItemId.equals(that.linkedItemId) : that.linkedItemId != null) {
+            return false;
+        }
+        if (phase != null ? !phase.equals(that.phase) : that.phase != null) {
+            return false;
+        }
+        if (productCategory != null ? !productCategory.equals(that.productCategory) : that.productCategory != null) {
+            return false;
+        }
+        if (productName != null ? !productName.equals(that.productName) : that.productName != null) {
+            return false;
+        }
+        if (productType != null ? !productType.equals(that.productType) : that.productType != null) {
+            return false;
+        }
+        if (recognizable != null ? !recognizable.equals(that.recognizable) : that.recognizable != null) {
+            return false;
+        }
+        if (slug != null ? !slug.equals(that.slug) : that.slug != null) {
+            return false;
+        }
+        if (startDate != null ? !startDate.equals(that.startDate) : that.startDate != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (itemId != null ? itemId.hashCode() : 0);
+        result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
+        result = 31 * result + (invoiceNumber != null ? invoiceNumber.hashCode() : 0);
+        result = 31 * result + (invoiceCreatedDate != null ? invoiceCreatedDate.hashCode() : 0);
+        result = 31 * result + (invoiceDate != null ? invoiceDate.hashCode() : 0);
+        result = 31 * result + (invoiceTargetDate != null ? invoiceTargetDate.hashCode() : 0);
+        result = 31 * result + (invoiceCurrency != null ? invoiceCurrency.hashCode() : 0);
+        result = 31 * result + (invoiceBalance != null ? invoiceBalance.hashCode() : 0);
+        result = 31 * result + (invoiceAmountPaid != null ? invoiceAmountPaid.hashCode() : 0);
+        result = 31 * result + (invoiceAmountCharged != null ? invoiceAmountCharged.hashCode() : 0);
+        result = 31 * result + (invoiceOriginalAmountCharged != null ? invoiceOriginalAmountCharged.hashCode() : 0);
+        result = 31 * result + (invoiceAmountCredited != null ? invoiceAmountCredited.hashCode() : 0);
+        result = 31 * result + (itemType != null ? itemType.hashCode() : 0);
+        result = 31 * result + (recognizable != null ? recognizable.hashCode() : 0);
+        result = 31 * result + (bundleExternalKey != null ? bundleExternalKey.hashCode() : 0);
+        result = 31 * result + (productName != null ? productName.hashCode() : 0);
+        result = 31 * result + (productType != null ? productType.hashCode() : 0);
+        result = 31 * result + (productCategory != null ? productCategory.hashCode() : 0);
+        result = 31 * result + (slug != null ? slug.hashCode() : 0);
+        result = 31 * result + (phase != null ? phase.hashCode() : 0);
+        result = 31 * result + (billingPeriod != null ? billingPeriod.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 + (currency != null ? currency.hashCode() : 0);
+        result = 31 * result + (linkedItemId != null ? linkedItemId.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoicePayment.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoicePayment.java
index e0bd52a..d5cd664 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoicePayment.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessInvoicePayment.java
@@ -22,7 +22,6 @@ 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.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentBaseModelDao;
 
 public class BusinessInvoicePayment extends BusinessEntityBase {
@@ -43,7 +42,7 @@ public class BusinessInvoicePayment extends BusinessEntityBase {
     private final Long paymentNumber;
     private final UUID linkedInvoicePaymentId;
     private final BigDecimal amount;
-    private final Currency currency;
+    private final String currency;
 
     public BusinessInvoicePayment(final BusinessInvoicePaymentBaseModelDao businessInvoicePaymentBaseModelDao) {
         super(businessInvoicePaymentBaseModelDao.getCreatedDate(),
@@ -71,4 +70,189 @@ public class BusinessInvoicePayment extends BusinessEntityBase {
         this.amount = businessInvoicePaymentBaseModelDao.getAmount();
         this.currency = businessInvoicePaymentBaseModelDao.getCurrency();
     }
+
+    public UUID getInvoicePaymentId() {
+        return invoicePaymentId;
+    }
+
+    public UUID getInvoiceId() {
+        return invoiceId;
+    }
+
+    public Integer getInvoiceNumber() {
+        return invoiceNumber;
+    }
+
+    public DateTime getInvoiceCreatedDate() {
+        return invoiceCreatedDate;
+    }
+
+    public LocalDate getInvoiceDate() {
+        return invoiceDate;
+    }
+
+    public LocalDate getInvoiceTargetDate() {
+        return invoiceTargetDate;
+    }
+
+    public String getInvoiceCurrency() {
+        return invoiceCurrency;
+    }
+
+    public BigDecimal getInvoiceBalance() {
+        return invoiceBalance;
+    }
+
+    public BigDecimal getInvoiceAmountPaid() {
+        return invoiceAmountPaid;
+    }
+
+    public BigDecimal getInvoiceAmountCharged() {
+        return invoiceAmountCharged;
+    }
+
+    public BigDecimal getInvoiceOriginalAmountCharged() {
+        return invoiceOriginalAmountCharged;
+    }
+
+    public BigDecimal getInvoiceAmountCredited() {
+        return invoiceAmountCredited;
+    }
+
+    public String getInvoicePaymentType() {
+        return invoicePaymentType;
+    }
+
+    public Long getPaymentNumber() {
+        return paymentNumber;
+    }
+
+    public UUID getLinkedInvoicePaymentId() {
+        return linkedInvoicePaymentId;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public String getCurrency() {
+        return currency;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessInvoicePayment");
+        sb.append("{invoicePaymentId=").append(invoicePaymentId);
+        sb.append(", invoiceId=").append(invoiceId);
+        sb.append(", invoiceNumber=").append(invoiceNumber);
+        sb.append(", invoiceCreatedDate=").append(invoiceCreatedDate);
+        sb.append(", invoiceDate=").append(invoiceDate);
+        sb.append(", invoiceTargetDate=").append(invoiceTargetDate);
+        sb.append(", invoiceCurrency='").append(invoiceCurrency).append('\'');
+        sb.append(", invoiceBalance=").append(invoiceBalance);
+        sb.append(", invoiceAmountPaid=").append(invoiceAmountPaid);
+        sb.append(", invoiceAmountCharged=").append(invoiceAmountCharged);
+        sb.append(", invoiceOriginalAmountCharged=").append(invoiceOriginalAmountCharged);
+        sb.append(", invoiceAmountCredited=").append(invoiceAmountCredited);
+        sb.append(", invoicePaymentType='").append(invoicePaymentType).append('\'');
+        sb.append(", paymentNumber=").append(paymentNumber);
+        sb.append(", linkedInvoicePaymentId=").append(linkedInvoicePaymentId);
+        sb.append(", amount=").append(amount);
+        sb.append(", currency='").append(currency).append('\'');
+        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 BusinessInvoicePayment that = (BusinessInvoicePayment) o;
+
+        if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+            return false;
+        }
+        if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
+            return false;
+        }
+        if (invoiceAmountCharged != null ? !invoiceAmountCharged.equals(that.invoiceAmountCharged) : that.invoiceAmountCharged != null) {
+            return false;
+        }
+        if (invoiceAmountCredited != null ? !invoiceAmountCredited.equals(that.invoiceAmountCredited) : that.invoiceAmountCredited != null) {
+            return false;
+        }
+        if (invoiceAmountPaid != null ? !invoiceAmountPaid.equals(that.invoiceAmountPaid) : that.invoiceAmountPaid != null) {
+            return false;
+        }
+        if (invoiceBalance != null ? !invoiceBalance.equals(that.invoiceBalance) : that.invoiceBalance != null) {
+            return false;
+        }
+        if (invoiceCreatedDate != null ? !invoiceCreatedDate.equals(that.invoiceCreatedDate) : that.invoiceCreatedDate != null) {
+            return false;
+        }
+        if (invoiceCurrency != null ? !invoiceCurrency.equals(that.invoiceCurrency) : that.invoiceCurrency != null) {
+            return false;
+        }
+        if (invoiceDate != null ? !invoiceDate.equals(that.invoiceDate) : that.invoiceDate != null) {
+            return false;
+        }
+        if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+            return false;
+        }
+        if (invoiceNumber != null ? !invoiceNumber.equals(that.invoiceNumber) : that.invoiceNumber != null) {
+            return false;
+        }
+        if (invoiceOriginalAmountCharged != null ? !invoiceOriginalAmountCharged.equals(that.invoiceOriginalAmountCharged) : that.invoiceOriginalAmountCharged != null) {
+            return false;
+        }
+        if (invoicePaymentId != null ? !invoicePaymentId.equals(that.invoicePaymentId) : that.invoicePaymentId != null) {
+            return false;
+        }
+        if (invoicePaymentType != null ? !invoicePaymentType.equals(that.invoicePaymentType) : that.invoicePaymentType != null) {
+            return false;
+        }
+        if (invoiceTargetDate != null ? !invoiceTargetDate.equals(that.invoiceTargetDate) : that.invoiceTargetDate != null) {
+            return false;
+        }
+        if (linkedInvoicePaymentId != null ? !linkedInvoicePaymentId.equals(that.linkedInvoicePaymentId) : that.linkedInvoicePaymentId != null) {
+            return false;
+        }
+        if (paymentNumber != null ? !paymentNumber.equals(that.paymentNumber) : that.paymentNumber != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (invoicePaymentId != null ? invoicePaymentId.hashCode() : 0);
+        result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
+        result = 31 * result + (invoiceNumber != null ? invoiceNumber.hashCode() : 0);
+        result = 31 * result + (invoiceCreatedDate != null ? invoiceCreatedDate.hashCode() : 0);
+        result = 31 * result + (invoiceDate != null ? invoiceDate.hashCode() : 0);
+        result = 31 * result + (invoiceTargetDate != null ? invoiceTargetDate.hashCode() : 0);
+        result = 31 * result + (invoiceCurrency != null ? invoiceCurrency.hashCode() : 0);
+        result = 31 * result + (invoiceBalance != null ? invoiceBalance.hashCode() : 0);
+        result = 31 * result + (invoiceAmountPaid != null ? invoiceAmountPaid.hashCode() : 0);
+        result = 31 * result + (invoiceAmountCharged != null ? invoiceAmountCharged.hashCode() : 0);
+        result = 31 * result + (invoiceOriginalAmountCharged != null ? invoiceOriginalAmountCharged.hashCode() : 0);
+        result = 31 * result + (invoiceAmountCredited != null ? invoiceAmountCredited.hashCode() : 0);
+        result = 31 * result + (invoicePaymentType != null ? invoicePaymentType.hashCode() : 0);
+        result = 31 * result + (paymentNumber != null ? paymentNumber.hashCode() : 0);
+        result = 31 * result + (linkedInvoicePaymentId != null ? linkedInvoicePaymentId.hashCode() : 0);
+        result = 31 * result + (amount != null ? amount.hashCode() : 0);
+        result = 31 * result + (currency != null ? currency.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessOverdueStatus.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessOverdueStatus.java
index 12b1b65..b4c52c2 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessOverdueStatus.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessOverdueStatus.java
@@ -23,8 +23,7 @@ import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessOverdueStatusMo
 
 public class BusinessOverdueStatus extends BusinessEntityBase {
 
-    private final ObjectType objectType;
-    private final String accountKey;
+    private final String objectType;
     private final String status;
     private final DateTime startDate;
     private final DateTime endDate;
@@ -39,22 +38,17 @@ public class BusinessOverdueStatus extends BusinessEntityBase {
               businessOverdueStatusModelDao.getAccountExternalKey());
 
         // TODO For now
-        this.objectType = ObjectType.BUNDLE;
+        this.objectType = ObjectType.BUNDLE.toString();
 
-        this.accountKey = businessOverdueStatusModelDao.getAccountExternalKey();
         this.status = businessOverdueStatusModelDao.getStatus();
         this.startDate = businessOverdueStatusModelDao.getStartDate();
         this.endDate = businessOverdueStatusModelDao.getEndDate();
     }
 
-    public ObjectType getObjectType() {
+    public String getObjectType() {
         return objectType;
     }
 
-    public String getAccountKey() {
-        return accountKey;
-    }
-
     public String getStatus() {
         return status;
     }
@@ -71,7 +65,6 @@ public class BusinessOverdueStatus extends BusinessEntityBase {
         final StringBuilder sb = new StringBuilder();
         sb.append("BusinessOverdueStatus");
         sb.append("{objectType=").append(objectType);
-        sb.append(", accountKey='").append(accountKey).append('\'');
         sb.append(", status='").append(status).append('\'');
         sb.append(", startDate=").append(startDate);
         sb.append(", endDate=").append(endDate);
@@ -89,9 +82,6 @@ public class BusinessOverdueStatus extends BusinessEntityBase {
 
         final BusinessOverdueStatus that = (BusinessOverdueStatus) o;
 
-        if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
-            return false;
-        }
         if (endDate != null ? !endDate.equals(that.endDate) : that.endDate != null) {
             return false;
         }
@@ -110,7 +100,6 @@ public class BusinessOverdueStatus extends BusinessEntityBase {
 
     public int hashCode() {
         int result = objectType != null ? objectType.hashCode() : 0;
-        result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
         result = 31 * result + (status != null ? status.hashCode() : 0);
         result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
         result = 31 * result + (endDate != null ? endDate.hashCode() : 0);
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessSubscriptionTransition.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessSubscriptionTransition.java
index 6def0a8..59799e9 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessSubscriptionTransition.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessSubscriptionTransition.java
@@ -25,7 +25,6 @@ import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionTra
 
 public class BusinessSubscriptionTransition extends BusinessEntityBase {
 
-    private final long totalOrdering;
     private final UUID bundleId;
     private final String bundleExternalKey;
     private final UUID subscriptionId;
@@ -72,7 +71,6 @@ public class BusinessSubscriptionTransition extends BusinessEntityBase {
               bstModelDao.getAccountName(),
               bstModelDao.getAccountExternalKey());
 
-        this.totalOrdering = bstModelDao.getTotalOrdering();
         this.bundleId = bstModelDao.getBundleId();
         this.bundleExternalKey = bstModelDao.getBundleExternalKey();
         this.subscriptionId = bstModelDao.getSubscriptionId();
@@ -88,7 +86,7 @@ public class BusinessSubscriptionTransition extends BusinessEntityBase {
         if (bstModelDao.getPreviousSubscription() != null) {
             this.prevProductName = bstModelDao.getPreviousSubscription().getProductName();
             this.prevProductType = bstModelDao.getPreviousSubscription().getProductType();
-            this.prevProductCategory = bstModelDao.getPreviousSubscription().getProductCategory().toString();
+            this.prevProductCategory = bstModelDao.getPreviousSubscription().getProductCategory();
             this.prevSlug = bstModelDao.getPreviousSubscription().getSlug();
             this.prevPhase = bstModelDao.getPreviousSubscription().getPhase();
             this.prevBillingPeriod = bstModelDao.getPreviousSubscription().getBillingPeriod();
@@ -118,7 +116,7 @@ public class BusinessSubscriptionTransition extends BusinessEntityBase {
         if (bstModelDao.getNextSubscription() != null) {
             this.nextProductName = bstModelDao.getNextSubscription().getProductName();
             this.nextProductType = bstModelDao.getNextSubscription().getProductType();
-            this.nextProductCategory = bstModelDao.getNextSubscription().getProductCategory().toString();
+            this.nextProductCategory = bstModelDao.getNextSubscription().getProductCategory();
             this.nextSlug = bstModelDao.getNextSubscription().getSlug();
             this.nextPhase = bstModelDao.getNextSubscription().getPhase();
             this.nextBillingPeriod = bstModelDao.getNextSubscription().getBillingPeriod();
@@ -147,4 +145,333 @@ public class BusinessSubscriptionTransition extends BusinessEntityBase {
             this.nextState = null;
         }
     }
+
+    public UUID getBundleId() {
+        return bundleId;
+    }
+
+    public String getBundleExternalKey() {
+        return bundleExternalKey;
+    }
+
+    public UUID getSubscriptionId() {
+        return subscriptionId;
+    }
+
+    public DateTime getRequestedTimestamp() {
+        return requestedTimestamp;
+    }
+
+    public String getEventType() {
+        return eventType;
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public String getPrevProductName() {
+        return prevProductName;
+    }
+
+    public String getPrevProductType() {
+        return prevProductType;
+    }
+
+    public String getPrevProductCategory() {
+        return prevProductCategory;
+    }
+
+    public String getPrevSlug() {
+        return prevSlug;
+    }
+
+    public String getPrevPhase() {
+        return prevPhase;
+    }
+
+    public String getPrevBillingPeriod() {
+        return prevBillingPeriod;
+    }
+
+    public BigDecimal getPrevPrice() {
+        return prevPrice;
+    }
+
+    public String getPrevPriceList() {
+        return prevPriceList;
+    }
+
+    public BigDecimal getPrevMrr() {
+        return prevMrr;
+    }
+
+    public String getPrevCurrency() {
+        return prevCurrency;
+    }
+
+    public Boolean getPrevBusinessActive() {
+        return prevBusinessActive;
+    }
+
+    public DateTime getPrevStartDate() {
+        return prevStartDate;
+    }
+
+    public String getPrevState() {
+        return prevState;
+    }
+
+    public String getNextProductName() {
+        return nextProductName;
+    }
+
+    public String getNextProductType() {
+        return nextProductType;
+    }
+
+    public String getNextProductCategory() {
+        return nextProductCategory;
+    }
+
+    public String getNextSlug() {
+        return nextSlug;
+    }
+
+    public String getNextPhase() {
+        return nextPhase;
+    }
+
+    public String getNextBillingPeriod() {
+        return nextBillingPeriod;
+    }
+
+    public BigDecimal getNextPrice() {
+        return nextPrice;
+    }
+
+    public String getNextPriceList() {
+        return nextPriceList;
+    }
+
+    public BigDecimal getNextMrr() {
+        return nextMrr;
+    }
+
+    public String getNextCurrency() {
+        return nextCurrency;
+    }
+
+    public Boolean getNextBusinessActive() {
+        return nextBusinessActive;
+    }
+
+    public DateTime getNextStartDate() {
+        return nextStartDate;
+    }
+
+    public DateTime getNextEndDate() {
+        return nextEndDate;
+    }
+
+    public String getNextState() {
+        return nextState;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessSubscriptionTransition");
+        sb.append("{bundleId=").append(bundleId);
+        sb.append(", bundleExternalKey='").append(bundleExternalKey).append('\'');
+        sb.append(", subscriptionId=").append(subscriptionId);
+        sb.append(", requestedTimestamp=").append(requestedTimestamp);
+        sb.append(", eventType='").append(eventType).append('\'');
+        sb.append(", category='").append(category).append('\'');
+        sb.append(", prevProductName='").append(prevProductName).append('\'');
+        sb.append(", prevProductType='").append(prevProductType).append('\'');
+        sb.append(", prevProductCategory='").append(prevProductCategory).append('\'');
+        sb.append(", prevSlug='").append(prevSlug).append('\'');
+        sb.append(", prevPhase='").append(prevPhase).append('\'');
+        sb.append(", prevBillingPeriod='").append(prevBillingPeriod).append('\'');
+        sb.append(", prevPrice=").append(prevPrice);
+        sb.append(", prevPriceList='").append(prevPriceList).append('\'');
+        sb.append(", prevMrr=").append(prevMrr);
+        sb.append(", prevCurrency='").append(prevCurrency).append('\'');
+        sb.append(", prevBusinessActive=").append(prevBusinessActive);
+        sb.append(", prevStartDate=").append(prevStartDate);
+        sb.append(", prevState='").append(prevState).append('\'');
+        sb.append(", nextProductName='").append(nextProductName).append('\'');
+        sb.append(", nextProductType='").append(nextProductType).append('\'');
+        sb.append(", nextProductCategory='").append(nextProductCategory).append('\'');
+        sb.append(", nextSlug='").append(nextSlug).append('\'');
+        sb.append(", nextPhase='").append(nextPhase).append('\'');
+        sb.append(", nextBillingPeriod='").append(nextBillingPeriod).append('\'');
+        sb.append(", nextPrice=").append(nextPrice);
+        sb.append(", nextPriceList='").append(nextPriceList).append('\'');
+        sb.append(", nextMrr=").append(nextMrr);
+        sb.append(", nextCurrency='").append(nextCurrency).append('\'');
+        sb.append(", nextBusinessActive=").append(nextBusinessActive);
+        sb.append(", nextStartDate=").append(nextStartDate);
+        sb.append(", nextEndDate=").append(nextEndDate);
+        sb.append(", nextState='").append(nextState).append('\'');
+        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 BusinessSubscriptionTransition that = (BusinessSubscriptionTransition) o;
+
+        if (bundleExternalKey != null ? !bundleExternalKey.equals(that.bundleExternalKey) : that.bundleExternalKey != null) {
+            return false;
+        }
+        if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+            return false;
+        }
+        if (category != null ? !category.equals(that.category) : that.category != null) {
+            return false;
+        }
+        if (eventType != null ? !eventType.equals(that.eventType) : that.eventType != null) {
+            return false;
+        }
+        if (nextBillingPeriod != null ? !nextBillingPeriod.equals(that.nextBillingPeriod) : that.nextBillingPeriod != null) {
+            return false;
+        }
+        if (nextBusinessActive != null ? !nextBusinessActive.equals(that.nextBusinessActive) : that.nextBusinessActive != null) {
+            return false;
+        }
+        if (nextCurrency != null ? !nextCurrency.equals(that.nextCurrency) : that.nextCurrency != null) {
+            return false;
+        }
+        if (nextEndDate != null ? !nextEndDate.equals(that.nextEndDate) : that.nextEndDate != null) {
+            return false;
+        }
+        if (nextMrr != null ? !nextMrr.equals(that.nextMrr) : that.nextMrr != null) {
+            return false;
+        }
+        if (nextPhase != null ? !nextPhase.equals(that.nextPhase) : that.nextPhase != null) {
+            return false;
+        }
+        if (nextPrice != null ? !nextPrice.equals(that.nextPrice) : that.nextPrice != null) {
+            return false;
+        }
+        if (nextPriceList != null ? !nextPriceList.equals(that.nextPriceList) : that.nextPriceList != null) {
+            return false;
+        }
+        if (nextProductCategory != null ? !nextProductCategory.equals(that.nextProductCategory) : that.nextProductCategory != null) {
+            return false;
+        }
+        if (nextProductName != null ? !nextProductName.equals(that.nextProductName) : that.nextProductName != null) {
+            return false;
+        }
+        if (nextProductType != null ? !nextProductType.equals(that.nextProductType) : that.nextProductType != null) {
+            return false;
+        }
+        if (nextSlug != null ? !nextSlug.equals(that.nextSlug) : that.nextSlug != null) {
+            return false;
+        }
+        if (nextStartDate != null ? !nextStartDate.equals(that.nextStartDate) : that.nextStartDate != null) {
+            return false;
+        }
+        if (nextState != null ? !nextState.equals(that.nextState) : that.nextState != null) {
+            return false;
+        }
+        if (prevBillingPeriod != null ? !prevBillingPeriod.equals(that.prevBillingPeriod) : that.prevBillingPeriod != null) {
+            return false;
+        }
+        if (prevBusinessActive != null ? !prevBusinessActive.equals(that.prevBusinessActive) : that.prevBusinessActive != null) {
+            return false;
+        }
+        if (prevCurrency != null ? !prevCurrency.equals(that.prevCurrency) : that.prevCurrency != null) {
+            return false;
+        }
+        if (prevMrr != null ? !prevMrr.equals(that.prevMrr) : that.prevMrr != null) {
+            return false;
+        }
+        if (prevPhase != null ? !prevPhase.equals(that.prevPhase) : that.prevPhase != null) {
+            return false;
+        }
+        if (prevPrice != null ? !prevPrice.equals(that.prevPrice) : that.prevPrice != null) {
+            return false;
+        }
+        if (prevPriceList != null ? !prevPriceList.equals(that.prevPriceList) : that.prevPriceList != null) {
+            return false;
+        }
+        if (prevProductCategory != null ? !prevProductCategory.equals(that.prevProductCategory) : that.prevProductCategory != null) {
+            return false;
+        }
+        if (prevProductName != null ? !prevProductName.equals(that.prevProductName) : that.prevProductName != null) {
+            return false;
+        }
+        if (prevProductType != null ? !prevProductType.equals(that.prevProductType) : that.prevProductType != null) {
+            return false;
+        }
+        if (prevSlug != null ? !prevSlug.equals(that.prevSlug) : that.prevSlug != null) {
+            return false;
+        }
+        if (prevStartDate != null ? !prevStartDate.equals(that.prevStartDate) : that.prevStartDate != null) {
+            return false;
+        }
+        if (prevState != null ? !prevState.equals(that.prevState) : that.prevState != null) {
+            return false;
+        }
+        if (requestedTimestamp != null ? !requestedTimestamp.equals(that.requestedTimestamp) : that.requestedTimestamp != null) {
+            return false;
+        }
+        if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+        result = 31 * result + (bundleExternalKey != null ? bundleExternalKey.hashCode() : 0);
+        result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
+        result = 31 * result + (requestedTimestamp != null ? requestedTimestamp.hashCode() : 0);
+        result = 31 * result + (eventType != null ? eventType.hashCode() : 0);
+        result = 31 * result + (category != null ? category.hashCode() : 0);
+        result = 31 * result + (prevProductName != null ? prevProductName.hashCode() : 0);
+        result = 31 * result + (prevProductType != null ? prevProductType.hashCode() : 0);
+        result = 31 * result + (prevProductCategory != null ? prevProductCategory.hashCode() : 0);
+        result = 31 * result + (prevSlug != null ? prevSlug.hashCode() : 0);
+        result = 31 * result + (prevPhase != null ? prevPhase.hashCode() : 0);
+        result = 31 * result + (prevBillingPeriod != null ? prevBillingPeriod.hashCode() : 0);
+        result = 31 * result + (prevPrice != null ? prevPrice.hashCode() : 0);
+        result = 31 * result + (prevPriceList != null ? prevPriceList.hashCode() : 0);
+        result = 31 * result + (prevMrr != null ? prevMrr.hashCode() : 0);
+        result = 31 * result + (prevCurrency != null ? prevCurrency.hashCode() : 0);
+        result = 31 * result + (prevBusinessActive != null ? prevBusinessActive.hashCode() : 0);
+        result = 31 * result + (prevStartDate != null ? prevStartDate.hashCode() : 0);
+        result = 31 * result + (prevState != null ? prevState.hashCode() : 0);
+        result = 31 * result + (nextProductName != null ? nextProductName.hashCode() : 0);
+        result = 31 * result + (nextProductType != null ? nextProductType.hashCode() : 0);
+        result = 31 * result + (nextProductCategory != null ? nextProductCategory.hashCode() : 0);
+        result = 31 * result + (nextSlug != null ? nextSlug.hashCode() : 0);
+        result = 31 * result + (nextPhase != null ? nextPhase.hashCode() : 0);
+        result = 31 * result + (nextBillingPeriod != null ? nextBillingPeriod.hashCode() : 0);
+        result = 31 * result + (nextPrice != null ? nextPrice.hashCode() : 0);
+        result = 31 * result + (nextPriceList != null ? nextPriceList.hashCode() : 0);
+        result = 31 * result + (nextMrr != null ? nextMrr.hashCode() : 0);
+        result = 31 * result + (nextCurrency != null ? nextCurrency.hashCode() : 0);
+        result = 31 * result + (nextBusinessActive != null ? nextBusinessActive.hashCode() : 0);
+        result = 31 * result + (nextStartDate != null ? nextStartDate.hashCode() : 0);
+        result = 31 * result + (nextEndDate != null ? nextEndDate.hashCode() : 0);
+        result = 31 * result + (nextState != null ? nextState.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessTag.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessTag.java
index 6f5aabd..4f410d8 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessTag.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/BusinessTag.java
@@ -27,7 +27,7 @@ public class BusinessTag extends BusinessEntityBase {
     private final ObjectType objectType;
     private final String name;
 
-    BusinessTag(final ObjectType objectType, final BusinessTagModelDao businessTagModelDao) {
+    private BusinessTag(final ObjectType objectType, final BusinessTagModelDao businessTagModelDao) {
         super(businessTagModelDao.getCreatedDate(),
               businessTagModelDao.getCreatedBy(),
               businessTagModelDao.getCreatedReasonCode(),
@@ -39,16 +39,16 @@ public class BusinessTag extends BusinessEntityBase {
         this.name = businessTagModelDao.getName();
     }
 
-    public BusinessTag(final BusinessAccountTagModelDao businessAccountTagModelDao) {
-        this(ObjectType.ACCOUNT, businessAccountTagModelDao);
-    }
-
-    public BusinessTag(final BusinessInvoiceTagModelDao businessInvoiceTagModelDao) {
-        this(ObjectType.INVOICE, businessInvoiceTagModelDao);
-    }
-
-    public BusinessTag(final BusinessInvoicePaymentTagModelDao businessInvoicePaymentTagModelDao) {
-        this(ObjectType.PAYMENT, businessInvoicePaymentTagModelDao);
+    public static BusinessTag create(final BusinessTagModelDao businessTagModelDao) {
+        if (businessTagModelDao instanceof BusinessAccountTagModelDao) {
+            return new BusinessTag(ObjectType.ACCOUNT, businessTagModelDao);
+        } else if (businessTagModelDao instanceof BusinessInvoiceTagModelDao) {
+            return new BusinessTag(ObjectType.INVOICE, businessTagModelDao);
+        } else if (businessTagModelDao instanceof BusinessInvoicePaymentTagModelDao) {
+            return new BusinessTag(ObjectType.INVOICE_PAYMENT, businessTagModelDao);
+        } else {
+            return null;
+        }
     }
 
     public ObjectType getObjectType() {
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsDao.java
index 7137c3c..b640ee5 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsDao.java
@@ -17,7 +17,10 @@
 package com.ning.billing.osgi.bundles.analytics.dao;
 
 import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import com.ning.billing.osgi.bundles.analytics.api.BusinessAccount;
@@ -40,6 +43,11 @@ import com.ning.killbill.osgi.libs.killbill.OSGIKillbillAPI;
 import com.ning.killbill.osgi.libs.killbill.OSGIKillbillDataSource;
 import com.ning.killbill.osgi.libs.killbill.OSGIKillbillLogService;
 
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
 public class AnalyticsDao extends BusinessAnalyticsDaoBase {
 
     public AnalyticsDao(final OSGIKillbillLogService logService,
@@ -65,7 +73,12 @@ public class AnalyticsDao extends BusinessAnalyticsDaoBase {
         final Long tenantRecordId = getTenantRecordId(context);
 
         final List<BusinessSubscriptionTransitionModelDao> businessSubscriptionTransitionModelDaos = sqlDao.getSubscriptionTransitionsByAccountRecordId(accountRecordId, tenantRecordId, context);
-        return null;
+        return Lists.transform(businessSubscriptionTransitionModelDaos, new Function<BusinessSubscriptionTransitionModelDao, BusinessSubscriptionTransition>() {
+            @Override
+            public BusinessSubscriptionTransition apply(final BusinessSubscriptionTransitionModelDao input) {
+                return new BusinessSubscriptionTransition(input);
+            }
+        });
     }
 
     public Collection<BusinessOverdueStatus> getOverdueStatusesForAccount(final UUID accountId, final TenantContext context) {
@@ -73,16 +86,34 @@ public class AnalyticsDao extends BusinessAnalyticsDaoBase {
         final Long tenantRecordId = getTenantRecordId(context);
 
         final List<BusinessOverdueStatusModelDao> businessOverdueStatusModelDaos = sqlDao.getOverdueStatusesByAccountRecordId(accountRecordId, tenantRecordId, context);
-        return null;
+        return Lists.transform(businessOverdueStatusModelDaos, new Function<BusinessOverdueStatusModelDao, BusinessOverdueStatus>() {
+            @Override
+            public BusinessOverdueStatus apply(final BusinessOverdueStatusModelDao input) {
+                return new BusinessOverdueStatus(input);
+            }
+        });
     }
 
     public Collection<BusinessInvoice> getInvoicesForAccount(final UUID accountId, final TenantContext context) {
         final Long accountRecordId = getAccountRecordId(accountId);
         final Long tenantRecordId = getTenantRecordId(context);
 
-        final List<BusinessInvoiceModelDao> businessInvoiceModelDaos = sqlDao.getInvoicesByAccountRecordId(accountRecordId, tenantRecordId, context);
         final List<BusinessInvoiceItemBaseModelDao> businessInvoiceItemModelDaos = sqlDao.getInvoiceItemsByAccountRecordId(accountRecordId, tenantRecordId, context);
-        return null;
+        final Map<UUID, List<BusinessInvoiceItemBaseModelDao>> itemsPerInvoice = new LinkedHashMap<UUID, List<BusinessInvoiceItemBaseModelDao>>();
+        for (final BusinessInvoiceItemBaseModelDao businessInvoiceModelDao : businessInvoiceItemModelDaos) {
+            if (itemsPerInvoice.get(businessInvoiceModelDao.getInvoiceId()) == null) {
+                itemsPerInvoice.put(businessInvoiceModelDao.getInvoiceId(), new LinkedList<BusinessInvoiceItemBaseModelDao>());
+            }
+            itemsPerInvoice.get(businessInvoiceModelDao.getInvoiceId()).add(businessInvoiceModelDao);
+        }
+
+        final List<BusinessInvoiceModelDao> businessInvoiceModelDaos = sqlDao.getInvoicesByAccountRecordId(accountRecordId, tenantRecordId, context);
+        return Lists.transform(businessInvoiceModelDaos, new Function<BusinessInvoiceModelDao, BusinessInvoice>() {
+            @Override
+            public BusinessInvoice apply(final BusinessInvoiceModelDao input) {
+                return new BusinessInvoice(input, Objects.firstNonNull(itemsPerInvoice.get(input.getInvoiceId()), ImmutableList.<BusinessInvoiceItemBaseModelDao>of()));
+            }
+        });
     }
 
     public Collection<BusinessInvoicePayment> getInvoicePaymentsForAccount(final UUID accountId, final TenantContext context) {
@@ -90,7 +121,12 @@ public class AnalyticsDao extends BusinessAnalyticsDaoBase {
         final Long tenantRecordId = getTenantRecordId(context);
 
         final List<BusinessInvoicePaymentBaseModelDao> businessInvoicePaymentBaseModelDaos = sqlDao.getInvoicePaymentsByAccountRecordId(accountRecordId, tenantRecordId, context);
-        return null;
+        return Lists.transform(businessInvoicePaymentBaseModelDaos, new Function<BusinessInvoicePaymentBaseModelDao, BusinessInvoicePayment>() {
+            @Override
+            public BusinessInvoicePayment apply(final BusinessInvoicePaymentBaseModelDao input) {
+                return new BusinessInvoicePayment(input);
+            }
+        });
     }
 
     public Collection<BusinessField> getFieldsForAccount(final UUID accountId, final TenantContext context) {
@@ -98,7 +134,12 @@ public class AnalyticsDao extends BusinessAnalyticsDaoBase {
         final Long tenantRecordId = getTenantRecordId(context);
 
         final List<BusinessFieldModelDao> businessFieldModelDaos = sqlDao.getFieldsByAccountRecordId(accountRecordId, tenantRecordId, context);
-        return null;
+        return Lists.transform(businessFieldModelDaos, new Function<BusinessFieldModelDao, BusinessField>() {
+            @Override
+            public BusinessField apply(final BusinessFieldModelDao input) {
+                return BusinessField.create(input);
+            }
+        });
     }
 
     public Collection<BusinessTag> getTagsForAccount(final UUID accountId, final TenantContext context) {
@@ -106,7 +147,12 @@ public class AnalyticsDao extends BusinessAnalyticsDaoBase {
         final Long tenantRecordId = getTenantRecordId(context);
 
         final List<BusinessTagModelDao> businessTagModelDaos = sqlDao.getTagsByAccountRecordId(accountRecordId, tenantRecordId, context);
-        return null;
+        return Lists.transform(businessTagModelDaos, new Function<BusinessTagModelDao, BusinessTag>() {
+            @Override
+            public BusinessTag apply(final BusinessTagModelDao input) {
+                return BusinessTag.create(input);
+            }
+        });
     }
 
     private Long getAccountRecordId(final UUID accountId) {
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java
index f15c1f9..552c5b5 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java
@@ -25,7 +25,6 @@ import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
@@ -57,7 +56,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
     private final BigDecimal invoiceOriginalAmountCharged;
     private final BigDecimal invoiceAmountCredited;
     private final String itemType;
-    private final Boolean recognizable;
+    private final Boolean revenueRecognizable;
     private final String bundleExternalKey;
     private final String productName;
     private final String productType;
@@ -68,7 +67,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
     private final LocalDate startDate;
     private final LocalDate endDate;
     private final BigDecimal amount;
-    private final Currency currency;
+    private final String currency;
     private final UUID linkedItemId;
 
     public static BusinessInvoiceItemBaseModelDao create(final Account account,
@@ -109,7 +108,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
                                             final BigDecimal invoiceOriginalAmountCharged,
                                             final BigDecimal invoiceAmountCredited,
                                             final String itemType,
-                                            final Boolean recognizable,
+                                            final Boolean revenueRecognizable,
                                             final String bundleExternalKey,
                                             final String productName,
                                             final String productType,
@@ -120,7 +119,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
                                             final LocalDate startDate,
                                             final LocalDate endDate,
                                             final BigDecimal amount,
-                                            final Currency currency,
+                                            final String currency,
                                             final UUID linkedItemId,
                                             final DateTime createdDate,
                                             final String createdBy,
@@ -154,7 +153,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
         this.invoiceOriginalAmountCharged = invoiceOriginalAmountCharged;
         this.invoiceAmountCredited = invoiceAmountCredited;
         this.itemType = itemType;
-        this.recognizable = recognizable;
+        this.revenueRecognizable = revenueRecognizable;
         this.bundleExternalKey = bundleExternalKey;
         this.productName = productName;
         this.productType = productType;
@@ -202,7 +201,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
              /* Populate end date for fixed items for convenience (null in invoice_items table) */
              (invoiceItem.getEndDate() == null && planPhase != null) ? invoiceItem.getStartDate().plus(planPhase.getDuration().toJodaPeriod()) : invoiceItem.getEndDate(),
              invoiceItem.getAmount(),
-             invoiceItem.getCurrency(),
+             invoiceItem.getCurrency() == null ? null : invoiceItem.getCurrency().toString(),
              invoiceItem.getLinkedItemId(),
              invoiceItem.getCreatedDate(),
              creationAuditLog.getUserName(),
@@ -272,8 +271,8 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
         return itemType;
     }
 
-    public Boolean getRecognizable() {
-        return recognizable;
+    public Boolean getRevenueRecognizable() {
+        return revenueRecognizable;
     }
 
     public String getBundleExternalKey() {
@@ -316,7 +315,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
         return amount;
     }
 
-    public Currency getCurrency() {
+    public String getCurrency() {
         return currency;
     }
 
@@ -342,7 +341,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
         sb.append(", invoiceOriginalAmountCharged=").append(invoiceOriginalAmountCharged);
         sb.append(", invoiceAmountCredited=").append(invoiceAmountCredited);
         sb.append(", itemType='").append(itemType).append('\'');
-        sb.append(", recognizable=").append(recognizable);
+        sb.append(", revenueRecognizable=").append(revenueRecognizable);
         sb.append(", bundleExternalKey='").append(bundleExternalKey).append('\'');
         sb.append(", productName='").append(productName).append('\'');
         sb.append(", productType='").append(productType).append('\'');
@@ -445,7 +444,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
         if (productType != null ? !productType.equals(that.productType) : that.productType != null) {
             return false;
         }
-        if (recognizable != null ? !recognizable.equals(that.recognizable) : that.recognizable != null) {
+        if (revenueRecognizable != null ? !revenueRecognizable.equals(that.revenueRecognizable) : that.revenueRecognizable != null) {
             return false;
         }
         if (slug != null ? !slug.equals(that.slug) : that.slug != null) {
@@ -475,7 +474,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
         result = 31 * result + (invoiceOriginalAmountCharged != null ? invoiceOriginalAmountCharged.hashCode() : 0);
         result = 31 * result + (invoiceAmountCredited != null ? invoiceAmountCredited.hashCode() : 0);
         result = 31 * result + (itemType != null ? itemType.hashCode() : 0);
-        result = 31 * result + (recognizable != null ? recognizable.hashCode() : 0);
+        result = 31 * result + (revenueRecognizable != null ? revenueRecognizable.hashCode() : 0);
         result = 31 * result + (bundleExternalKey != null ? bundleExternalKey.hashCode() : 0);
         result = 31 * result + (productName != null ? productName.hashCode() : 0);
         result = 31 * result + (productType != null ? productType.hashCode() : 0);
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoicePaymentBaseModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoicePaymentBaseModelDao.java
index e429f79..5937fe2 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoicePaymentBaseModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoicePaymentBaseModelDao.java
@@ -23,7 +23,6 @@ import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
 
 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.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
@@ -56,7 +55,7 @@ public abstract class BusinessInvoicePaymentBaseModelDao extends BusinessModelDa
     private final Long paymentNumber;
     private final UUID linkedInvoicePaymentId;
     private final BigDecimal amount;
-    private final Currency currency;
+    private final String currency;
 
     public static BusinessInvoicePaymentBaseModelDao create(final Account account,
                                                             final Invoice invoice,
@@ -90,7 +89,7 @@ public abstract class BusinessInvoicePaymentBaseModelDao extends BusinessModelDa
                                                final Long paymentNumber,
                                                final UUID linkedInvoicePaymentId,
                                                final BigDecimal amount,
-                                               final Currency currency,
+                                               final String currency,
                                                final DateTime createdDate,
                                                final String createdBy,
                                                final String createdReasonCode,
@@ -152,7 +151,7 @@ public abstract class BusinessInvoicePaymentBaseModelDao extends BusinessModelDa
              null /* TODO */,
              invoicePayment.getLinkedInvoicePaymentId(),
              invoicePayment.getAmount(),
-             invoicePayment.getCurrency(),
+             invoicePayment.getCurrency() == null ? null : invoicePayment.getCurrency().toString(),
              invoicePayment.getCreatedDate(),
              creationAuditLog.getUserName(),
              creationAuditLog.getReasonCode(),
@@ -233,7 +232,7 @@ public abstract class BusinessInvoicePaymentBaseModelDao extends BusinessModelDa
         return amount;
     }
 
-    public Currency getCurrency() {
+    public String getCurrency() {
         return currency;
     }
 
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessSubscription.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessSubscription.java
index c6b33ed..5abbbdb 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessSubscription.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessSubscription.java
@@ -31,7 +31,6 @@ import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
 
 import static com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
@@ -45,7 +44,7 @@ public class BusinessSubscription {
 
     private final String productName;
     private final String productType;
-    private final ProductCategory productCategory;
+    private final String productCategory;
     private final String slug;
     private final String phase;
     private final String billingPeriod;
@@ -53,13 +52,17 @@ public class BusinessSubscription {
     private final String priceList;
     private final BigDecimal mrr;
     private final String currency;
-    private final SubscriptionState state;
+    private final String state;
     private final Boolean businessActive;
     private final DateTime startDate;
     private final DateTime endDate;
 
-    public BusinessSubscription(@Nullable final Plan currentPlan, @Nullable final PlanPhase currentPhase, @Nullable final PriceList priceList,
-                                final Currency currency, final DateTime startDate, final SubscriptionState state) {
+    public BusinessSubscription(@Nullable final Plan currentPlan,
+                                @Nullable final PlanPhase currentPhase,
+                                @Nullable final PriceList priceList,
+                                final Currency currency,
+                                final DateTime startDate,
+                                final SubscriptionState state) {
         // TODO
         businessActive = true;
 
@@ -69,7 +72,7 @@ public class BusinessSubscription {
         if (currentPlan != null && currentPlan.getProduct() != null) {
             final Product product = currentPlan.getProduct();
             productName = product.getName();
-            productCategory = product.getCategory();
+            productCategory = product.getCategory().toString();
             // TODO - we should keep the product type
             productType = product.getCatalogName();
         } else {
@@ -133,7 +136,7 @@ public class BusinessSubscription {
         } else {
             this.endDate = null;
         }
-        this.state = state;
+        this.state = state == null ? null : state.toString();
     }
 
     public String getBillingPeriod() {
@@ -168,7 +171,7 @@ public class BusinessSubscription {
         return Rounder.round(price);
     }
 
-    public ProductCategory getProductCategory() {
+    public String getProductCategory() {
         return productCategory;
     }
 
@@ -196,7 +199,7 @@ public class BusinessSubscription {
         return endDate;
     }
 
-    public SubscriptionState getState() {
+    public String getState() {
         return state;
     }
 
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/ddl.sql b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/ddl.sql
index 14be6f6..c038055 100644
--- a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/ddl.sql
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/ddl.sql
@@ -141,6 +141,7 @@ create table bia (
 , invoice_original_amount_charged numeric(10, 4) default 0
 , invoice_amount_credited numeric(10, 4) default 0
 , item_type char(50) not null
+, revenue_recognizable bool default true
 , bundle_external_key varchar(50) default null
 , product_name varchar(50) default null
 , product_type varchar(50) default null
@@ -186,6 +187,7 @@ create table bii (
 , invoice_original_amount_charged numeric(10, 4) default 0
 , invoice_amount_credited numeric(10, 4) default 0
 , item_type char(50) not null
+, revenue_recognizable bool default true
 , bundle_external_key varchar(50) default null
 , product_name varchar(50) default null
 , product_type varchar(50) default null
@@ -231,6 +233,7 @@ create table biia (
 , invoice_original_amount_charged numeric(10, 4) default 0
 , invoice_amount_credited numeric(10, 4) default 0
 , item_type char(50) not null
+, revenue_recognizable bool default true
 , bundle_external_key varchar(50) default null
 , product_name varchar(50) default null
 , product_type varchar(50) default null
@@ -276,7 +279,7 @@ create table biic (
 , invoice_original_amount_charged numeric(10, 4) default 0
 , invoice_amount_credited numeric(10, 4) default 0
 , item_type char(50) not null
-, recognizable bool default true
+, revenue_recognizable bool default true
 , bundle_external_key varchar(50) default null
 , product_name varchar(50) default null
 , product_type varchar(50) default null
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java
index 490b83f..1343051 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java
@@ -28,36 +28,77 @@ import org.testng.annotations.BeforeMethod;
 
 import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionTransition;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceItemType;
 import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.InvoicePayment.InvoicePaymentType;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.osgi.bundles.analytics.api.BusinessEntityBase;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessModelDaoBase;
 import com.ning.billing.payment.api.Payment;
 import com.ning.billing.payment.api.Payment.PaymentAttempt;
+import com.ning.billing.payment.api.PaymentMethod;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.api.PaymentStatus;
 import com.ning.billing.util.audit.AuditLog;
 import com.ning.billing.util.audit.ChangeType;
+import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.customfield.CustomField;
 import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.TagDefinition;
+import com.ning.killbill.osgi.libs.killbill.OSGIKillbillAPI;
+import com.ning.killbill.osgi.libs.killbill.OSGIKillbillDataSource;
+import com.ning.killbill.osgi.libs.killbill.OSGIKillbillLogService;
 
 import com.google.common.collect.ImmutableList;
 
 public abstract class AnalyticsTestSuiteNoDB {
 
     protected Account account;
+    protected SubscriptionBundle bundle;
+    protected Plan plan;
+    protected PlanPhase phase;
+    protected PriceList priceList;
+    protected SubscriptionTransition subscriptionTransition;
+    protected BlockingState blockingState;
     protected Invoice invoice;
     protected InvoiceItem invoiceItem;
     protected InvoicePayment invoicePayment;
     protected PaymentAttempt paymentAttempt;
+    protected PaymentMethod paymentMethod;
     protected Payment payment;
     protected CustomField customField;
     protected Tag tag;
     protected TagDefinition tagDefinition;
     protected AuditLog auditLog;
+    protected CallContext callContext;
+    protected OSGIKillbillLogService logService;
+    protected OSGIKillbillAPI killbillAPI;
+    protected OSGIKillbillDataSource killbillDataSource;
+
+    protected void verifyBusinessEntityBase(final BusinessEntityBase businessEntityBase) {
+        Assert.assertEquals(businessEntityBase.getCreatedDate(), auditLog.getCreatedDate());
+        Assert.assertEquals(businessEntityBase.getCreatedBy(), auditLog.getUserName());
+        Assert.assertEquals(businessEntityBase.getCreatedReasonCode(), auditLog.getReasonCode());
+        Assert.assertEquals(businessEntityBase.getCreatedComments(), auditLog.getComment());
+        Assert.assertEquals(businessEntityBase.getAccountId(), account.getId());
+        Assert.assertEquals(businessEntityBase.getAccountName(), account.getName());
+        Assert.assertEquals(businessEntityBase.getAccountExternalKey(), account.getExternalKey());
+    }
 
     protected void verifyBusinessModelDaoBase(final BusinessModelDaoBase businessModelDaoBase) {
         //Assert.assertEquals(businessModelDaoBase.getRecordId(), /* TODO */);
@@ -96,6 +137,57 @@ public abstract class AnalyticsTestSuiteNoDB {
         Mockito.when(account.isMigrated()).thenReturn(true);
         Mockito.when(account.isNotifiedForInvoices()).thenReturn(true);
 
+        bundle = Mockito.mock(SubscriptionBundle.class);
+        Mockito.when(bundle.getId()).thenReturn(UUID.randomUUID());
+        Mockito.when(bundle.getAccountId()).thenReturn(account.getId());
+        Mockito.when(bundle.getExternalKey()).thenReturn(UUID.randomUUID().toString());
+
+        final Product product = Mockito.mock(Product.class);
+        Mockito.when(product.getName()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(product.isRetired()).thenReturn(true);
+        Mockito.when(product.getCategory()).thenReturn(ProductCategory.STANDALONE);
+        Mockito.when(product.getCatalogName()).thenReturn(UUID.randomUUID().toString());
+
+        plan = Mockito.mock(Plan.class);
+        Mockito.when(plan.getProduct()).thenReturn(product);
+        Mockito.when(plan.getName()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(plan.isRetired()).thenReturn(true);
+        Mockito.when(plan.getBillingPeriod()).thenReturn(BillingPeriod.QUARTERLY);
+        Mockito.when(plan.getEffectiveDateForExistingSubscriptons()).thenReturn(new DateTime(2016, 1, 22, 10, 56, 59, DateTimeZone.UTC).toDate());
+
+        phase = Mockito.mock(PlanPhase.class);
+        Mockito.when(phase.getBillingPeriod()).thenReturn(BillingPeriod.QUARTERLY);
+        Mockito.when(phase.getName()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(phase.getPlan()).thenReturn(plan);
+        Mockito.when(phase.getPhaseType()).thenReturn(PhaseType.DISCOUNT);
+
+        priceList = Mockito.mock(PriceList.class);
+        Mockito.when(priceList.getName()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(priceList.isRetired()).thenReturn(false);
+
+        subscriptionTransition = Mockito.mock(SubscriptionTransition.class);
+        Mockito.when(subscriptionTransition.getSubscriptionId()).thenReturn(UUID.randomUUID());
+        Mockito.when(subscriptionTransition.getBundleId()).thenReturn(bundle.getId());
+        Mockito.when(subscriptionTransition.getNextState()).thenReturn(SubscriptionState.ACTIVE);
+        Mockito.when(subscriptionTransition.getNextPlan()).thenReturn(plan);
+        Mockito.when(subscriptionTransition.getNextPhase()).thenReturn(phase);
+        Mockito.when(subscriptionTransition.getNextPriceList()).thenReturn(priceList);
+        Mockito.when(subscriptionTransition.getRequestedTransitionTime()).thenReturn(new DateTime(2010, 1, 2, 3, 4, 5, DateTimeZone.UTC));
+        Mockito.when(subscriptionTransition.getEffectiveTransitionTime()).thenReturn(new DateTime(2011, 2, 3, 4, 5, 6, DateTimeZone.UTC));
+        Mockito.when(subscriptionTransition.getTransitionType()).thenReturn(SubscriptionTransitionType.CREATE);
+
+        blockingState = Mockito.mock(BlockingState.class);
+        Mockito.when(blockingState.getId()).thenReturn(UUID.randomUUID());
+        Mockito.when(blockingState.getBlockedId()).thenReturn(bundle.getId());
+        Mockito.when(blockingState.getStateName()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(blockingState.getType()).thenReturn(Type.SUBSCRIPTION_BUNDLE);
+        Mockito.when(blockingState.getTimestamp()).thenReturn(new DateTime(2010, 2, 2, 4, 22, 22, DateTimeZone.UTC));
+        Mockito.when(blockingState.isBlockBilling()).thenReturn(true);
+        Mockito.when(blockingState.isBlockChange()).thenReturn(false);
+        Mockito.when(blockingState.isBlockEntitlement()).thenReturn(true);
+        Mockito.when(blockingState.getDescription()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(blockingState.getService()).thenReturn(UUID.randomUUID().toString());
+
         invoiceItem = Mockito.mock(InvoiceItem.class);
         Mockito.when(invoiceItem.getId()).thenReturn(UUID.randomUUID());
         Mockito.when(invoiceItem.getInvoiceItemType()).thenReturn(InvoiceItemType.EXTERNAL_CHARGE);
@@ -106,10 +198,10 @@ public abstract class AnalyticsTestSuiteNoDB {
         Mockito.when(invoiceItem.getAmount()).thenReturn(new BigDecimal("12000"));
         Mockito.when(invoiceItem.getCurrency()).thenReturn(Currency.EUR);
         Mockito.when(invoiceItem.getDescription()).thenReturn(UUID.randomUUID().toString());
-        Mockito.when(invoiceItem.getBundleId()).thenReturn(UUID.randomUUID());
-        Mockito.when(invoiceItem.getSubscriptionId()).thenReturn(UUID.randomUUID());
-        Mockito.when(invoiceItem.getPlanName()).thenReturn(UUID.randomUUID().toString());
-        Mockito.when(invoiceItem.getPhaseName()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(invoiceItem.getBundleId()).thenReturn(bundle.getId());
+        Mockito.when(invoiceItem.getSubscriptionId()).thenReturn(subscriptionTransition.getSubscriptionId());
+        Mockito.when(invoiceItem.getPlanName()).thenReturn(plan.getName());
+        Mockito.when(invoiceItem.getPhaseName()).thenReturn(phase.getName());
         Mockito.when(invoiceItem.getRate()).thenReturn(new BigDecimal("1203"));
         Mockito.when(invoiceItem.getLinkedItemId()).thenReturn(UUID.randomUUID());
 
@@ -117,7 +209,7 @@ public abstract class AnalyticsTestSuiteNoDB {
         Mockito.when(invoicePayment.getId()).thenReturn(UUID.randomUUID());
         Mockito.when(invoicePayment.getPaymentId()).thenReturn(UUID.randomUUID());
         Mockito.when(invoicePayment.getType()).thenReturn(InvoicePaymentType.ATTEMPT);
-        Mockito.when(invoicePayment.getInvoiceId()).thenReturn(UUID.randomUUID());
+        Mockito.when(invoicePayment.getInvoiceId()).thenReturn(invoice.getId());
         Mockito.when(invoicePayment.getPaymentDate()).thenReturn(new DateTime(2003, 4, 12, 3, 34, 52, DateTimeZone.UTC));
         Mockito.when(invoicePayment.getAmount()).thenReturn(BigDecimal.ONE);
         Mockito.when(invoicePayment.getCurrency()).thenReturn(Currency.MXN);
@@ -127,10 +219,10 @@ public abstract class AnalyticsTestSuiteNoDB {
         invoice = Mockito.mock(Invoice.class);
         Mockito.when(invoice.getId()).thenReturn(UUID.randomUUID());
         Mockito.when(invoice.getInvoiceItems()).thenReturn(ImmutableList.<InvoiceItem>of(invoiceItem));
-        Mockito.when(invoice.getNumberOfItems()).thenReturn(6);
+        Mockito.when(invoice.getNumberOfItems()).thenReturn(1);
         Mockito.when(invoice.getPayments()).thenReturn(ImmutableList.<InvoicePayment>of(invoicePayment));
-        Mockito.when(invoice.getNumberOfPayments()).thenReturn(3);
-        Mockito.when(invoice.getAccountId()).thenReturn(UUID.randomUUID());
+        Mockito.when(invoice.getNumberOfPayments()).thenReturn(1);
+        Mockito.when(invoice.getAccountId()).thenReturn(account.getId());
         Mockito.when(invoice.getInvoiceNumber()).thenReturn(42);
         Mockito.when(invoice.getInvoiceDate()).thenReturn(new LocalDate(1954, 12, 1));
         Mockito.when(invoice.getTargetDate()).thenReturn(new LocalDate(2017, 3, 4));
@@ -152,11 +244,22 @@ public abstract class AnalyticsTestSuiteNoDB {
         Mockito.when(paymentAttempt.getGatewayErrorMsg()).thenReturn(UUID.randomUUID().toString());
         Mockito.when(paymentAttempt.getPaymentStatus()).thenReturn(PaymentStatus.SUCCESS);
 
+        final PaymentMethodPlugin paymentMethodPlugin = Mockito.mock(PaymentMethodPlugin.class);
+        Mockito.when(paymentMethodPlugin.getExternalPaymentMethodId()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(paymentMethodPlugin.isDefaultPaymentMethod()).thenReturn(true);
+
+        paymentMethod = Mockito.mock(PaymentMethod.class);
+        Mockito.when(paymentMethod.getId()).thenReturn(UUID.randomUUID());
+        Mockito.when(paymentMethod.getAccountId()).thenReturn(account.getId());
+        Mockito.when(paymentMethod.isActive()).thenReturn(true);
+        Mockito.when(paymentMethod.getPluginName()).thenReturn(UUID.randomUUID().toString());
+        Mockito.when(paymentMethod.getPluginDetail()).thenReturn(paymentMethodPlugin);
+
         payment = Mockito.mock(Payment.class);
         Mockito.when(payment.getId()).thenReturn(UUID.randomUUID());
-        Mockito.when(payment.getAccountId()).thenReturn(UUID.randomUUID());
-        Mockito.when(payment.getInvoiceId()).thenReturn(UUID.randomUUID());
-        Mockito.when(payment.getPaymentMethodId()).thenReturn(UUID.randomUUID());
+        Mockito.when(payment.getAccountId()).thenReturn(account.getId());
+        Mockito.when(payment.getInvoiceId()).thenReturn(invoice.getId());
+        Mockito.when(payment.getPaymentMethodId()).thenReturn(paymentMethod.getId());
         Mockito.when(payment.getPaymentNumber()).thenReturn(1);
         Mockito.when(payment.getAmount()).thenReturn(new BigDecimal("199999"));
         Mockito.when(payment.getPaidAmount()).thenReturn(new BigDecimal("199998"));
@@ -194,5 +297,9 @@ public abstract class AnalyticsTestSuiteNoDB {
         Mockito.when(auditLog.getReasonCode()).thenReturn(UUID.randomUUID().toString());
         Mockito.when(auditLog.getUserToken()).thenReturn(UUID.randomUUID().toString());
         Mockito.when(auditLog.getComment()).thenReturn(UUID.randomUUID().toString());
+
+        callContext = Mockito.mock(CallContext.class);
+        killbillAPI = Mockito.mock(OSGIKillbillAPI.class);
+        killbillDataSource = Mockito.mock(OSGIKillbillDataSource.class);
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteWithEmbeddedDB.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteWithEmbeddedDB.java
index d2c3a54..5a94a46 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteWithEmbeddedDB.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteWithEmbeddedDB.java
@@ -16,5 +16,71 @@
 
 package com.ning.billing.osgi.bundles.analytics;
 
+import java.io.IOException;
+
+import javax.sql.DataSource;
+
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+import org.skife.jdbi.v2.DBI;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+
+import com.ning.billing.commons.embeddeddb.h2.H2EmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAnalyticsSqlDao;
+import com.ning.billing.util.io.IOUtils;
+import com.ning.killbill.osgi.libs.killbill.OSGIKillbillDataSource;
+
+import com.google.common.io.Resources;
+
 public abstract class AnalyticsTestSuiteWithEmbeddedDB extends AnalyticsTestSuiteNoDB {
+
+    protected H2EmbeddedDB embeddedDB;
+    protected DBI dbi;
+    protected BusinessAnalyticsSqlDao analyticsSqlDao;
+
+    @BeforeClass(groups = "slow")
+    public void setUpClass() throws Exception {
+        embeddedDB = new H2EmbeddedDB();
+        embeddedDB.initialize();
+        embeddedDB.start();
+    }
+
+    @BeforeMethod(groups = "slow")
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        killbillDataSource = new AnalyticsOSGIKillbillDataSource();
+
+        final String ddl = IOUtils.toString(Resources.getResource("com/ning/billing/osgi/bundles/analytics").openStream());
+        embeddedDB.executeScript(ddl);
+
+        dbi = new DBI(embeddedDB.getDataSource());
+        analyticsSqlDao = dbi.onDemand(BusinessAnalyticsSqlDao.class);
+    }
+
+    @AfterClass(groups = "slow")
+    public void tearDown() throws Exception {
+        embeddedDB.stop();
+    }
+
+    private final class AnalyticsOSGIKillbillDataSource extends OSGIKillbillDataSource {
+
+        public AnalyticsOSGIKillbillDataSource() {
+            super(Mockito.mock(BundleContext.class));
+        }
+
+        @Override
+        public DataSource getDataSource() {
+            try {
+                return embeddedDB.getDataSource();
+            } catch (IOException e) {
+                Assert.fail(e.toString(), e);
+                return null;
+            }
+        }
+    }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessAccount.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessAccount.java
new file mode 100644
index 0000000..c24a6a2
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessAccount.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import java.math.BigDecimal;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountModelDao;
+
+public class TestBusinessAccount extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final BusinessAccountModelDao accountModelDao = new BusinessAccountModelDao(account,
+                                                                                    BigDecimal.ONE,
+                                                                                    invoice,
+                                                                                    payment,
+                                                                                    auditLog);
+        final BusinessAccount businessAccount = new BusinessAccount(accountModelDao);
+
+        verifyBusinessEntityBase(businessAccount);
+        Assert.assertEquals(businessAccount.getEmail(), accountModelDao.getEmail());
+        Assert.assertEquals(businessAccount.getFirstNameLength(), accountModelDao.getFirstNameLength());
+        Assert.assertEquals(businessAccount.getCurrency(), accountModelDao.getCurrency());
+        Assert.assertEquals(businessAccount.getBillingCycleDayLocal(), accountModelDao.getBillingCycleDayLocal());
+        Assert.assertEquals(businessAccount.getAddress1(), accountModelDao.getAddress1());
+        Assert.assertEquals(businessAccount.getAddress2(), accountModelDao.getAddress2());
+        Assert.assertEquals(businessAccount.getCompanyName(), accountModelDao.getCompanyName());
+        Assert.assertEquals(businessAccount.getCity(), accountModelDao.getCity());
+        Assert.assertEquals(businessAccount.getStateOrProvince(), accountModelDao.getStateOrProvince());
+        Assert.assertEquals(businessAccount.getCountry(), accountModelDao.getCountry());
+        Assert.assertEquals(businessAccount.getPostalCode(), accountModelDao.getPostalCode());
+        Assert.assertEquals(businessAccount.getPhone(), accountModelDao.getPhone());
+        Assert.assertEquals(businessAccount.getMigrated(), accountModelDao.getMigrated());
+        Assert.assertEquals(businessAccount.getNotifiedForInvoices(), accountModelDao.getNotifiedForInvoices());
+        Assert.assertEquals(businessAccount.getBalance(), accountModelDao.getBalance());
+        Assert.assertEquals(businessAccount.getLastInvoiceDate(), accountModelDao.getLastInvoiceDate());
+        Assert.assertEquals(businessAccount.getLastPaymentDate(), accountModelDao.getLastPaymentDate());
+        Assert.assertEquals(businessAccount.getLastPaymentStatus(), accountModelDao.getLastPaymentStatus());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessField.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessField.java
new file mode 100644
index 0000000..d768ef7
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessField.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentFieldModelDao;
+
+public class TestBusinessField extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructorAccount() throws Exception {
+        final BusinessAccountFieldModelDao businessAccountFieldModelDao = new BusinessAccountFieldModelDao(account, customField, auditLog);
+        final BusinessField businessField = BusinessField.create(businessAccountFieldModelDao);
+        verifyBusinessField(businessField);
+        Assert.assertEquals(businessField.getObjectType(), ObjectType.ACCOUNT);
+    }
+
+    @Test(groups = "fast")
+    public void testConstructorInvoice() throws Exception {
+        final BusinessInvoiceFieldModelDao businessInvoiceFieldModelDao = new BusinessInvoiceFieldModelDao(account, customField, auditLog);
+        final BusinessField businessField = BusinessField.create(businessInvoiceFieldModelDao);
+        verifyBusinessField(businessField);
+        Assert.assertEquals(businessField.getObjectType(), ObjectType.INVOICE);
+    }
+
+    @Test(groups = "fast")
+    public void testConstructorPayment() throws Exception {
+        final BusinessInvoicePaymentFieldModelDao invoicePaymentFieldModelDao = new BusinessInvoicePaymentFieldModelDao(account, customField, auditLog);
+        final BusinessField businessField = BusinessField.create(invoicePaymentFieldModelDao);
+        verifyBusinessField(businessField);
+        Assert.assertEquals(businessField.getObjectType(), ObjectType.INVOICE_PAYMENT);
+    }
+
+    private void verifyBusinessField(final BusinessField accountField) {
+        verifyBusinessEntityBase(accountField);
+        Assert.assertEquals(accountField.getName(), customField.getFieldName());
+        Assert.assertEquals(accountField.getValue(), customField.getFieldValue());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoice.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoice.java
new file mode 100644
index 0000000..23048e7
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoice.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceModelDao;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestBusinessInvoice extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final BusinessInvoiceModelDao invoiceModelDao = new BusinessInvoiceModelDao(account, invoice, auditLog);
+        final BusinessInvoiceItemBaseModelDao invoiceItemBaseModelDao = BusinessInvoiceItemBaseModelDao.create(account,
+                                                                                                               invoice,
+                                                                                                               invoiceItem,
+                                                                                                               bundle,
+                                                                                                               plan,
+                                                                                                               phase,
+                                                                                                               auditLog);
+        final BusinessInvoice businessInvoice = new BusinessInvoice(invoiceModelDao,
+                                                                    ImmutableList.<BusinessInvoiceItemBaseModelDao>of(invoiceItemBaseModelDao));
+        verifyBusinessEntityBase(businessInvoice);
+        Assert.assertEquals(businessInvoice.getInvoiceId(), invoiceModelDao.getInvoiceId());
+        Assert.assertEquals(businessInvoice.getInvoiceNumber(), invoiceModelDao.getInvoiceNumber());
+        Assert.assertEquals(businessInvoice.getInvoiceDate(), invoiceModelDao.getInvoiceDate());
+        Assert.assertEquals(businessInvoice.getTargetDate(), invoiceModelDao.getTargetDate());
+        Assert.assertEquals(businessInvoice.getCurrency(), invoiceModelDao.getCurrency());
+        Assert.assertEquals(businessInvoice.getBalance(), invoiceModelDao.getBalance());
+        Assert.assertEquals(businessInvoice.getAmountPaid(), invoiceModelDao.getAmountPaid());
+        Assert.assertEquals(businessInvoice.getAmountCharged(), invoiceModelDao.getAmountCharged());
+        Assert.assertEquals(businessInvoice.getOriginalAmountCharged(), invoiceModelDao.getOriginalAmountCharged());
+        Assert.assertEquals(businessInvoice.getAmountCredited(), invoiceModelDao.getAmountCredited());
+        Assert.assertEquals(businessInvoice.getInvoiceItems().size(), 1);
+
+        final BusinessInvoiceItem businessInvoiceItem = businessInvoice.getInvoiceItems().get(0);
+        verifyBusinessEntityBase(businessInvoiceItem);
+        Assert.assertEquals(businessInvoiceItem.getItemId(), invoiceItemBaseModelDao.getItemId());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceId(), invoiceItemBaseModelDao.getInvoiceId());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceNumber(), invoiceItemBaseModelDao.getInvoiceNumber());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceCreatedDate(), invoiceItemBaseModelDao.getInvoiceCreatedDate());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceDate(), invoiceItemBaseModelDao.getInvoiceDate());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceTargetDate(), invoiceItemBaseModelDao.getInvoiceTargetDate());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceCurrency(), invoiceItemBaseModelDao.getInvoiceCurrency());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceBalance(), invoiceItemBaseModelDao.getInvoiceBalance());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceAmountPaid(), invoiceItemBaseModelDao.getInvoiceAmountPaid());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceAmountCharged(), invoiceItemBaseModelDao.getInvoiceAmountCharged());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceOriginalAmountCharged(), invoiceItemBaseModelDao.getInvoiceOriginalAmountCharged());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceAmountCredited(), invoiceItemBaseModelDao.getInvoiceAmountCredited());
+        Assert.assertEquals(businessInvoiceItem.getItemType(), invoiceItemBaseModelDao.getItemType());
+        Assert.assertEquals(businessInvoiceItem.getRecognizable(), invoiceItemBaseModelDao.getRevenueRecognizable());
+        Assert.assertEquals(businessInvoiceItem.getBundleExternalKey(), invoiceItemBaseModelDao.getBundleExternalKey());
+        Assert.assertEquals(businessInvoiceItem.getProductName(), invoiceItemBaseModelDao.getProductName());
+        Assert.assertEquals(businessInvoiceItem.getProductType(), invoiceItemBaseModelDao.getProductType());
+        Assert.assertEquals(businessInvoiceItem.getProductCategory(), invoiceItemBaseModelDao.getProductCategory());
+        Assert.assertEquals(businessInvoiceItem.getSlug(), invoiceItemBaseModelDao.getSlug());
+        Assert.assertEquals(businessInvoiceItem.getPhase(), invoiceItemBaseModelDao.getPhase());
+        Assert.assertEquals(businessInvoiceItem.getBillingPeriod(), invoiceItemBaseModelDao.getBillingPeriod());
+        Assert.assertEquals(businessInvoiceItem.getStartDate(), invoiceItemBaseModelDao.getStartDate());
+        Assert.assertEquals(businessInvoiceItem.getEndDate(), invoiceItemBaseModelDao.getEndDate());
+        Assert.assertEquals(businessInvoiceItem.getAmount(), invoiceItemBaseModelDao.getAmount());
+        Assert.assertEquals(businessInvoiceItem.getCurrency(), invoiceItemBaseModelDao.getCurrency());
+        Assert.assertEquals(businessInvoiceItem.getLinkedItemId(), invoiceItemBaseModelDao.getLinkedItemId());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoiceItem.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoiceItem.java
new file mode 100644
index 0000000..b60af52
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoiceItem.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao;
+
+public class TestBusinessInvoiceItem extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final BusinessInvoiceItemBaseModelDao invoiceItemBaseModelDao = BusinessInvoiceItemBaseModelDao.create(account,
+                                                                                                               invoice,
+                                                                                                               invoiceItem,
+                                                                                                               bundle,
+                                                                                                               plan,
+                                                                                                               phase,
+                                                                                                               auditLog);
+        final BusinessInvoiceItem businessInvoiceItem = new BusinessInvoiceItem(invoiceItemBaseModelDao);
+        verifyBusinessEntityBase(businessInvoiceItem);
+        Assert.assertEquals(businessInvoiceItem.getItemId(), invoiceItemBaseModelDao.getItemId());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceId(), invoiceItemBaseModelDao.getInvoiceId());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceNumber(), invoiceItemBaseModelDao.getInvoiceNumber());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceCreatedDate(), invoiceItemBaseModelDao.getInvoiceCreatedDate());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceDate(), invoiceItemBaseModelDao.getInvoiceDate());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceTargetDate(), invoiceItemBaseModelDao.getInvoiceTargetDate());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceCurrency(), invoiceItemBaseModelDao.getInvoiceCurrency());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceBalance(), invoiceItemBaseModelDao.getInvoiceBalance());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceAmountPaid(), invoiceItemBaseModelDao.getInvoiceAmountPaid());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceAmountCharged(), invoiceItemBaseModelDao.getInvoiceAmountCharged());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceOriginalAmountCharged(), invoiceItemBaseModelDao.getInvoiceOriginalAmountCharged());
+        Assert.assertEquals(businessInvoiceItem.getInvoiceAmountCredited(), invoiceItemBaseModelDao.getInvoiceAmountCredited());
+        Assert.assertEquals(businessInvoiceItem.getItemType(), invoiceItemBaseModelDao.getItemType());
+        Assert.assertEquals(businessInvoiceItem.getRecognizable(), invoiceItemBaseModelDao.getRevenueRecognizable());
+        Assert.assertEquals(businessInvoiceItem.getBundleExternalKey(), invoiceItemBaseModelDao.getBundleExternalKey());
+        Assert.assertEquals(businessInvoiceItem.getProductName(), invoiceItemBaseModelDao.getProductName());
+        Assert.assertEquals(businessInvoiceItem.getProductType(), invoiceItemBaseModelDao.getProductType());
+        Assert.assertEquals(businessInvoiceItem.getProductCategory(), invoiceItemBaseModelDao.getProductCategory());
+        Assert.assertEquals(businessInvoiceItem.getSlug(), invoiceItemBaseModelDao.getSlug());
+        Assert.assertEquals(businessInvoiceItem.getPhase(), invoiceItemBaseModelDao.getPhase());
+        Assert.assertEquals(businessInvoiceItem.getBillingPeriod(), invoiceItemBaseModelDao.getBillingPeriod());
+        Assert.assertEquals(businessInvoiceItem.getStartDate(), invoiceItemBaseModelDao.getStartDate());
+        Assert.assertEquals(businessInvoiceItem.getEndDate(), invoiceItemBaseModelDao.getEndDate());
+        Assert.assertEquals(businessInvoiceItem.getAmount(), invoiceItemBaseModelDao.getAmount());
+        Assert.assertEquals(businessInvoiceItem.getCurrency(), invoiceItemBaseModelDao.getCurrency());
+        Assert.assertEquals(businessInvoiceItem.getLinkedItemId(), invoiceItemBaseModelDao.getLinkedItemId());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoicePayment.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoicePayment.java
new file mode 100644
index 0000000..7521def
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoicePayment.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentBaseModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentModelDao;
+
+public class TestBusinessInvoicePayment extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final BusinessInvoicePaymentBaseModelDao invoicePaymentBaseModelDao = BusinessInvoicePaymentModelDao.create(account,
+                                                                                                                    invoice,
+                                                                                                                    invoicePayment,
+                                                                                                                    payment,
+                                                                                                                    paymentMethod,
+                                                                                                                    auditLog);
+        final BusinessInvoicePayment businessInvoicePayment = new BusinessInvoicePayment(invoicePaymentBaseModelDao);
+        verifyBusinessEntityBase(businessInvoicePayment);
+        Assert.assertEquals(businessInvoicePayment.getInvoicePaymentId(), invoicePaymentBaseModelDao.getInvoicePaymentId());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceId(), invoicePaymentBaseModelDao.getInvoiceId());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceNumber(), invoicePaymentBaseModelDao.getInvoiceNumber());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceCreatedDate(), invoicePaymentBaseModelDao.getInvoiceCreatedDate());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceDate(), invoicePaymentBaseModelDao.getInvoiceDate());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceTargetDate(), invoicePaymentBaseModelDao.getInvoiceTargetDate());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceCurrency(), invoicePaymentBaseModelDao.getInvoiceCurrency());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceBalance(), invoicePaymentBaseModelDao.getInvoiceBalance());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceAmountPaid(), invoicePaymentBaseModelDao.getInvoiceAmountPaid());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceAmountCharged(), invoicePaymentBaseModelDao.getInvoiceAmountCharged());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceOriginalAmountCharged(), invoicePaymentBaseModelDao.getInvoiceOriginalAmountCharged());
+        Assert.assertEquals(businessInvoicePayment.getInvoiceAmountCredited(), invoicePaymentBaseModelDao.getInvoiceAmountCredited());
+        Assert.assertEquals(businessInvoicePayment.getInvoicePaymentType(), invoicePaymentBaseModelDao.getInvoicePaymentType());
+        Assert.assertEquals(businessInvoicePayment.getPaymentNumber(), invoicePaymentBaseModelDao.getPaymentNumber());
+        Assert.assertEquals(businessInvoicePayment.getLinkedInvoicePaymentId(), invoicePaymentBaseModelDao.getLinkedInvoicePaymentId());
+        Assert.assertEquals(businessInvoicePayment.getAmount(), invoicePaymentBaseModelDao.getAmount());
+        Assert.assertEquals(businessInvoicePayment.getCurrency(), invoicePaymentBaseModelDao.getCurrency());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSnapshot.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSnapshot.java
new file mode 100644
index 0000000..acc538b
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSnapshot.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import java.math.BigDecimal;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentBaseModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessOverdueStatusModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscription;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionEvent;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionTransitionModelDao;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestBusinessSnapshot extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        // Account
+        final BusinessAccountModelDao accountModelDao = new BusinessAccountModelDao(account,
+                                                                                    BigDecimal.ONE,
+                                                                                    invoice,
+                                                                                    payment,
+                                                                                    auditLog);
+        final BusinessAccount businessAccount = new BusinessAccount(accountModelDao);
+
+        // Field
+        final BusinessAccountFieldModelDao businessAccountFieldModelDao = new BusinessAccountFieldModelDao(account, customField, auditLog);
+        final BusinessField businessField = BusinessField.create(businessAccountFieldModelDao);
+
+        // Invoice
+        final BusinessInvoiceModelDao invoiceModelDao = new BusinessInvoiceModelDao(account, invoice, auditLog);
+        final BusinessInvoiceItemBaseModelDao invoiceItemBaseModelDao = BusinessInvoiceItemBaseModelDao.create(account,
+                                                                                                               invoice,
+                                                                                                               invoiceItem,
+                                                                                                               bundle,
+                                                                                                               plan,
+                                                                                                               phase,
+                                                                                                               auditLog);
+        final BusinessInvoice businessInvoice = new BusinessInvoice(invoiceModelDao,
+                                                                    ImmutableList.<BusinessInvoiceItemBaseModelDao>of(invoiceItemBaseModelDao));
+
+        // Invoice payment
+        final BusinessInvoicePaymentBaseModelDao invoicePaymentBaseModelDao = BusinessInvoicePaymentModelDao.create(account,
+                                                                                                                    invoice,
+                                                                                                                    invoicePayment,
+                                                                                                                    payment,
+                                                                                                                    paymentMethod,
+                                                                                                                    auditLog);
+        final BusinessInvoicePayment businessInvoicePayment = new BusinessInvoicePayment(invoicePaymentBaseModelDao);
+
+        // Overdue
+        final DateTime endDate = new DateTime(2005, 6, 5, 4, 5, 6, DateTimeZone.UTC);
+        final BusinessOverdueStatusModelDao businessOverdueStatusModelDao = new BusinessOverdueStatusModelDao(account,
+                                                                                                              bundle,
+                                                                                                              blockingState,
+                                                                                                              endDate,
+                                                                                                              auditLog);
+        final BusinessOverdueStatus businessOverdueStatus = new BusinessOverdueStatus(businessOverdueStatusModelDao);
+
+        // Subscriptions
+        final DateTime startDate = new DateTime(2012, 6, 5, 4, 3, 12, DateTimeZone.UTC);
+        final DateTime requestedTimestamp = new DateTime(2012, 7, 21, 10, 10, 10, DateTimeZone.UTC);
+
+        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf("ADD_BASE");
+        final BusinessSubscription previousSubscription = null;
+        final BusinessSubscription nextSubscription = new BusinessSubscription(null, null, null, Currency.GBP, startDate, SubscriptionState.ACTIVE);
+        final BusinessSubscriptionTransitionModelDao subscriptionTransitionModelDao = new BusinessSubscriptionTransitionModelDao(account,
+                                                                                                                                 bundle,
+                                                                                                                                 subscriptionTransition,
+                                                                                                                                 requestedTimestamp,
+                                                                                                                                 event,
+                                                                                                                                 previousSubscription,
+                                                                                                                                 nextSubscription,
+                                                                                                                                 auditLog);
+        final BusinessSubscriptionTransition businessSubscriptionTransition = new BusinessSubscriptionTransition(subscriptionTransitionModelDao);
+
+        // Tag
+        final BusinessAccountTagModelDao businessAccountTagModelDao = new BusinessAccountTagModelDao(account,
+                                                                                                     tag,
+                                                                                                     tagDefinition,
+                                                                                                     auditLog);
+        final BusinessTag businessTag = BusinessTag.create(businessAccountTagModelDao);
+
+        // Create the snapshot
+        final BusinessSnapshot businessSnapshot = new BusinessSnapshot(businessAccount,
+                                                                       ImmutableList.<BusinessSubscriptionTransition>of(businessSubscriptionTransition),
+                                                                       ImmutableList.<BusinessInvoice>of(businessInvoice),
+                                                                       ImmutableList.<BusinessInvoicePayment>of(businessInvoicePayment),
+                                                                       ImmutableList.<BusinessOverdueStatus>of(businessOverdueStatus),
+                                                                       ImmutableList.<BusinessTag>of(businessTag),
+                                                                       ImmutableList.<BusinessField>of(businessField));
+        Assert.assertEquals(businessSnapshot.getBusinessAccount(), businessAccount);
+        Assert.assertEquals(businessSnapshot.getBusinessSubscriptionTransitions().size(), 1);
+        Assert.assertEquals(businessSnapshot.getBusinessSubscriptionTransitions().iterator().next(), businessSubscriptionTransition);
+        Assert.assertEquals(businessSnapshot.getBusinessInvoices().size(), 1);
+        Assert.assertEquals(businessSnapshot.getBusinessInvoices().iterator().next(), businessInvoice);
+        Assert.assertEquals(businessSnapshot.getBusinessInvoicePayments().size(), 1);
+        Assert.assertEquals(businessSnapshot.getBusinessInvoicePayments().iterator().next(), businessInvoicePayment);
+        Assert.assertEquals(businessSnapshot.getBusinessOverdueStatuses().size(), 1);
+        Assert.assertEquals(businessSnapshot.getBusinessOverdueStatuses().iterator().next(), businessOverdueStatus);
+        Assert.assertEquals(businessSnapshot.getBusinessTags().size(), 1);
+        Assert.assertEquals(businessSnapshot.getBusinessTags().iterator().next(), businessTag);
+        Assert.assertEquals(businessSnapshot.getBusinessFields().size(), 1);
+        Assert.assertEquals(businessSnapshot.getBusinessFields().iterator().next(), businessField);
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSubscriptionTransition.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSubscriptionTransition.java
new file mode 100644
index 0000000..2edd44f
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSubscriptionTransition.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscription;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionEvent;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionTransitionModelDao;
+
+public class TestBusinessSubscriptionTransition extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final DateTime startDate = new DateTime(2012, 6, 5, 4, 3, 12, DateTimeZone.UTC);
+        final DateTime requestedTimestamp = new DateTime(2012, 7, 21, 10, 10, 10, DateTimeZone.UTC);
+
+        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf("ADD_BASE");
+        final BusinessSubscription previousSubscription = null;
+        final BusinessSubscription nextSubscription = new BusinessSubscription(null, null, null, Currency.GBP, startDate, SubscriptionState.ACTIVE);
+        final BusinessSubscriptionTransitionModelDao subscriptionTransitionModelDao = new BusinessSubscriptionTransitionModelDao(account,
+                                                                                                                                 bundle,
+                                                                                                                                 subscriptionTransition,
+                                                                                                                                 requestedTimestamp,
+                                                                                                                                 event,
+                                                                                                                                 previousSubscription,
+                                                                                                                                 nextSubscription,
+                                                                                                                                 auditLog);
+        final BusinessSubscriptionTransition businessSubscriptionTransition = new BusinessSubscriptionTransition(subscriptionTransitionModelDao);
+
+        verifyBusinessEntityBase(businessSubscriptionTransition);
+        Assert.assertEquals(businessSubscriptionTransition.getBundleId(), subscriptionTransitionModelDao.getBundleId());
+        Assert.assertEquals(businessSubscriptionTransition.getBundleExternalKey(), subscriptionTransitionModelDao.getBundleExternalKey());
+        Assert.assertEquals(businessSubscriptionTransition.getSubscriptionId(), subscriptionTransitionModelDao.getSubscriptionId());
+        Assert.assertEquals(businessSubscriptionTransition.getRequestedTimestamp(), subscriptionTransitionModelDao.getRequestedTimestamp());
+        Assert.assertEquals(businessSubscriptionTransition.getEventType(), subscriptionTransitionModelDao.getEvent().getEventType().toString());
+        Assert.assertEquals(businessSubscriptionTransition.getCategory(), subscriptionTransitionModelDao.getEvent().getCategory().toString());
+
+        Assert.assertNull(businessSubscriptionTransition.getPrevProductName());
+        Assert.assertNull(businessSubscriptionTransition.getPrevProductType());
+        Assert.assertNull(businessSubscriptionTransition.getPrevProductCategory());
+        Assert.assertNull(businessSubscriptionTransition.getPrevSlug());
+        Assert.assertNull(businessSubscriptionTransition.getPrevPhase());
+        Assert.assertNull(businessSubscriptionTransition.getPrevBillingPeriod());
+        Assert.assertNull(businessSubscriptionTransition.getPrevPrice());
+        Assert.assertNull(businessSubscriptionTransition.getPrevPriceList());
+        Assert.assertNull(businessSubscriptionTransition.getPrevMrr());
+        Assert.assertNull(businessSubscriptionTransition.getPrevCurrency());
+        Assert.assertNull(businessSubscriptionTransition.getPrevBusinessActive());
+        Assert.assertNull(businessSubscriptionTransition.getPrevStartDate());
+        Assert.assertNull(businessSubscriptionTransition.getPrevState());
+
+        Assert.assertEquals(businessSubscriptionTransition.getNextProductName(), subscriptionTransitionModelDao.getNextSubscription().getProductName());
+        Assert.assertEquals(businessSubscriptionTransition.getNextProductType(), subscriptionTransitionModelDao.getNextSubscription().getProductType());
+        Assert.assertEquals(businessSubscriptionTransition.getNextProductCategory(), subscriptionTransitionModelDao.getNextSubscription().getProductCategory());
+        Assert.assertEquals(businessSubscriptionTransition.getNextSlug(), subscriptionTransitionModelDao.getNextSubscription().getSlug());
+        Assert.assertEquals(businessSubscriptionTransition.getNextPhase(), subscriptionTransitionModelDao.getNextSubscription().getPhase());
+        Assert.assertEquals(businessSubscriptionTransition.getNextBillingPeriod(), subscriptionTransitionModelDao.getNextSubscription().getBillingPeriod());
+        Assert.assertEquals(businessSubscriptionTransition.getNextPrice(), subscriptionTransitionModelDao.getNextSubscription().getPrice());
+        Assert.assertEquals(businessSubscriptionTransition.getNextPriceList(), subscriptionTransitionModelDao.getNextSubscription().getPriceList());
+        Assert.assertEquals(businessSubscriptionTransition.getNextMrr(), subscriptionTransitionModelDao.getNextSubscription().getMrr());
+        Assert.assertEquals(businessSubscriptionTransition.getNextCurrency(), subscriptionTransitionModelDao.getNextSubscription().getCurrency());
+        Assert.assertEquals(businessSubscriptionTransition.getNextBusinessActive(), subscriptionTransitionModelDao.getNextSubscription().getBusinessActive());
+        Assert.assertEquals(businessSubscriptionTransition.getNextStartDate(), subscriptionTransitionModelDao.getNextSubscription().getStartDate());
+        Assert.assertEquals(businessSubscriptionTransition.getNextEndDate(), subscriptionTransitionModelDao.getNextSubscription().getEndDate());
+        Assert.assertEquals(businessSubscriptionTransition.getNextState(), subscriptionTransitionModelDao.getNextSubscription().getState());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessTag.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessTag.java
new file mode 100644
index 0000000..e1e50e1
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessTag.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.api;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceTagModelDao;
+
+public class TestBusinessTag extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructorAccount() throws Exception {
+        final BusinessAccountTagModelDao businessAccountTagModelDao = new BusinessAccountTagModelDao(account,
+                                                                                                     tag,
+                                                                                                     tagDefinition,
+                                                                                                     auditLog);
+        final BusinessTag businessTag = BusinessTag.create(businessAccountTagModelDao);
+        verifyBusinessTag(businessTag);
+        Assert.assertEquals(businessTag.getObjectType(), ObjectType.ACCOUNT);
+    }
+
+    @Test(groups = "fast")
+    public void testConstructorInvoice() throws Exception {
+        final BusinessInvoiceTagModelDao businessInvoiceTagModelDao = new BusinessInvoiceTagModelDao(account,
+                                                                                                     tag,
+                                                                                                     tagDefinition,
+                                                                                                     auditLog);
+        final BusinessTag businessTag = BusinessTag.create(businessInvoiceTagModelDao);
+        verifyBusinessTag(businessTag);
+        Assert.assertEquals(businessTag.getObjectType(), ObjectType.INVOICE);
+    }
+
+    @Test(groups = "fast")
+    public void testConstructorPayment() throws Exception {
+        final BusinessInvoicePaymentTagModelDao invoicePaymentTagModelDao = new BusinessInvoicePaymentTagModelDao(account,
+                                                                                                                  tag,
+                                                                                                                  tagDefinition,
+                                                                                                                  auditLog);
+        final BusinessTag businessTag = BusinessTag.create(invoicePaymentTagModelDao);
+        verifyBusinessTag(businessTag);
+        Assert.assertEquals(businessTag.getObjectType(), ObjectType.INVOICE_PAYMENT);
+    }
+
+    private void verifyBusinessTag(final BusinessTag accountTag) {
+        verifyBusinessEntityBase(accountTag);
+        Assert.assertEquals(accountTag.getName(), accountTag.getName());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/user/TestDefaultAnalyticsUserApi.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/user/TestDefaultAnalyticsUserApi.java
index cfc56ce..d708ca0 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/user/TestDefaultAnalyticsUserApi.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/user/TestDefaultAnalyticsUserApi.java
@@ -17,78 +17,28 @@
 package com.ning.billing.osgi.bundles.analytics.api.user;
 
 import java.math.BigDecimal;
-import java.util.UUID;
 
-import org.joda.time.DateTime;
-import org.mockito.Mockito;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import com.ning.billing.analytics.api.TimeSeriesData;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.mock.MockPlan;
 import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
-import com.ning.billing.osgi.bundles.analytics.MockDuration;
-import com.ning.billing.osgi.bundles.analytics.MockPhase;
-import com.ning.billing.osgi.bundles.analytics.MockProduct;
+import com.ning.billing.osgi.bundles.analytics.api.BusinessAccount;
+import com.ning.billing.osgi.bundles.analytics.api.BusinessSnapshot;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountModelDao;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscription;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionEvent;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionTransitionModelDao;
 
 public class TestDefaultAnalyticsUserApi extends AnalyticsTestSuiteWithEmbeddedDB {
 
-    @Test(groups = "mysql")
-    public void testAccountsCreatedOverTime() throws Exception {
-        final BusinessAccountModelDao account = new BusinessAccountModelDao(UUID.randomUUID(), UUID.randomUUID().toString(), UUID.randomUUID().toString(), BigDecimal.ONE, clock.getUTCToday(),
-                                                                            BigDecimal.TEN, "ERROR_NOT_ENOUGH_FUNDS", "CreditCard", "Visa", "FRANCE", "USD", clock.getUTCNow(), clock.getUTCNow());
-        accountSqlDao.createAccount(account, internalCallContext);
-
-        final TimeSeriesData data = analyticsUserApi.getAccountsCreatedOverTime(callContext);
-        Assert.assertEquals(data.getDates().size(), 1);
-        Assert.assertEquals(data.getDates().get(0), clock.getUTCToday());
-        Assert.assertEquals(data.getValues().size(), 1);
-        Assert.assertEquals(data.getValues().get(0), (double) 1);
-    }
-
-    @Test(groups = "mysql")
-    public void testSubscriptionsCreatedOverTime() throws Exception {
-        final String productType = "subscription";
-        final Product product = new MockProduct("platinum", productType, ProductCategory.BASE);
-        final Plan plan = new MockPlan("platinum-monthly", product);
-        final PlanPhase phase = new MockPhase(PhaseType.TRIAL, plan, MockDuration.UNLIMITED(), 25.95);
-        final Catalog catalog = Mockito.mock(Catalog.class);
-        Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(plan);
-        Mockito.when(catalog.findPhase(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(phase);
-        final BusinessSubscriptionTransitionModelDao transition = new BusinessSubscriptionTransitionModelDao(
-                3L,
-                UUID.randomUUID(),
-                UUID.randomUUID().toString(),
-                UUID.randomUUID(),
-                UUID.randomUUID().toString(),
-                UUID.randomUUID(),
-                clock.getUTCNow(),
-                BusinessSubscriptionEvent.subscriptionCreated(plan.getName(), catalog, clock.getUTCNow(), clock.getUTCNow()),
-                null,
-                new BusinessSubscription("DEFAULT", plan.getName(), phase.getName(), Currency.USD, clock.getUTCNow(), Subscription.SubscriptionState.ACTIVE, catalog)
-        );
-        subscriptionTransitionSqlDao.createTransition(transition, internalCallContext);
-
-        final TimeSeriesData notFoundData = analyticsUserApi.getSubscriptionsCreatedOverTime(productType, UUID.randomUUID().toString(), callContext);
-        Assert.assertEquals(notFoundData.getDates().size(), 0);
-        Assert.assertEquals(notFoundData.getValues().size(), 0);
-
-        final TimeSeriesData data = analyticsUserApi.getSubscriptionsCreatedOverTime(productType, phase.getName(), callContext);
-        Assert.assertEquals(data.getDates().size(), 1);
-        Assert.assertEquals(data.getDates().get(0), clock.getUTCToday());
-        Assert.assertEquals(data.getValues().size(), 1);
-        Assert.assertEquals(data.getValues().get(0), (double) 1);
+    @Test(groups = "slow")
+    public void testAccountSnapshot() throws Exception {
+        final BusinessAccountModelDao accountModelDao = new BusinessAccountModelDao(account,
+                                                                                    BigDecimal.ONE,
+                                                                                    invoice,
+                                                                                    payment,
+                                                                                    auditLog);
+        analyticsSqlDao.create(accountModelDao.getTableName(), accountModelDao, callContext);
+
+        final AnalyticsUserApi analyticsUserApi = new AnalyticsUserApi(logService, killbillAPI, killbillDataSource);
+        final BusinessSnapshot businessSnapshot = analyticsUserApi.getBusinessSnapshot(account.getId(), callContext);
+        Assert.assertEquals(businessSnapshot.getBusinessAccount(), new BusinessAccount(accountModelDao));
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountFieldModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountFieldModelDao.java
index fc246ef..348c81f 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountFieldModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountFieldModelDao.java
@@ -25,10 +25,10 @@ public class TestBusinessAccountFieldModelDao extends AnalyticsTestSuiteNoDB {
 
     @Test(groups = "fast")
     public void testConstructor() throws Exception {
-        final BusinessAccountFieldModelDao accountField = new BusinessAccountFieldModelDao(account, customField, auditLog);
-        verifyBusinessModelDaoBase(accountField);
-        //Assert.assertEquals(accountField.getCustomFieldRecordId(), /* TODO */);
-        Assert.assertEquals(accountField.getName(), customField.getFieldName());
-        Assert.assertEquals(accountField.getValue(), customField.getFieldValue());
+        final BusinessAccountFieldModelDao accountFieldModelDao = new BusinessAccountFieldModelDao(account, customField, auditLog);
+        verifyBusinessModelDaoBase(accountFieldModelDao);
+        //Assert.assertEquals(accountFieldModelDao.getCustomFieldRecordId(), /* TODO */);
+        Assert.assertEquals(accountFieldModelDao.getName(), customField.getFieldName());
+        Assert.assertEquals(accountFieldModelDao.getValue(), customField.getFieldValue());
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountModelDao.java
index 4d8333b..8353e81 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountModelDao.java
@@ -27,39 +27,39 @@ public class TestBusinessAccountModelDao extends AnalyticsTestSuiteNoDB {
 
     @Test(groups = "fast")
     public void testConstructorWithNulls() throws Exception {
-        final BusinessAccountModelDao businessAccount = new BusinessAccountModelDao(account, BigDecimal.ONE, null, null, auditLog);
-        verifyAccountFields(businessAccount);
-        Assert.assertEquals(businessAccount.getBalance(), BigDecimal.ONE);
-        Assert.assertNull(businessAccount.getLastInvoiceDate());
-        Assert.assertNull(businessAccount.getLastPaymentDate());
-        Assert.assertNull(businessAccount.getLastPaymentStatus());
+        final BusinessAccountModelDao accountModelDao = new BusinessAccountModelDao(account, BigDecimal.ONE, null, null, auditLog);
+        verifyAccountFields(accountModelDao);
+        Assert.assertEquals(accountModelDao.getBalance(), BigDecimal.ONE);
+        Assert.assertNull(accountModelDao.getLastInvoiceDate());
+        Assert.assertNull(accountModelDao.getLastPaymentDate());
+        Assert.assertNull(accountModelDao.getLastPaymentStatus());
     }
 
     @Test(groups = "fast")
     public void testConstructorWithoutNulls() throws Exception {
-        final BusinessAccountModelDao businessAccount = new BusinessAccountModelDao(account, BigDecimal.ONE, invoice, payment, auditLog);
-        verifyAccountFields(businessAccount);
-        Assert.assertEquals(businessAccount.getBalance(), BigDecimal.ONE);
-        Assert.assertEquals(businessAccount.getLastInvoiceDate(), invoice.getInvoiceDate());
-        Assert.assertEquals(businessAccount.getLastPaymentDate(), payment.getEffectiveDate());
-        Assert.assertEquals(businessAccount.getLastPaymentStatus(), payment.getPaymentStatus().toString());
+        final BusinessAccountModelDao accountModelDao = new BusinessAccountModelDao(account, BigDecimal.ONE, invoice, payment, auditLog);
+        verifyAccountFields(accountModelDao);
+        Assert.assertEquals(accountModelDao.getBalance(), BigDecimal.ONE);
+        Assert.assertEquals(accountModelDao.getLastInvoiceDate(), invoice.getInvoiceDate());
+        Assert.assertEquals(accountModelDao.getLastPaymentDate(), payment.getEffectiveDate());
+        Assert.assertEquals(accountModelDao.getLastPaymentStatus(), payment.getPaymentStatus().toString());
     }
 
-    private void verifyAccountFields(final BusinessAccountModelDao businessAccount) {
-        verifyBusinessModelDaoBase(businessAccount);
-        Assert.assertEquals(businessAccount.getEmail(), account.getEmail());
-        Assert.assertEquals(businessAccount.getFirstNameLength(), account.getFirstNameLength());
-        Assert.assertEquals(businessAccount.getCurrency(), account.getCurrency().toString());
-        Assert.assertEquals(businessAccount.getBillingCycleDayLocal(), account.getBillCycleDayLocal());
-        Assert.assertEquals(businessAccount.getAddress1(), account.getAddress1());
-        Assert.assertEquals(businessAccount.getAddress2(), account.getAddress2());
-        Assert.assertEquals(businessAccount.getCompanyName(), account.getCompanyName());
-        Assert.assertEquals(businessAccount.getCity(), account.getCity());
-        Assert.assertEquals(businessAccount.getStateOrProvince(), account.getStateOrProvince());
-        Assert.assertEquals(businessAccount.getCountry(), account.getCountry());
-        Assert.assertEquals(businessAccount.getPostalCode(), account.getPostalCode());
-        Assert.assertEquals(businessAccount.getPhone(), account.getPhone());
-        Assert.assertEquals(businessAccount.getMigrated(), account.isMigrated());
-        Assert.assertEquals(businessAccount.getNotifiedForInvoices(), account.isNotifiedForInvoices());
+    private void verifyAccountFields(final BusinessAccountModelDao accountModelDao) {
+        verifyBusinessModelDaoBase(accountModelDao);
+        Assert.assertEquals(accountModelDao.getEmail(), account.getEmail());
+        Assert.assertEquals(accountModelDao.getFirstNameLength(), account.getFirstNameLength());
+        Assert.assertEquals(accountModelDao.getCurrency(), account.getCurrency().toString());
+        Assert.assertEquals(accountModelDao.getBillingCycleDayLocal(), account.getBillCycleDayLocal());
+        Assert.assertEquals(accountModelDao.getAddress1(), account.getAddress1());
+        Assert.assertEquals(accountModelDao.getAddress2(), account.getAddress2());
+        Assert.assertEquals(accountModelDao.getCompanyName(), account.getCompanyName());
+        Assert.assertEquals(accountModelDao.getCity(), account.getCity());
+        Assert.assertEquals(accountModelDao.getStateOrProvince(), account.getStateOrProvince());
+        Assert.assertEquals(accountModelDao.getCountry(), account.getCountry());
+        Assert.assertEquals(accountModelDao.getPostalCode(), account.getPostalCode());
+        Assert.assertEquals(accountModelDao.getPhone(), account.getPhone());
+        Assert.assertEquals(accountModelDao.getMigrated(), account.isMigrated());
+        Assert.assertEquals(accountModelDao.getNotifiedForInvoices(), account.isNotifiedForInvoices());
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountTagModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountTagModelDao.java
index b53ee87..cdc1bbc 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountTagModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessAccountTagModelDao.java
@@ -24,10 +24,10 @@ import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
 public class TestBusinessAccountTagModelDao extends AnalyticsTestSuiteNoDB {
 
     @Test(groups = "fast")
-    public void testEquals() throws Exception {
-        final BusinessAccountTagModelDao accountTag = new BusinessAccountTagModelDao(account, tag, tagDefinition, auditLog);
-        verifyBusinessModelDaoBase(accountTag);
-        //Assert.assertEquals(accountTag.getTagRecordId(), /* TODO */);
-        Assert.assertEquals(accountTag.getName(), tagDefinition.getName());
+    public void testConstructor() throws Exception {
+        final BusinessAccountTagModelDao tagModelDao = new BusinessAccountTagModelDao(account, tag, tagDefinition, auditLog);
+        verifyBusinessModelDaoBase(tagModelDao);
+        //Assert.assertEquals(tagModelDao.getTagRecordId(), /* TODO */);
+        Assert.assertEquals(tagModelDao.getName(), tagDefinition.getName());
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoiceItemModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoiceItemModelDao.java
new file mode 100644
index 0000000..3957591
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoiceItemModelDao.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.dao.model;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoiceItemModelDao extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructorWithNulls() throws Exception {
+        final BusinessInvoiceItemModelDao invoiceItemModelDao = new BusinessInvoiceItemModelDao(account,
+                                                                                                invoice,
+                                                                                                invoiceItem,
+                                                                                                null,
+                                                                                                null,
+                                                                                                null,
+                                                                                                auditLog);
+        verifyInvoiceItemFields(invoiceItemModelDao);
+        Assert.assertNull(invoiceItemModelDao.getBundleExternalKey());
+        Assert.assertNull(invoiceItemModelDao.getProductName());
+        Assert.assertNull(invoiceItemModelDao.getProductType());
+        Assert.assertNull(invoiceItemModelDao.getProductCategory());
+        Assert.assertNull(invoiceItemModelDao.getSlug());
+        Assert.assertNull(invoiceItemModelDao.getPhase());
+        Assert.assertNull(invoiceItemModelDao.getBillingPeriod());
+        Assert.assertNull(invoiceItemModelDao.getEndDate());
+    }
+
+    @Test(groups = "fast")
+    public void testConstructorWithoutNulls() throws Exception {
+        final BusinessInvoiceItemModelDao invoiceItemModelDao = new BusinessInvoiceItemModelDao(account,
+                                                                                                invoice,
+                                                                                                invoiceItem,
+                                                                                                bundle,
+                                                                                                plan,
+                                                                                                phase,
+                                                                                                auditLog);
+        verifyInvoiceItemFields(invoiceItemModelDao);
+        Assert.assertEquals(invoiceItemModelDao.getBundleExternalKey(), bundle.getExternalKey());
+        Assert.assertEquals(invoiceItemModelDao.getProductName(), plan.getProduct().getName());
+        Assert.assertEquals(invoiceItemModelDao.getProductType(), plan.getProduct().getCatalogName());
+        Assert.assertEquals(invoiceItemModelDao.getProductCategory(), plan.getProduct().getCategory().toString());
+        Assert.assertEquals(invoiceItemModelDao.getSlug(), phase.getName());
+        Assert.assertEquals(invoiceItemModelDao.getPhase(), phase.getPhaseType().toString());
+        Assert.assertEquals(invoiceItemModelDao.getBillingPeriod(), phase.getBillingPeriod().toString());
+        Assert.assertEquals(invoiceItemModelDao.getEndDate(), invoiceItem.getStartDate().plus(phase.getDuration().toJodaPeriod()));
+    }
+
+    private void verifyInvoiceItemFields(final BusinessInvoiceItemModelDao invoiceItemModelDao) {
+        verifyBusinessModelDaoBase(invoiceItemModelDao);
+        //Assert.assertEquals(invoiceItemModelDao.getInvoiceItemRecordId(), /* TODO */);
+        Assert.assertEquals(invoiceItemModelDao.getItemId(), invoiceItem.getId());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceId(), invoice.getId());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceNumber(), invoice.getInvoiceNumber());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceCreatedDate(), invoice.getCreatedDate());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceDate(), invoice.getInvoiceDate());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceTargetDate(), invoice.getTargetDate());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceCurrency(), invoice.getCurrency().toString());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceBalance(), invoice.getBalance());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceAmountPaid(), invoice.getPaidAmount());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceAmountCharged(), invoice.getChargedAmount());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceOriginalAmountCharged(), invoice.getOriginalChargedAmount());
+        Assert.assertEquals(invoiceItemModelDao.getInvoiceAmountCredited(), invoice.getCreditAdjAmount());
+        Assert.assertEquals(invoiceItemModelDao.getItemType(), invoiceItem.getInvoiceItemType().toString());
+        //Assert.assertEquals(invoiceItemModelDao.getRevenueRecognizable(), /* TODO */);
+        Assert.assertEquals(invoiceItemModelDao.getStartDate(), invoiceItem.getStartDate());
+        Assert.assertEquals(invoiceItemModelDao.getAmount(), invoiceItem.getAmount());
+        Assert.assertEquals(invoiceItemModelDao.getCurrency(), invoiceItem.getCurrency().toString());
+        Assert.assertEquals(invoiceItemModelDao.getLinkedItemId(), invoiceItem.getLinkedItemId());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoiceModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoiceModelDao.java
new file mode 100644
index 0000000..a349d1d
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoiceModelDao.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.dao.model;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoiceModelDao extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final BusinessInvoiceModelDao invoiceModelDao = new BusinessInvoiceModelDao(account, invoice, auditLog);
+        verifyBusinessModelDaoBase(invoiceModelDao);
+        //Assert.assertEquals(invoiceModelDao.getInvoiceRecordId(), /* TODO */);
+        Assert.assertEquals(invoiceModelDao.getInvoiceId(), invoice.getId());
+        Assert.assertEquals(invoiceModelDao.getInvoiceNumber(), invoice.getInvoiceNumber());
+        Assert.assertEquals(invoiceModelDao.getInvoiceDate(), invoice.getInvoiceDate());
+        Assert.assertEquals(invoiceModelDao.getTargetDate(), invoice.getTargetDate());
+        Assert.assertEquals(invoiceModelDao.getCurrency(), invoice.getCurrency().toString());
+        Assert.assertEquals(invoiceModelDao.getBalance(), invoice.getBalance());
+        Assert.assertEquals(invoiceModelDao.getAmountPaid(), invoice.getPaidAmount());
+        Assert.assertEquals(invoiceModelDao.getAmountCharged(), invoice.getChargedAmount());
+        Assert.assertEquals(invoiceModelDao.getOriginalAmountCharged(), invoice.getOriginalChargedAmount());
+        Assert.assertEquals(invoiceModelDao.getAmountCredited(), invoice.getCreditAdjAmount());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoicePaymentModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoicePaymentModelDao.java
new file mode 100644
index 0000000..669be7e
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessInvoicePaymentModelDao.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.dao.model;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoicePaymentModelDao extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final BusinessInvoicePaymentModelDao invoicePaymentModelDao = new BusinessInvoicePaymentModelDao(account,
+                                                                                                         invoice,
+                                                                                                         invoicePayment,
+                                                                                                         payment,
+                                                                                                         paymentMethod,
+                                                                                                         auditLog);
+        verifyBusinessModelDaoBase(invoicePaymentModelDao);
+        //Assert.assertEquals(invoicePaymentModelDao.getInvoicePaymentRecordId(), /* TODO */);
+        Assert.assertEquals(invoicePaymentModelDao.getInvoicePaymentId(), invoicePayment.getId());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceId(), invoice.getId());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceNumber(), invoice.getInvoiceNumber());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceCreatedDate(), invoice.getCreatedDate());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceDate(), invoice.getInvoiceDate());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceTargetDate(), invoice.getInvoiceDate());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceCurrency(), invoice.getCurrency().toString());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceBalance(), invoice.getBalance());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceAmountPaid(), invoice.getPaidAmount());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceAmountCharged(), invoice.getChargedAmount());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceOriginalAmountCharged(), invoice.getOriginalChargedAmount());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoiceAmountCredited(), invoice.getCreditAdjAmount());
+        Assert.assertEquals(invoicePaymentModelDao.getInvoicePaymentType(), invoicePayment.getType().toString());
+        //Assert.assertEquals(invoicePaymentModelDao.getPaymentNumber(), /* TODO */);
+        Assert.assertEquals(invoicePaymentModelDao.getLinkedInvoicePaymentId(), invoicePayment.getLinkedInvoicePaymentId());
+        Assert.assertEquals(invoicePaymentModelDao.getAmount(), payment.getAmount());
+        Assert.assertEquals(invoicePaymentModelDao.getCurrency(), payment.getCurrency().toString());
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessOverdueStatusModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessOverdueStatusModelDao.java
new file mode 100644
index 0000000..bdb4d65
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessOverdueStatusModelDao.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.dao.model;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessOverdueStatusModelDao extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testEquals() throws Exception {
+        final DateTime endDate = new DateTime(2012, 7, 21, 10, 10, 10, DateTimeZone.UTC);
+        final BusinessOverdueStatusModelDao overdueStatusModelDao = new BusinessOverdueStatusModelDao(account,
+                                                                                                      bundle,
+                                                                                                      blockingState,
+                                                                                                      endDate,
+                                                                                                      auditLog);
+        verifyBusinessModelDaoBase(overdueStatusModelDao);
+        //Assert.assertEquals(overdueStatusModelDao.getBlockingStateRecordId(), /* TODO */);
+        Assert.assertEquals(overdueStatusModelDao.getBundleId(), bundle.getId());
+        Assert.assertEquals(overdueStatusModelDao.getBundleExternalKey(), bundle.getExternalKey());
+        Assert.assertEquals(overdueStatusModelDao.getStatus(), blockingState.getStateName());
+        Assert.assertEquals(overdueStatusModelDao.getStartDate(), blockingState.getTimestamp());
+        Assert.assertEquals(overdueStatusModelDao.getEndDate(), endDate);
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscription.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscription.java
index 1323ce5..91dcf8e 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscription.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscription.java
@@ -19,28 +19,14 @@ package com.ning.billing.osgi.bundles.analytics.dao.model;
 import java.math.BigDecimal;
 
 import org.joda.time.DateTime;
-import org.mockito.Mockito;
+import org.joda.time.DateTimeZone;
 import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.mock.MockPlan;
-import com.ning.billing.mock.MockSubscription;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
-import com.ning.billing.osgi.bundles.analytics.MockDuration;
-import com.ning.billing.osgi.bundles.analytics.MockPhase;
-import com.ning.billing.osgi.bundles.analytics.MockProduct;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscription;
-
-import static com.ning.billing.catalog.api.Currency.USD;
 
 public class TestBusinessSubscription extends AnalyticsTestSuiteNoDB {
 
@@ -109,31 +95,6 @@ public class TestBusinessSubscription extends AnalyticsTestSuiteNoDB {
             {BillingPeriod.ANNUAL, 2299.0000, 191.5833},
             {BillingPeriod.ANNUAL, 5499.0000, 458.2500}};
 
-    private Product product;
-    private Plan plan;
-    private PlanPhase phase;
-    private Subscription isubscription;
-    private BusinessSubscription subscription;
-
-    private final Catalog catalog = Mockito.mock(Catalog.class);
-
-    @Override
-    @BeforeMethod(groups = "fast")
-    public void beforeMethod() throws Exception {
-        super.beforeMethod();
-        product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
-        plan = new MockPlan("platinum-monthly", product);
-        phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
-
-        Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any())).thenReturn(plan);
-        Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(plan);
-        Mockito.when(catalog.findPhase(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(phase);
-        Mockito.when(catalogService.getFullCatalog()).thenReturn(catalog);
-
-        isubscription = new MockSubscription(Subscription.SubscriptionState.ACTIVE, plan, phase);
-        subscription = new BusinessSubscription(isubscription, USD, catalog);
-    }
-
     @Test(groups = "fast")
     public void testMrrComputation() throws Exception {
         int i = 0;
@@ -149,25 +110,51 @@ public class TestBusinessSubscription extends AnalyticsTestSuiteNoDB {
     }
 
     @Test(groups = "fast")
-    public void testConstructor() throws Exception {
-        Assert.assertEquals(subscription.getRoundedMrr(), 0.0);
-        Assert.assertEquals(subscription.getSlug(), phase.getName());
-        Assert.assertEquals(subscription.getPhase(), phase.getPhaseType().toString());
-        Assert.assertEquals(subscription.getBillingPeriod(), phase.getBillingPeriod());
-        Assert.assertEquals(subscription.getPrice(), phase.getRecurringPrice().getPrice(null));
-        Assert.assertEquals(subscription.getProductCategory(), product.getCategory());
-        Assert.assertEquals(subscription.getProductName(), product.getName());
-        Assert.assertEquals(subscription.getProductType(), product.getCatalogName());
-        Assert.assertEquals(subscription.getStartDate(), isubscription.getStartDate());
+    public void testConstructorWithNulls() throws Exception {
+        final DateTime startDate = new DateTime(2019, 7, 4, 29, 3, 11, DateTimeZone.UTC);
+        final BusinessSubscription businessSubscription = new BusinessSubscription(null,
+                                                                                   null,
+                                                                                   null,
+                                                                                   Currency.GBP,
+                                                                                   startDate,
+                                                                                   SubscriptionState.ACTIVE);
+        Assert.assertNull(businessSubscription.getProductName());
+        Assert.assertNull(businessSubscription.getProductType());
+        Assert.assertNull(businessSubscription.getProductCategory());
+        Assert.assertNull(businessSubscription.getSlug());
+        Assert.assertNull(businessSubscription.getPhase());
+        Assert.assertNull(businessSubscription.getBillingPeriod());
+        Assert.assertNull(businessSubscription.getPrice());
+        Assert.assertNull(businessSubscription.getPriceList(), priceList.getName());
+        Assert.assertEquals(businessSubscription.getCurrency(), Currency.GBP.toString());
+        Assert.assertEquals(businessSubscription.getState(), SubscriptionState.ACTIVE);
+        //Assert.assertEquals(businessSubscription.getBusinessActive(), /* TODO */);
+        Assert.assertEquals(businessSubscription.getStartDate(), startDate);
+        Assert.assertNull(businessSubscription.getEndDate());
+
     }
 
     @Test(groups = "fast")
-    public void testEquals() throws Exception {
-        Assert.assertSame(subscription, subscription);
-        Assert.assertEquals(subscription, subscription);
-        Assert.assertTrue(subscription.equals(subscription));
-
-        final Subscription otherSubscription = new MockSubscription(Subscription.SubscriptionState.CANCELLED, plan, phase);
-        Assert.assertTrue(!subscription.equals(new BusinessSubscription(otherSubscription, USD, catalog)));
+    public void testConstructorWithoutNulls() throws Exception {
+        final DateTime startDate = new DateTime(2019, 7, 4, 29, 3, 11, DateTimeZone.UTC);
+        final BusinessSubscription businessSubscription = new BusinessSubscription(plan,
+                                                                                   phase,
+                                                                                   priceList,
+                                                                                   Currency.GBP,
+                                                                                   startDate,
+                                                                                   SubscriptionState.ACTIVE);
+        Assert.assertEquals(businessSubscription.getProductName(), plan.getProduct().getName());
+        Assert.assertEquals(businessSubscription.getProductType(), plan.getProduct().getCatalogName());
+        Assert.assertEquals(businessSubscription.getProductCategory(), plan.getProduct().getCategory().toString());
+        Assert.assertEquals(businessSubscription.getSlug(), phase.getName());
+        Assert.assertEquals(businessSubscription.getPhase(), phase.getPhaseType().toString());
+        Assert.assertEquals(businessSubscription.getBillingPeriod(), phase.getBillingPeriod().toString());
+        Assert.assertEquals(businessSubscription.getPrice(), phase.getRecurringPrice());
+        Assert.assertEquals(businessSubscription.getPriceList(), priceList.getName());
+        Assert.assertEquals(businessSubscription.getCurrency(), Currency.GBP.toString());
+        Assert.assertEquals(businessSubscription.getState(), SubscriptionState.ACTIVE);
+        //Assert.assertEquals(businessSubscription.getBusinessActive(), /* TODO */);
+        Assert.assertEquals(businessSubscription.getStartDate(), startDate);
+        Assert.assertNull(businessSubscription.getEndDate());
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionEvent.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionEvent.java
index d727c45..e4de1b0 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionEvent.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionEvent.java
@@ -16,52 +16,14 @@
 
 package com.ning.billing.osgi.bundles.analytics.dao.model;
 
-import org.joda.time.DateTime;
-import org.mockito.Mockito;
 import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
 import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.mock.MockPlan;
-import com.ning.billing.mock.MockSubscription;
 import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
-import com.ning.billing.osgi.bundles.analytics.MockDuration;
-import com.ning.billing.osgi.bundles.analytics.MockPhase;
-import com.ning.billing.osgi.bundles.analytics.MockProduct;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionEvent;
 
 public class TestBusinessSubscriptionEvent extends AnalyticsTestSuiteNoDB {
 
-    private Product product;
-    private Plan plan;
-    private PlanPhase phase;
-    private Subscription subscription;
-
-    private final Catalog catalog = Mockito.mock(Catalog.class);
-
-    @Override
-    @BeforeMethod(groups = "fast")
-    public void beforeMethod() throws Exception {
-        super.beforeMethod();
-        product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
-        plan = new MockPlan("platinum-monthly", product);
-        phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
-
-        Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any())).thenReturn(plan);
-        Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(plan);
-        Mockito.when(catalog.findPhase(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(phase);
-        Mockito.when(catalogService.getFullCatalog()).thenReturn(catalog);
-
-        subscription = new MockSubscription(Subscription.SubscriptionState.ACTIVE, plan, phase);
-    }
-
     @Test(groups = "fast")
     public void testValueOf() throws Exception {
         BusinessSubscriptionEvent event;
@@ -81,45 +43,9 @@ public class TestBusinessSubscriptionEvent extends AnalyticsTestSuiteNoDB {
 
     @Test(groups = "fast")
     public void testFromSubscription() throws Exception {
-        BusinessSubscriptionEvent event;
-
-        final DateTime now = new DateTime();
-
-        event = BusinessSubscriptionEvent.subscriptionCreated(subscription.getCurrentPlan().getName(), catalog, now, now);
+        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.fromTransition(subscriptionTransition);
         Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.ADD);
-        Assert.assertEquals(event.getCategory(), product.getCategory());
+        Assert.assertEquals(event.getCategory(), subscriptionTransition.getNextPlan().getProduct().getCategory());
         Assert.assertEquals(event.toString(), "ADD_BASE");
-
-        event = BusinessSubscriptionEvent.subscriptionCancelled(subscription.getCurrentPlan().getName(), catalog, now, now);
-        Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.CANCEL);
-        Assert.assertEquals(event.getCategory(), product.getCategory());
-        Assert.assertEquals(event.toString(), "CANCEL_BASE");
-
-        event = BusinessSubscriptionEvent.subscriptionChanged(subscription.getCurrentPlan().getName(), catalog, now, now);
-        Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.CHANGE);
-        Assert.assertEquals(event.getCategory(), product.getCategory());
-        Assert.assertEquals(event.toString(), "CHANGE_BASE");
-
-        event = BusinessSubscriptionEvent.subscriptionPhaseChanged(subscription.getCurrentPlan().getName(), subscription.getState(), catalog, now, now);
-        // The subscription is still active, it's a system change
-        Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.SYSTEM_CHANGE);
-        Assert.assertEquals(event.getCategory(), product.getCategory());
-        Assert.assertEquals(event.toString(), "SYSTEM_CHANGE_BASE");
-
-        subscription = new MockSubscription(Subscription.SubscriptionState.CANCELLED, plan, phase);
-        event = BusinessSubscriptionEvent.subscriptionPhaseChanged(subscription.getCurrentPlan().getName(), subscription.getState(), catalog, now, now);
-        // The subscription is cancelled, it's a system cancellation
-        Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.SYSTEM_CANCEL);
-        Assert.assertEquals(event.getCategory(), product.getCategory());
-        Assert.assertEquals(event.toString(), "SYSTEM_CANCEL_BASE");
-    }
-
-    @Test(groups = "fast")
-    public void testEquals() throws Exception {
-        final DateTime now = new DateTime();
-        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionChanged(subscription.getCurrentPlan().getName(), catalog, now, now);
-        Assert.assertSame(event, event);
-        Assert.assertEquals(event, event);
-        Assert.assertTrue(event.equals(event));
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionTransitionModelDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionTransitionModelDao.java
new file mode 100644
index 0000000..3aaf1ab
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/model/TestBusinessSubscriptionTransitionModelDao.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.dao.model;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessSubscriptionTransitionModelDao extends AnalyticsTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testConstructor() throws Exception {
+        final DateTime startDate = new DateTime(2012, 6, 5, 4, 3, 12, DateTimeZone.UTC);
+        final DateTime requestedTimestamp = new DateTime(2012, 7, 21, 10, 10, 10, DateTimeZone.UTC);
+
+        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf("ADD_BASE");
+        final BusinessSubscription previousSubscription = null;
+        final BusinessSubscription nextSubscription = new BusinessSubscription(null, null, null, Currency.GBP, startDate, SubscriptionState.ACTIVE);
+        final BusinessSubscriptionTransitionModelDao subscriptionTransitionModelDao = new BusinessSubscriptionTransitionModelDao(account,
+                                                                                                                                 bundle,
+                                                                                                                                 subscriptionTransition,
+                                                                                                                                 requestedTimestamp,
+                                                                                                                                 event,
+                                                                                                                                 previousSubscription,
+                                                                                                                                 nextSubscription,
+                                                                                                                                 auditLog);
+        verifyBusinessModelDaoBase(subscriptionTransitionModelDao);
+        //Assert.assertEquals(subscriptionTransitionModelDao.getSubscriptionEventRecordId(), /* TODO */);
+        Assert.assertEquals(subscriptionTransitionModelDao.getBundleId(), bundle.getId());
+        Assert.assertEquals(subscriptionTransitionModelDao.getBundleExternalKey(), bundle.getExternalKey());
+        Assert.assertEquals(subscriptionTransitionModelDao.getSubscriptionId(), subscriptionTransition.getSubscriptionId());
+        Assert.assertEquals(subscriptionTransitionModelDao.getRequestedTimestamp(), requestedTimestamp);
+        Assert.assertEquals(subscriptionTransitionModelDao.getEvent(), event);
+        Assert.assertEquals(subscriptionTransitionModelDao.getPreviousSubscription(), previousSubscription);
+        Assert.assertEquals(subscriptionTransitionModelDao.getNextSubscription(), nextSubscription);
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestAnalyticsDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestAnalyticsDao.java
index 9e179c1..82c86a1 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestAnalyticsDao.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestAnalyticsDao.java
@@ -17,253 +17,34 @@
 package com.ning.billing.osgi.bundles.analytics.dao;
 
 import java.math.BigDecimal;
-import java.util.List;
-import java.util.UUID;
 
-import org.joda.time.DateTime;
-import org.mockito.Mockito;
 import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.mock.MockPlan;
 import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
-import com.ning.billing.osgi.bundles.analytics.MockDuration;
-import com.ning.billing.osgi.bundles.analytics.MockPhase;
-import com.ning.billing.osgi.bundles.analytics.MockProduct;
+import com.ning.billing.osgi.bundles.analytics.api.BusinessAccount;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountModelDao;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscription;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionEvent;
-import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessSubscriptionTransitionModelDao;
-import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
 
 public class TestAnalyticsDao extends AnalyticsTestSuiteWithEmbeddedDB {
 
-    private static final Long TOTAL_ORDERING = 1L;
-    private static final UUID BUNDLE_ID = UUID.randomUUID();
-    private static final String EXTERNAL_KEY = "23456";
-    private static final UUID ACCOUNT_ID = UUID.randomUUID();
-    private static final String ACCOUNT_KEY = "pierre-143343-vcc";
-    private static final String CURRENCY = UUID.randomUUID().toString();
-
-    private final Product product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
-    private final Plan plan = new MockPlan("platinum-monthly", product);
-    private final PlanPhase phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
-
-    private BusinessSubscriptionTransitionModelDao transition;
-    private BusinessAccountModelDao account;
-
-    private final Catalog catalog = Mockito.mock(Catalog.class);
-
-    @BeforeClass(groups = "slow")
-    public void beforeClass() throws Exception {
-        super.beforeClass();
-        Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any())).thenReturn(plan);
-        Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(plan);
-        Mockito.when(catalog.findPhase(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(phase);
-        Mockito.when(catalogService.getFullCatalog()).thenReturn(catalog);
-
-        setupBusinessSubscriptionTransition();
-        setupBusinessAccount();
-    }
-
-    private void setupBusinessSubscriptionTransition() {
-        final DateTime requestedTimestamp = clock.getUTCNow();
-        final BusinessSubscription prevSubscription = new BusinessSubscription(null, plan.getName(), phase.getName(), Currency.USD, clock.getUTCNow(), Subscription.SubscriptionState.ACTIVE, catalog);
-        final BusinessSubscription nextSubscription = new BusinessSubscription(null, plan.getName(), phase.getName(), Currency.USD, clock.getUTCNow(), Subscription.SubscriptionState.CANCELLED, catalog);
-        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(plan.getName(), catalog, requestedTimestamp, requestedTimestamp);
-
-        transition = new BusinessSubscriptionTransitionModelDao(TOTAL_ORDERING, BUNDLE_ID, EXTERNAL_KEY, ACCOUNT_ID, ACCOUNT_KEY,
-                                                                UUID.randomUUID(), requestedTimestamp, event, prevSubscription, nextSubscription);
-    }
-
-    private void setupBusinessAccount() {
-        account = new BusinessAccountModelDao(UUID.randomUUID(), ACCOUNT_KEY, UUID.randomUUID().toString(), BigDecimal.ONE, clock.getUTCToday(),
-                                              BigDecimal.TEN, "ERROR_NOT_ENOUGH_FUNDS", "CreditCard", "Visa", "FRANCE", CURRENCY, clock.getUTCNow(), clock.getUTCNow());
-    }
-
-    @Test(groups = "slow")
-    public void testTransitionsWithNullPrevSubscription() {
-        final BusinessSubscriptionTransitionModelDao transitionWithNullPrev = new BusinessSubscriptionTransitionModelDao(
-                transition.getTotalOrdering(),
-                transition.getBundleId(),
-                transition.getExternalKey(),
-                transition.getAccountId(),
-                transition.getAccountKey(),
-                transition.getSubscriptionId(),
-                transition.getRequestedTimestamp(),
-                transition.getEvent(),
-                null,
-                transition.getNextSubscription()
-        );
-        subscriptionTransitionSqlDao.createTransition(transitionWithNullPrev, internalCallContext);
-
-        final List<BusinessSubscriptionTransitionModelDao> transitions = subscriptionTransitionSqlDao.getTransitionsByKey(EXTERNAL_KEY, internalCallContext);
-        Assert.assertEquals(transitions.size(), 1);
-        Assert.assertEquals(transitions.get(0), transitionWithNullPrev);
-    }
-
     @Test(groups = "slow")
-    public void testTransitionsWithNullNextSubscription() {
-        final BusinessSubscriptionTransitionModelDao transitionWithNullNext = new BusinessSubscriptionTransitionModelDao(
-                transition.getTotalOrdering(),
-                transition.getBundleId(),
-                transition.getExternalKey(),
-                transition.getAccountId(),
-                transition.getAccountKey(),
-                transition.getSubscriptionId(),
-                transition.getRequestedTimestamp(),
-                transition.getEvent(),
-                transition.getPreviousSubscription(),
-                null
-        );
-        subscriptionTransitionSqlDao.createTransition(transitionWithNullNext, internalCallContext);
+    public void testDao() throws Exception {
+        final AnalyticsDao analyticsDao = new AnalyticsDao(logService, killbillAPI, killbillDataSource);
+        Assert.assertNull(analyticsDao.getAccountById(account.getId(), callContext));
 
-        final List<BusinessSubscriptionTransitionModelDao> transitions = subscriptionTransitionSqlDao.getTransitionsByKey(EXTERNAL_KEY, internalCallContext);
-        Assert.assertEquals(transitions.size(), 1);
-        Assert.assertEquals(transitions.get(0), transitionWithNullNext);
-    }
-
-    @Test(groups = "slow")
-    public void testTransitionsWithNullFieldsInSubscription() {
-        final BusinessSubscription subscriptionWithNullFields = new BusinessSubscription(null, plan.getName(), phase.getName(), Currency.USD, null, null, catalog);
-        final BusinessSubscriptionTransitionModelDao transitionWithNullFields = new BusinessSubscriptionTransitionModelDao(
-                transition.getTotalOrdering(),
-                transition.getBundleId(),
-                transition.getExternalKey(),
-                transition.getAccountId(),
-                transition.getAccountKey(),
-                transition.getSubscriptionId(),
-                transition.getRequestedTimestamp(),
-                transition.getEvent(),
-                subscriptionWithNullFields,
-                subscriptionWithNullFields
-        );
-        subscriptionTransitionSqlDao.createTransition(transitionWithNullFields, internalCallContext);
-
-        final List<BusinessSubscriptionTransitionModelDao> transitions = subscriptionTransitionSqlDao.getTransitionsByKey(EXTERNAL_KEY, internalCallContext);
-        Assert.assertEquals(transitions.size(), 1);
-        Assert.assertEquals(transitions.get(0), transitionWithNullFields);
-    }
-
-    @Test(groups = "slow")
-    public void testTransitionsWithNullPlanAndPhase() throws Exception {
-        final BusinessSubscription subscriptionWithNullPlanAndPhase = new BusinessSubscription(null, null, null, Currency.USD, null, null, catalog);
-        final BusinessSubscriptionTransitionModelDao transitionWithNullPlanAndPhase = new BusinessSubscriptionTransitionModelDao(
-                transition.getTotalOrdering(),
-                transition.getBundleId(),
-                transition.getExternalKey(),
-                transition.getAccountId(),
-                transition.getAccountKey(),
-                transition.getSubscriptionId(),
-                transition.getRequestedTimestamp(),
-                transition.getEvent(),
-                subscriptionWithNullPlanAndPhase,
-                subscriptionWithNullPlanAndPhase
-        );
-        subscriptionTransitionSqlDao.createTransition(transitionWithNullPlanAndPhase, internalCallContext);
-
-        final List<BusinessSubscriptionTransitionModelDao> transitions = subscriptionTransitionSqlDao.getTransitionsByKey(EXTERNAL_KEY, internalCallContext);
-        Assert.assertEquals(transitions.size(), 1);
-        Assert.assertEquals(transitions.get(0).getExternalKey(), transition.getExternalKey());
-        Assert.assertEquals(transitions.get(0).getRequestedTimestamp(), transition.getRequestedTimestamp());
-        Assert.assertEquals(transitions.get(0).getEvent(), transition.getEvent());
-        Assert.assertNull(transitions.get(0).getPreviousSubscription());
-        Assert.assertNull(transitions.get(0).getNextSubscription());
-    }
-
-    @Test(groups = "slow")
-    public void testTransitionsWithNullPlan() throws Exception {
-        final BusinessSubscription subscriptionWithNullPlan = new BusinessSubscription(null, null, phase.getName(), Currency.USD, null, null, catalog);
-        final BusinessSubscriptionTransitionModelDao transitionWithNullPlan = new BusinessSubscriptionTransitionModelDao(
-                transition.getTotalOrdering(),
-                transition.getBundleId(),
-                transition.getExternalKey(),
-                transition.getAccountId(),
-                transition.getAccountKey(),
-                transition.getSubscriptionId(),
-                transition.getRequestedTimestamp(),
-                transition.getEvent(),
-                subscriptionWithNullPlan,
-                subscriptionWithNullPlan
-        );
-        subscriptionTransitionSqlDao.createTransition(transitionWithNullPlan, internalCallContext);
-
-        final List<BusinessSubscriptionTransitionModelDao> transitions = subscriptionTransitionSqlDao.getTransitionsByKey(EXTERNAL_KEY, internalCallContext);
-        Assert.assertEquals(transitions.size(), 1);
-        // Null Plan but Phase - we don't turn the subscription into a null
-        Assert.assertEquals(transitions.get(0), transitionWithNullPlan);
-    }
-
-    @Test(groups = "slow")
-    public void testTransitionsWithNullPhase() throws Exception {
-        final BusinessSubscription subscriptionWithNullPhase = new BusinessSubscription(null, plan.getName(), null, Currency.USD, null, null, catalog);
-        final BusinessSubscriptionTransitionModelDao transitionWithNullPhase = new BusinessSubscriptionTransitionModelDao(
-                transition.getTotalOrdering(),
-                transition.getBundleId(),
-                transition.getExternalKey(),
-                transition.getAccountId(),
-                transition.getAccountKey(),
-                transition.getSubscriptionId(),
-                transition.getRequestedTimestamp(),
-                transition.getEvent(),
-                subscriptionWithNullPhase,
-                subscriptionWithNullPhase
-        );
-        subscriptionTransitionSqlDao.createTransition(transitionWithNullPhase, internalCallContext);
-
-        final List<BusinessSubscriptionTransitionModelDao> transitions = subscriptionTransitionSqlDao.getTransitionsByKey(EXTERNAL_KEY, internalCallContext);
-        Assert.assertEquals(transitions.size(), 1);
-        Assert.assertEquals(transitions.get(0).getExternalKey(), transition.getExternalKey());
-        Assert.assertEquals(transitions.get(0).getRequestedTimestamp(), transition.getRequestedTimestamp());
-        Assert.assertEquals(transitions.get(0).getEvent(), transition.getEvent());
-
-        // Null Phase but Plan - we don't turn the subscription into a null, however price and mrr are both set to 0 (not null)
-        final BusinessSubscription blankSubscription = new BusinessSubscription(null, plan.getName(), new MockPhase(null, null, null, 0.0).getName(), Currency.USD, null, null, catalog);
-        Assert.assertEquals(transitions.get(0).getPreviousSubscription(), blankSubscription);
-        Assert.assertEquals(transitions.get(0).getNextSubscription(), blankSubscription);
-    }
-
-    @Test(groups = "slow")
-    public void testCreateAndRetrieveTransitions() {
-        subscriptionTransitionSqlDao.createTransition(transition, internalCallContext);
-
-        final List<BusinessSubscriptionTransitionModelDao> transitions = subscriptionTransitionSqlDao.getTransitionsByKey(EXTERNAL_KEY, internalCallContext);
-        Assert.assertEquals(transitions.size(), 1);
-        Assert.assertEquals(transitions.get(0), transition);
-
-        Assert.assertEquals(subscriptionTransitionSqlDao.getTransitionsByKey("Doesn't exist", internalCallContext).size(), 0);
-    }
-
-    @Test(groups = "slow")
-    public void testCreateSaveAndRetrieveAccounts() {
-        // Create and retrieve an account
-        accountSqlDao.createAccount(account, internalCallContext);
-        final BusinessAccountModelDao foundAccount = accountSqlDao.getAccountByKey(ACCOUNT_KEY, internalCallContext);
-        Assert.assertEquals(foundAccount.getCreatedDate().getMillis(), account.getCreatedDate().getMillis());
-        Assert.assertEquals(foundAccount.getUpdatedDate().getMillis(), account.getUpdatedDate().getMillis());
-        Assert.assertTrue(foundAccount.equals(account));
+        final BusinessAccountModelDao accountModelDao = new BusinessAccountModelDao(account,
+                                                                                    BigDecimal.ONE,
+                                                                                    invoice,
+                                                                                    payment,
+                                                                                    auditLog);
 
-        // Try to update the account
-        account.setBalance(BigDecimal.TEN);
-        account.setPaymentMethod("PayPal");
-        account.setCurrency("CAD");
-        accountSqlDao.saveAccount(account, internalCallContext);
-        // Verify the save worked as expected
-        account = accountSqlDao.getAccountByKey(ACCOUNT_KEY, internalCallContext);
-        Assert.assertEquals(Rounder.round(BigDecimal.TEN), account.getRoundedBalance());
-        Assert.assertEquals("PayPal", account.getPaymentMethod());
-        Assert.assertEquals("CAD", account.getCurrency());
+        analyticsSqlDao.create(accountModelDao.getTableName(), accountModelDao, callContext);
+        Assert.assertEquals(analyticsDao.getAccountById(account.getId(), callContext), new BusinessAccount(accountModelDao));
 
-        // ACCOUNT not found
-        Assert.assertNull(accountSqlDao.getAccountByKey("Doesn't exist", internalCallContext));
+        analyticsSqlDao.deleteByAccountRecordId(accountModelDao.getTableName(),
+                                                accountModelDao.getAccountRecordId(),
+                                                accountModelDao.getTenantRecordId(),
+                                                callContext);
+        Assert.assertNull(analyticsDao.getAccountById(account.getId(), callContext));
     }
 }
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAnalyticsSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAnalyticsSqlDao.java
new file mode 100644
index 0000000..f3cda23
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAnalyticsSqlDao.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-2013 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.osgi.bundles.analytics.dao;
+
+import java.math.BigDecimal;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountModelDao;
+
+public class TestBusinessAnalyticsSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+    @Test(groups = "slow")
+    public void testSqlDao() throws Exception {
+        final BusinessAccountModelDao accountModelDao = new BusinessAccountModelDao(account,
+                                                                                    BigDecimal.ONE,
+                                                                                    invoice,
+                                                                                    payment,
+                                                                                    auditLog);
+
+        Assert.assertNull(analyticsSqlDao.getAccountByAccountRecordId(accountModelDao.getAccountRecordId(),
+                                                                      accountModelDao.getTenantRecordId(),
+                                                                      callContext));
+
+        analyticsSqlDao.create(accountModelDao.getTableName(), accountModelDao, callContext);
+        Assert.assertEquals(analyticsSqlDao.getAccountByAccountRecordId(accountModelDao.getAccountRecordId(),
+                                                                        accountModelDao.getTenantRecordId(),
+                                                                        callContext), accountModelDao);
+
+        analyticsSqlDao.deleteByAccountRecordId(accountModelDao.getTableName(),
+                                                accountModelDao.getAccountRecordId(),
+                                                accountModelDao.getTenantRecordId(),
+                                                callContext);
+        Assert.assertNull(analyticsSqlDao.getAccountByAccountRecordId(accountModelDao.getAccountRecordId(),
+                                                                      accountModelDao.getTenantRecordId(),
+                                                                      callContext));
+    }
+}