killbill-memoizeit

analytics: implement custom fields and tags for bundles Signed-off-by:

5/1/2013 3:35:09 PM

Changes

Details

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 8324189..8a11600 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
@@ -18,6 +18,7 @@ package com.ning.billing.osgi.bundles.analytics.api;
 
 import com.ning.billing.ObjectType;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentFieldModelDao;
@@ -45,6 +46,8 @@ public class BusinessField extends BusinessEntityBase {
     public static BusinessField create(final BusinessFieldModelDao businessFieldModelDao) {
         if (businessFieldModelDao instanceof BusinessAccountFieldModelDao) {
             return new BusinessField(ObjectType.ACCOUNT, businessFieldModelDao);
+        } else if (businessFieldModelDao instanceof BusinessBundleFieldModelDao) {
+            return new BusinessField(ObjectType.BUNDLE, businessFieldModelDao);
         } else if (businessFieldModelDao instanceof BusinessInvoiceFieldModelDao) {
             return new BusinessField(ObjectType.INVOICE, businessFieldModelDao);
         } else if (businessFieldModelDao instanceof BusinessInvoicePaymentFieldModelDao) {
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 08d99f6..e65ed76 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
@@ -18,6 +18,7 @@ package com.ning.billing.osgi.bundles.analytics.api;
 
 import com.ning.billing.ObjectType;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessTagModelDao;
@@ -43,6 +44,8 @@ public class BusinessTag extends BusinessEntityBase {
     public static BusinessTag create(final BusinessTagModelDao businessTagModelDao) {
         if (businessTagModelDao instanceof BusinessAccountTagModelDao) {
             return new BusinessTag(ObjectType.ACCOUNT, businessTagModelDao);
+        } else if (businessTagModelDao instanceof BusinessBundleTagModelDao) {
+            return new BusinessTag(ObjectType.BUNDLE, businessTagModelDao);
         } else if (businessTagModelDao instanceof BusinessInvoiceTagModelDao) {
             return new BusinessTag(ObjectType.INVOICE, businessTagModelDao);
         } else if (businessTagModelDao instanceof BusinessInvoicePaymentTagModelDao) {
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 e0cff38..f549805 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
@@ -150,6 +150,7 @@ public class AnalyticsDao extends BusinessAnalyticsDaoBase {
 
         final List<BusinessFieldModelDao> businessFieldModelDaos = new LinkedList<BusinessFieldModelDao>();
         businessFieldModelDaos.addAll(sqlDao.getAccountFieldsByAccountRecordId(accountRecordId, tenantRecordId, context));
+        businessFieldModelDaos.addAll(sqlDao.getBundleFieldsByAccountRecordId(accountRecordId, tenantRecordId, context));
         businessFieldModelDaos.addAll(sqlDao.getInvoiceFieldsByAccountRecordId(accountRecordId, tenantRecordId, context));
         businessFieldModelDaos.addAll(sqlDao.getInvoicePaymentFieldsByAccountRecordId(accountRecordId, tenantRecordId, context));
 
@@ -167,6 +168,7 @@ public class AnalyticsDao extends BusinessAnalyticsDaoBase {
 
         final List<BusinessTagModelDao> businessTagModelDaos = new LinkedList<BusinessTagModelDao>();
         businessTagModelDaos.addAll(sqlDao.getAccountTagsByAccountRecordId(accountRecordId, tenantRecordId, context));
+        businessTagModelDaos.addAll(sqlDao.getBundleTagsByAccountRecordId(accountRecordId, tenantRecordId, context));
         businessTagModelDaos.addAll(sqlDao.getInvoiceTagsByAccountRecordId(accountRecordId, tenantRecordId, context));
         businessTagModelDaos.addAll(sqlDao.getInvoicePaymentTagsByAccountRecordId(accountRecordId, tenantRecordId, context));
 
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.java
index 94725f4..76997fa 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.java
@@ -28,7 +28,9 @@ import com.ning.billing.commons.jdbi.binder.SmartBindBean;
 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.BusinessBundleFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleSummaryModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceAdjustmentModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemAdjustmentModelDao;
@@ -128,6 +130,11 @@ public interface BusinessAnalyticsSqlDao extends Transactional<BusinessAnalytics
                                                                                 final TenantContext tenantContext);
 
     @SqlQuery
+    public List<BusinessBundleFieldModelDao> getBundleFieldsByAccountRecordId(@Bind("accountRecordId") final Long accountRecordId,
+                                                                              @Bind("tenantRecordId") final Long tenantRecordId,
+                                                                              final TenantContext tenantContext);
+
+    @SqlQuery
     public List<BusinessInvoiceFieldModelDao> getInvoiceFieldsByAccountRecordId(@Bind("accountRecordId") final Long accountRecordId,
                                                                                 @Bind("tenantRecordId") final Long tenantRecordId,
                                                                                 final TenantContext tenantContext);
@@ -143,6 +150,11 @@ public interface BusinessAnalyticsSqlDao extends Transactional<BusinessAnalytics
                                                                             final TenantContext tenantContext);
 
     @SqlQuery
+    public List<BusinessBundleTagModelDao> getBundleTagsByAccountRecordId(@Bind("accountRecordId") final Long accountRecordId,
+                                                                          @Bind("tenantRecordId") final Long tenantRecordId,
+                                                                          final TenantContext tenantContext);
+
+    @SqlQuery
     public List<BusinessInvoiceTagModelDao> getInvoiceTagsByAccountRecordId(@Bind("accountRecordId") final Long accountRecordId,
                                                                             @Bind("tenantRecordId") final Long tenantRecordId,
                                                                             final TenantContext tenantContext);
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessDBIProvider.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessDBIProvider.java
index 7c8cf5d..80fb9ea 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessDBIProvider.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessDBIProvider.java
@@ -28,7 +28,9 @@ import com.ning.billing.commons.jdbi.mapper.LowerToCamelBeanMapperFactory;
 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.BusinessBundleFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleSummaryModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceAdjustmentModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemAdjustmentModelDao;
@@ -71,6 +73,8 @@ public class BusinessDBIProvider {
         dbi.registerMapper(new LowerToCamelBeanMapperFactory(BusinessOverdueStatusModelDao.class));
         dbi.registerMapper(new LowerToCamelBeanMapperFactory(BusinessSubscriptionTransitionModelDao.class));
         dbi.registerMapper(new LowerToCamelBeanMapperFactory(BusinessBundleSummaryModelDao.class));
+        dbi.registerMapper(new LowerToCamelBeanMapperFactory(BusinessBundleFieldModelDao.class));
+        dbi.registerMapper(new LowerToCamelBeanMapperFactory(BusinessBundleTagModelDao.class));
 
         dbi.setStatementLocator(new AnalyticsStatementLocator());
 
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessBundleFieldModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessBundleFieldModelDao.java
new file mode 100644
index 0000000..25ff33b
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessBundleFieldModelDao.java
@@ -0,0 +1,95 @@
+/*
+ * 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 java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.customfield.CustomField;
+
+public class BusinessBundleFieldModelDao extends BusinessFieldModelDao {
+
+    private UUID bundleId;
+
+    public BusinessBundleFieldModelDao() { /* When reading from the database */ }
+
+    public BusinessBundleFieldModelDao(final Account account,
+                                       final Long accountRecordId,
+                                       final CustomField customField,
+                                       final Long customFieldRecordId,
+                                       @Nullable final AuditLog creationAuditLog,
+                                       final Long tenantRecordId,
+                                       @Nullable final ReportGroup reportGroup) {
+        super(account,
+              accountRecordId,
+              customField,
+              customFieldRecordId,
+              creationAuditLog,
+              tenantRecordId,
+              reportGroup);
+        this.bundleId = customField.getObjectId();
+    }
+
+    @Override
+    public String getTableName() {
+        return BUNDLE_FIELDS_TABLE_NAME;
+    }
+
+    public UUID getBundleId() {
+        return bundleId;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessBundleFieldModelDao");
+        sb.append("{bundleId=").append(bundleId);
+        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 BusinessBundleFieldModelDao that = (BusinessBundleFieldModelDao) o;
+
+        if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessBundleTagModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessBundleTagModelDao.java
new file mode 100644
index 0000000..9f96b9a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessBundleTagModelDao.java
@@ -0,0 +1,98 @@
+/*
+ * 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 java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDefinition;
+
+public class BusinessBundleTagModelDao extends BusinessTagModelDao {
+
+    private UUID bundleId;
+
+    public BusinessBundleTagModelDao() { /* When reading from the database */ }
+
+    public BusinessBundleTagModelDao(final Account account,
+                                     final Long accountRecordId,
+                                     final Tag tag,
+                                     final Long tagRecordId,
+                                     final TagDefinition tagDefinition,
+                                     @Nullable final AuditLog creationAuditLog,
+                                     final Long tenantRecordId,
+                                     @Nullable final ReportGroup reportGroup) {
+        super(account,
+              accountRecordId,
+              tag,
+              tagRecordId,
+              tagDefinition,
+              creationAuditLog,
+              tenantRecordId,
+              reportGroup);
+        this.bundleId = tag.getObjectId();
+    }
+
+    @Override
+    public String getTableName() {
+        return BUNDLE_TAGS_TABLE_NAME;
+    }
+
+    public UUID getBundleId() {
+        return bundleId;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("BusinessBundleTagModelDao");
+        sb.append("{bundleId=").append(bundleId);
+        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 BusinessBundleTagModelDao that = (BusinessBundleTagModelDao) o;
+
+        if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessFieldModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessFieldModelDao.java
index 9e71e90..582040e 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessFieldModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessFieldModelDao.java
@@ -30,10 +30,11 @@ import com.ning.billing.util.customfield.CustomField;
 public abstract class BusinessFieldModelDao extends BusinessModelDaoBase {
 
     protected static final String ACCOUNT_FIELDS_TABLE_NAME = "bac_fields";
+    protected static final String BUNDLE_FIELDS_TABLE_NAME = "bbu_fields";
     protected static final String INVOICE_FIELDS_TABLE_NAME = "bin_fields";
     protected static final String INVOICE_PAYMENT_FIELDS_TABLE_NAME = "bip_fields";
 
-    public static final String[] ALL_FIELDS_TABLE_NAMES = new String[]{ACCOUNT_FIELDS_TABLE_NAME, INVOICE_FIELDS_TABLE_NAME, INVOICE_PAYMENT_FIELDS_TABLE_NAME};
+    public static final String[] ALL_FIELDS_TABLE_NAMES = new String[]{ACCOUNT_FIELDS_TABLE_NAME, BUNDLE_FIELDS_TABLE_NAME, INVOICE_FIELDS_TABLE_NAME, INVOICE_PAYMENT_FIELDS_TABLE_NAME};
 
     private Long customFieldRecordId;
     private String name;
@@ -54,6 +55,14 @@ public abstract class BusinessFieldModelDao extends BusinessModelDaoBase {
                                                     creationAuditLog,
                                                     tenantRecordId,
                                                     reportGroup);
+        } else if (ObjectType.BUNDLE.equals(customField.getObjectType())) {
+            return new BusinessBundleFieldModelDao(account,
+                                                   accountRecordId,
+                                                   customField,
+                                                   customFieldRecordId,
+                                                   creationAuditLog,
+                                                   tenantRecordId,
+                                                   reportGroup);
         } else if (ObjectType.INVOICE_PAYMENT.equals(customField.getObjectType())) {
             return new BusinessInvoiceFieldModelDao(account,
                                                     accountRecordId,
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessTagModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessTagModelDao.java
index 8a4868d..600fb30 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessTagModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessTagModelDao.java
@@ -31,10 +31,11 @@ import com.ning.billing.util.tag.TagDefinition;
 public abstract class BusinessTagModelDao extends BusinessModelDaoBase {
 
     protected static final String ACCOUNT_TAGS_TABLE_NAME = "bac_tags";
+    protected static final String BUNDLE_TAGS_TABLE_NAME = "bbu_tags";
     protected static final String INVOICE_PAYMENT_TAGS_TABLE_NAME = "bip_tags";
     protected static final String INVOICE_TAGS_TABLE_NAME = "bin_tags";
 
-    public static final String[] ALL_TAGS_TABLE_NAMES = new String[]{ACCOUNT_TAGS_TABLE_NAME, INVOICE_PAYMENT_TAGS_TABLE_NAME, INVOICE_TAGS_TABLE_NAME};
+    public static final String[] ALL_TAGS_TABLE_NAMES = new String[]{ACCOUNT_TAGS_TABLE_NAME, BUNDLE_TAGS_TABLE_NAME, INVOICE_PAYMENT_TAGS_TABLE_NAME, INVOICE_TAGS_TABLE_NAME};
 
     private Long tagRecordId;
     private String name;
@@ -56,6 +57,15 @@ public abstract class BusinessTagModelDao extends BusinessModelDaoBase {
                                                   creationAuditLog,
                                                   tenantRecordId,
                                                   reportGroup);
+        } else if (ObjectType.BUNDLE.equals(tag.getObjectType())) {
+            return new BusinessBundleTagModelDao(account,
+                                                 accountRecordId,
+                                                 tag,
+                                                 tagRecordId,
+                                                 tagDefinition,
+                                                 creationAuditLog,
+                                                 tenantRecordId,
+                                                 reportGroup);
         } else if (ObjectType.INVOICE_PAYMENT.equals(tag.getObjectType())) {
             return new BusinessInvoicePaymentTagModelDao(account,
                                                          accountRecordId,
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.sql.stg
index 5207470..92c2d40 100644
--- a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.sql.stg
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAnalyticsSqlDao.sql.stg
@@ -1014,6 +1014,38 @@ insert into bac_tags (
 );
 >>
 
+createBbuTags() ::= <<
+insert into bbu_tags (
+  tag_record_id
+, bundle_id
+, name
+, created_date
+, created_by
+, created_reason_code
+, created_comments
+, account_id
+, account_name
+, account_external_key
+, account_record_id
+, tenant_record_id
+, report_group
+) values (
+  :tagRecordId
+, :bundleId
+, :name
+, :createdDate
+, :createdBy
+, :createdReasonCode
+, :createdComments
+, :accountId
+, :accountName
+, :accountExternalKey
+, :accountRecordId
+, :tenantRecordId
+, :reportGroup
+);
+>>
+
 createBinTags() ::= <<
 insert into bin_tags (
   tag_record_id
@@ -1110,6 +1142,40 @@ insert into bac_fields (
 );
 >>
 
+createBbuFields() ::= <<
+insert into bbu_fields (
+  custom_field_record_id
+, bundle_id
+, name
+, value
+, created_date
+, created_by
+, created_reason_code
+, created_comments
+, account_id
+, account_name
+, account_external_key
+, account_record_id
+, tenant_record_id
+, report_group
+) values (
+  :customFieldRecordId
+, :bundleId
+, :name
+, :value
+, :createdDate
+, :createdBy
+, :createdReasonCode
+, :createdComments
+, :accountId
+, :accountName
+, :accountExternalKey
+, :accountRecordId
+, :tenantRecordId
+, :reportGroup
+);
+>>
+
 createBinFields() ::= <<
 insert into bin_fields (
   custom_field_record_id
@@ -1260,6 +1326,11 @@ getAccountFieldsByAccountRecordId() ::= <<
 ;
 >>
 
+getBundleFieldsByAccountRecordId() ::= <<
+<SELECT_STAR_FROM_TABLE("bbu_fields")>
+;
+>>
+
 getInvoiceFieldsByAccountRecordId() ::= <<
 <SELECT_STAR_FROM_TABLE("bin_fields")>
 ;
@@ -1275,6 +1346,11 @@ getAccountTagsByAccountRecordId() ::= <<
 ;
 >>
 
+getBundleTagsByAccountRecordId() ::= <<
+<SELECT_STAR_FROM_TABLE("bbu_tags")>
+;
+>>
+
 getInvoiceTagsByAccountRecordId() ::= <<
 <SELECT_STAR_FROM_TABLE("bin_tags")>
 ;
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 80273fa..456f17a 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
@@ -616,6 +616,28 @@ create index bac_tags_account_id on bac_tags(account_id);
 create index bac_tags_account_record_id on bac_tags(account_record_id);
 create index bac_tags_tenant_account_record_id on bac_tags(tenant_record_id, account_record_id);
 
+drop table if exists bbu_tags;
+create table bbu_tags (
+  record_id int(11) unsigned not null auto_increment
+, tag_record_id int(11) unsigned default null
+, bundle_id char(36) default null
+, name varchar(50) default null
+, created_date datetime default null
+, created_by varchar(50) default null
+, created_reason_code varchar(255) default null
+, created_comments varchar(255) default null
+, account_id char(36) default null
+, account_name varchar(100) default null
+, account_external_key varchar(50) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, report_group enum('default', 'test', 'partner') not null
+, primary key(record_id)
+);
+create index bbu_tags_account_id on bbu_tags(account_id);
+create index bbu_tags_account_record_id on bbu_tags(account_record_id);
+create index bbu_tags_tenant_account_record_id on bbu_tags(tenant_record_id, account_record_id);
+
 drop table if exists bin_tags;
 create table bin_tags (
   record_id int(11) unsigned not null auto_increment
@@ -682,6 +704,29 @@ create index bac_fields_account_id on bac_fields(account_id);
 create index bac_fields_account_record_id on bac_fields(account_record_id);
 create index bac_fields_tenant_account_record_id on bac_fields(tenant_record_id, account_record_id);
 
+drop table if exists bbu_fields;
+create table bbu_fields (
+  record_id int(11) unsigned not null auto_increment
+, custom_field_record_id int(11) unsigned default null
+, bundle_id char(36) default null
+, name varchar(50) default null
+, value varchar(255) default null
+, created_date datetime default null
+, created_by varchar(50) default null
+, created_reason_code varchar(255) default null
+, created_comments varchar(255) default null
+, account_id char(36) default null
+, account_name varchar(100) default null
+, account_external_key varchar(50) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, report_group enum('default', 'test', 'partner') not null
+, primary key(record_id)
+);
+create index bbu_fields_account_id on bbu_fields(account_id);
+create index bbu_fields_account_record_id on bbu_fields(account_record_id);
+create index bbu_fields_tenant_account_record_id on bbu_fields(tenant_record_id, account_record_id);
+
 drop table if exists bin_fields;
 create table bin_fields (
   record_id int(11) unsigned not null auto_increment
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
index faeb548..0479a43 100644
--- 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
@@ -22,6 +22,7 @@ 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.BusinessBundleFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentFieldModelDao;
 
@@ -42,6 +43,20 @@ public class TestBusinessField extends AnalyticsTestSuiteNoDB {
     }
 
     @Test(groups = "fast")
+    public void testConstructorBundle() throws Exception {
+        final BusinessBundleFieldModelDao businessBundleFieldModelDao = new BusinessBundleFieldModelDao(account,
+                                                                                                        accountRecordId,
+                                                                                                        customField,
+                                                                                                        fieldRecordId,
+                                                                                                        auditLog,
+                                                                                                        tenantRecordId,
+                                                                                                        reportGroup);
+        final BusinessField businessField = BusinessField.create(businessBundleFieldModelDao);
+        verifyBusinessField(businessField);
+        Assert.assertEquals(businessField.getObjectType(), ObjectType.BUNDLE);
+    }
+
+    @Test(groups = "fast")
     public void testConstructorInvoice() throws Exception {
         final BusinessInvoiceFieldModelDao businessInvoiceFieldModelDao = new BusinessInvoiceFieldModelDao(account,
                                                                                                            accountRecordId,
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
index 5a629c3..3518043 100644
--- 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
@@ -22,6 +22,7 @@ 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.BusinessBundleTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoicePaymentTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceTagModelDao;
 
@@ -43,6 +44,21 @@ public class TestBusinessTag extends AnalyticsTestSuiteNoDB {
     }
 
     @Test(groups = "fast")
+    public void testConstructorBundle() throws Exception {
+        final BusinessBundleTagModelDao businessBundleTagModelDao = new BusinessBundleTagModelDao(account,
+                                                                                                  accountRecordId,
+                                                                                                  tag,
+                                                                                                  tagRecordId,
+                                                                                                  tagDefinition,
+                                                                                                  auditLog,
+                                                                                                  tenantRecordId,
+                                                                                                  reportGroup);
+        final BusinessTag businessTag = BusinessTag.create(businessBundleTagModelDao);
+        verifyBusinessTag(businessTag);
+        Assert.assertEquals(businessTag.getObjectType(), ObjectType.BUNDLE);
+    }
+
+    @Test(groups = "fast")
     public void testConstructorInvoice() throws Exception {
         final BusinessInvoiceTagModelDao businessInvoiceTagModelDao = new BusinessInvoiceTagModelDao(account,
                                                                                                      accountRecordId,
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
index 5d2e8e3..ae9e9e7 100644
--- 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
@@ -31,7 +31,9 @@ import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
 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.BusinessBundleFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleSummaryModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessBundleTagModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceFieldModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao;
@@ -105,6 +107,28 @@ public class TestBusinessAnalyticsSqlDao extends AnalyticsTestSuiteWithEmbeddedD
     }
 
     @Test(groups = "slow")
+    public void testSqlDaoForBundleField() throws Exception {
+        final BusinessFieldModelDao businessFieldModelDao = new BusinessBundleFieldModelDao(account,
+                                                                                            accountRecordId,
+                                                                                            customField,
+                                                                                            fieldRecordId,
+                                                                                            auditLog,
+                                                                                            tenantRecordId,
+                                                                                            reportGroup);
+        // Check the record doesn't exist yet
+        Assert.assertEquals(analyticsSqlDao.getBundleFieldsByAccountRecordId(accountRecordId, tenantRecordId, callContext).size(), 0);
+
+        // Create and check we can retrieve it
+        analyticsSqlDao.create(businessFieldModelDao.getTableName(), businessFieldModelDao, callContext);
+        Assert.assertEquals(analyticsSqlDao.getBundleFieldsByAccountRecordId(accountRecordId, tenantRecordId, callContext).size(), 1);
+        Assert.assertEquals(analyticsSqlDao.getBundleFieldsByAccountRecordId(accountRecordId, tenantRecordId, callContext).get(0), businessFieldModelDao);
+
+        // Delete and verify it doesn't exist anymore
+        analyticsSqlDao.deleteByAccountRecordId(businessFieldModelDao.getTableName(), accountRecordId, tenantRecordId, callContext);
+        Assert.assertEquals(analyticsSqlDao.getBundleFieldsByAccountRecordId(accountRecordId, tenantRecordId, callContext).size(), 0);
+    }
+
+    @Test(groups = "slow")
     public void testSqlDaoForInvoiceField() throws Exception {
         final BusinessFieldModelDao businessFieldModelDao = new BusinessInvoiceFieldModelDao(account,
                                                                                              accountRecordId,
@@ -377,6 +401,29 @@ public class TestBusinessAnalyticsSqlDao extends AnalyticsTestSuiteWithEmbeddedD
     }
 
     @Test(groups = "slow")
+    public void testSqlDaoForBundleTag() throws Exception {
+        final BusinessTagModelDao businessTagModelDao = new BusinessBundleTagModelDao(account,
+                                                                                      accountRecordId,
+                                                                                      tag,
+                                                                                      tagRecordId,
+                                                                                      tagDefinition,
+                                                                                      auditLog,
+                                                                                      tenantRecordId,
+                                                                                      reportGroup);
+        // Check the record doesn't exist yet
+        Assert.assertEquals(analyticsSqlDao.getBundleTagsByAccountRecordId(accountRecordId, tenantRecordId, callContext).size(), 0);
+
+        // Create and check we can retrieve it
+        analyticsSqlDao.create(businessTagModelDao.getTableName(), businessTagModelDao, callContext);
+        Assert.assertEquals(analyticsSqlDao.getBundleTagsByAccountRecordId(accountRecordId, tenantRecordId, callContext).size(), 1);
+        Assert.assertEquals(analyticsSqlDao.getBundleTagsByAccountRecordId(accountRecordId, tenantRecordId, callContext).get(0), businessTagModelDao);
+
+        // Delete and verify it doesn't exist anymore
+        analyticsSqlDao.deleteByAccountRecordId(businessTagModelDao.getTableName(), accountRecordId, tenantRecordId, callContext);
+        Assert.assertEquals(analyticsSqlDao.getBundleTagsByAccountRecordId(accountRecordId, tenantRecordId, callContext).size(), 0);
+    }
+
+    @Test(groups = "slow")
     public void testSqlDaoForInvoiceTag() throws Exception {
         final BusinessTagModelDao businessTagModelDao = new BusinessInvoiceTagModelDao(account,
                                                                                        accountRecordId,