killbill-aplcache
Changes
osgi-bundles/bundles/analytics/pom.xml 242(+242 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsActivator.java 46(+46 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsListener.java 290(+290 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultAnalyticsService.java 66(+66 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessAccount.java 180(+180 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessField.java 114(+114 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessInvoice.java 296(+296 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessInvoicePayment.java 278(+278 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessOverdueStatus.java 123(+123 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSnapshot.java 153(+153 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSubscriptionTransition.java 497(+497 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessTag.java 102(+102 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultTimeSeriesData.java 89(+89 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/sanity/DefaultAnalyticsSanityApi.java 82(+82 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/user/DefaultAnalyticsUserApi.java 395(+395 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessAccountDao.java 154(+154 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoiceDao.java 221(+221 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoicePaymentDao.java 203(+203 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessOverdueStatusDao.java 120(+120 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessSubscriptionTransitionDao.java 261(+261 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessTagDao.java 154(+154 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsDao.java 52(+52 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanityDao.java 43(+43 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.java 62(+62 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountBinder.java 78(+78 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldMapper.java 38(+38 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.java 54(+54 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountMapper.java 52(+52 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.java 63(+63 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagMapper.java 37(+37 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.java 53(+53 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceBinder.java 91(+91 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldMapper.java 34(+34 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.java 53(+53 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemBinder.java 94(+94 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemMapper.java 60(+60 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.java 64(+64 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceMapper.java 55(+55 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentBinder.java 97(+97 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldMapper.java 34(+34 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.java 53(+53 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentMapper.java 69(+69 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.java 56(+56 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagMapper.java 34(+34 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.java 52(+52 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.java 64(+64 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagMapper.java 34(+34 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.java 52(+52 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusBinder.java 63(+63 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusMapper.java 43(+43 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.java 52(+52 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSqlProvider.java 39(+39 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionBinder.java 138(+138 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldMapper.java 39(+39 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.java 55(+55 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionMapper.java 95(+95 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.java 64(+64 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagMapper.java 38(+38 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.java 54(+54 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsDao.java 110(+110 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsSanityDao.java 81(+81 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTuple.java 76(+76 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTupleMapper.java 32(+32 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountFieldModelDao.java 87(+87 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountModelDao.java 257(+257 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountTagModelDao.java 82(+82 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessFieldModelDao.java 41(+41 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceFieldModelDao.java 76(+76 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceItemModelDao.java 257(+257 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceModelDao.java 204(+204 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentFieldModelDao.java 76(+76 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentModelDao.java 272(+272 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentTagModelDao.java 71(+71 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceTagModelDao.java 71(+71 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessOverdueStatusModelDao.java 127(+127 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscription.java 384(+384 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionEvent.java 174(+174 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionFieldModelDao.java 99(+99 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionModelDao.java 200(+200 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionTagModelDao.java 93(+93 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessTagModelDao.java 32(+32 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/PaymentMethodUtils.java 60(+60 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/setup/AnalyticsModule.java 106(+106 -0)
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/utils/Rounder.java 36(+36 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.sql.stg 301(+301 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.sql.stg 42(+42 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.sql.stg 123(+123 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.sql.stg 39(+39 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.sql.stg 39(+39 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.sql.stg 141(+141 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.sql.stg 39(+39 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.sql.stg 122(+122 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.sql.stg 37(+37 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.sql.stg 138(+138 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.sql.stg 37(+37 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.sql.stg 50(+50 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.sql.stg 46(+46 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg 229(+229 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.sql.stg 43(+43 -0)
osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/ddl.sql 259(+259 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java 139(+139 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteWithEmbeddedDB.java 153(+153 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestAnalyticsService.java 231(+231 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/user/TestDefaultAnalyticsUserApi.java 94(+94 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestAnalyticsDao.java 269(+269 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountFieldSqlDao.java 90(+90 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountTagSqlDao.java 88(+88 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceFieldSqlDao.java 86(+86 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceItemSqlDao.java 117(+117 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentFieldSqlDao.java 86(+86 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentSqlDao.java 118(+118 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentTagSqlDao.java 84(+84 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceSqlDao.java 107(+107 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceTagSqlDao.java 84(+84 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessOverdueStatusSqlDao.java 75(+75 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionFieldSqlDao.java 92(+92 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionTagSqlDao.java 90(+90 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModule.java 68(+68 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleNoDB.java 74(+74 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleWithEmbeddedDB.java 39(+39 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockBusinessSubscriptionTransitionSqlDao.java 127(+127 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockDuration.java 50(+50 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockPhase.java 124(+124 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockProduct.java 74(+74 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccount.java 67(+67 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountField.java 52(+52 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountTag.java 44(+44 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoice.java 70(+70 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceField.java 48(+48 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceItem.java 80(+80 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePayment.java 86(+86 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentField.java 48(+48 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentTag.java 43(+43 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceTag.java 42(+42 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessOverdueStatus.java 57(+57 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscription.java 172(+172 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionEvent.java 124(+124 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransition.java 161(+161 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionField.java 56(+56 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionTag.java 52(+52 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessInvoiceRecorder.java 64(+64 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessSubscriptionTransitionRecorder.java 87(+87 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessTagRecorder.java 78(+78 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestPaymentMethodUtils.java 56(+56 -0)
osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/utils/TestRounder.java 40(+40 -0)
osgi-bundles/defaultbundles/pom.xml 4(+4 -0)
Details
osgi-bundles/bundles/analytics/pom.xml 242(+242 -0)
diff --git a/osgi-bundles/bundles/analytics/pom.xml b/osgi-bundles/bundles/analytics/pom.xml
new file mode 100644
index 0000000..6b2da9c
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/pom.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-osgi-bundles</artifactId>
+ <version>0.1.62-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>killbill-osgi-bundles-analytics</artifactId>
+ <name>Killbill billing platform: OSGI Analytics bundle</name>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-osgi-bundles-lib-killbill</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>stringtemplate</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jdbi</groupId>
+ <artifactId>jdbi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-account</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-entitlement</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-entitlement</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-invoice</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-payment</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.jayway.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj-db-files</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>jar</goal>
+ <goal>test-jar</goal>
+ </goals>
+ <configuration>
+ <archive>
+ <!-- use the manifest file created by the bundle plugin -->
+ <!--<useDefaultManifestFile>true</useDefaultManifestFile>-->
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ <!-- bundle plugin already generated the maven descriptor -->
+ <addMavenDescriptor>false</addMavenDescriptor>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Activator>com.ning.billing.osgi.bundles.analytics.AnalyticsActivator</Bundle-Activator>
+ <Export-Package/>
+ <Private-Package>com.ning.billing.osgi.bundles.analytics.*</Private-Package>
+ <!-- Optional resolution because exported by the Felix system bundle -->
+ <Import-Package>*;resolution:=optional</Import-Package>
+ </instructions>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>assemble-killbill-osgi-bundles-analytics</id>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <createSourcesJar>true</createSourcesJar>
+ <shadedArtifactAttached>false</shadedArtifactAttached>
+ <shadedClassifierName>jar-with-dependencies</shadedClassifierName>
+ <filters>
+ <filter>
+ <artifact>${project.groupId}:${project.artifactId}</artifact>
+ </filter>
+ </filters>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsActivator.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsActivator.java
new file mode 100644
index 0000000..1510ba8
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsActivator.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import org.osgi.framework.BundleContext;
+import org.skife.config.SimplePropertyConfigSource;
+
+import com.ning.billing.osgi.bundles.analytics.setup.AnalyticsModule;
+import com.ning.killbill.osgi.libs.killbill.KillbillActivatorBase;
+import com.ning.killbill.osgi.libs.killbill.OSGIKillbillEventDispatcher.OSGIKillbillEventHandler;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+public class AnalyticsActivator extends KillbillActivatorBase {
+
+ private OSGIKillbillEventHandler analyticsListener;
+
+ @Override
+ public void start(final BundleContext context) throws Exception {
+ super.start(context);
+
+ final SimplePropertyConfigSource configSource = new SimplePropertyConfigSource(System.getProperties());
+ final Injector injector = Guice.createInjector(new AnalyticsModule(configSource));
+ analyticsListener = injector.getInstance(AnalyticsListener.class);
+ }
+
+ @Override
+ public OSGIKillbillEventHandler getOSGIKillbillEventHandler() {
+ return analyticsListener;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsListener.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsListener.java
new file mode 100644
index 0000000..a62c243
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/AnalyticsListener.java
@@ -0,0 +1,290 @@
+/*
+ * 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;
+
+import java.util.concurrent.Callable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.beatrix.bus.api.ExtBusEvent;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.events.AccountChangeInternalEvent;
+import com.ning.billing.util.events.AccountCreationInternalEvent;
+import com.ning.billing.util.events.BusInternalEvent;
+import com.ning.billing.util.events.ControlTagCreationInternalEvent;
+import com.ning.billing.util.events.ControlTagDefinitionCreationInternalEvent;
+import com.ning.billing.util.events.ControlTagDefinitionDeletionInternalEvent;
+import com.ning.billing.util.events.ControlTagDeletionInternalEvent;
+import com.ning.billing.util.events.EffectiveSubscriptionInternalEvent;
+import com.ning.billing.util.events.InvoiceAdjustmentInternalEvent;
+import com.ning.billing.util.events.InvoiceCreationInternalEvent;
+import com.ning.billing.util.events.NullInvoiceInternalEvent;
+import com.ning.billing.util.events.OverdueChangeInternalEvent;
+import com.ning.billing.util.events.PaymentErrorInternalEvent;
+import com.ning.billing.util.events.PaymentInfoInternalEvent;
+import com.ning.billing.util.events.RepairEntitlementInternalEvent;
+import com.ning.billing.util.events.RequestedSubscriptionInternalEvent;
+import com.ning.billing.util.events.UserTagCreationInternalEvent;
+import com.ning.billing.util.events.UserTagDefinitionCreationInternalEvent;
+import com.ning.billing.util.events.UserTagDefinitionDeletionInternalEvent;
+import com.ning.billing.util.events.UserTagDeletionInternalEvent;
+import com.ning.billing.util.globallocker.GlobalLock;
+import com.ning.billing.util.globallocker.GlobalLocker;
+import com.ning.billing.util.globallocker.GlobalLocker.LockerType;
+import com.ning.killbill.osgi.libs.killbill.OSGIKillbillEventDispatcher.OSGIKillbillEventHandler;
+
+import com.google.inject.Inject;
+
+public class AnalyticsListener implements OSGIKillbillEventHandler {
+
+ private static final Logger log = LoggerFactory.getLogger(AnalyticsListener.class);
+ private static final int NB_LOCK_TRY = 5;
+
+ private final BusinessSubscriptionTransitionDao bstDao;
+ private final BusinessAccountDao bacDao;
+ private final BusinessInvoiceDao invoiceDao;
+ private final BusinessOverdueStatusDao bosDao;
+ private final BusinessInvoicePaymentDao bipDao;
+ private final BusinessTagDao tagDao;
+ private final GlobalLocker locker;
+ private final InternalCallContextFactory internalCallContextFactory;
+
+ @Inject
+ public AnalyticsListener(final BusinessSubscriptionTransitionDao bstDao,
+ final BusinessAccountDao bacDao,
+ final BusinessInvoiceDao invoiceDao,
+ final BusinessOverdueStatusDao bosDao,
+ final BusinessInvoicePaymentDao bipDao,
+ final BusinessTagDao tagDao,
+ final GlobalLocker locker,
+ final InternalCallContextFactory internalCallContextFactory) {
+ this.bstDao = bstDao;
+ this.bacDao = bacDao;
+ this.invoiceDao = invoiceDao;
+ this.bosDao = bosDao;
+ this.bipDao = bipDao;
+ this.tagDao = tagDao;
+ this.locker = locker;
+ this.internalCallContextFactory = internalCallContextFactory;
+ }
+
+ @Override
+ public void handleKillbillEvent(final ExtBusEvent killbillEvent) {
+ // TODO
+ }
+
+ private void handleEffectiveSubscriptionTransitionChange(final EffectiveSubscriptionInternalEvent eventEffective) {
+ updateWithAccountLock(eventEffective.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ // The event is used as a trigger to rebuild all transitions for this bundle
+ bstDao.rebuildTransitionsForBundle(eventEffective.getBundleId(), createCallContext(eventEffective));
+ return null;
+ }
+ });
+ }
+
+ private void handleRequestedSubscriptionTransitionChange(final RequestedSubscriptionInternalEvent eventRequested) {
+ updateWithAccountLock(eventRequested.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ // The event is used as a trigger to rebuild all transitions for this bundle
+ bstDao.rebuildTransitionsForBundle(eventRequested.getBundleId(), createCallContext(eventRequested));
+ return null;
+ }
+ });
+ }
+
+ private void handleRepairEntitlement(final RepairEntitlementInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ // In case of repair, just rebuild all transitions
+ bstDao.rebuildTransitionsForBundle(event.getBundleId(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleAccountCreation(final AccountCreationInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ bacDao.accountUpdated(event.getId(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleAccountChange(final AccountChangeInternalEvent event) {
+ if (!event.hasChanges()) {
+ return;
+ }
+
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ bacDao.accountUpdated(event.getAccountId(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleInvoiceCreation(final InvoiceCreationInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ // The event is used as a trigger to rebuild all invoices and invoice items for this account
+ invoiceDao.rebuildInvoicesForAccount(event.getAccountId(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleNullInvoice(final NullInvoiceInternalEvent event) {
+ // Ignored for now
+ }
+
+ private void handleInvoiceAdjustment(final InvoiceAdjustmentInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ // The event is used as a trigger to rebuild all invoices and invoice items for this account
+ invoiceDao.rebuildInvoicesForAccount(event.getAccountId(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handlePaymentInfo(final PaymentInfoInternalEvent paymentInfo) {
+ updateWithAccountLock(paymentInfo.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ bipDao.invoicePaymentPosted(paymentInfo.getAccountId(),
+ paymentInfo.getPaymentId(),
+ paymentInfo.getStatus().toString(),
+ createCallContext(paymentInfo));
+ return null;
+ }
+ });
+ }
+
+ private void handlePaymentError(final PaymentErrorInternalEvent paymentError) {
+ updateWithAccountLock(paymentError.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ bipDao.invoicePaymentPosted(paymentError.getAccountId(),
+ paymentError.getPaymentId(),
+ paymentError.getMessage(),
+ createCallContext(paymentError));
+ return null;
+ }
+ });
+ }
+
+ private void handleOverdueChange(final OverdueChangeInternalEvent changeEvent) {
+ updateWithAccountLock(changeEvent.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ bosDao.overdueStatusChanged(changeEvent.getOverdueObjectType(), changeEvent.getOverdueObjectId(), createCallContext(changeEvent));
+ return null;
+ }
+ });
+ }
+
+ private void handleControlTagCreation(final ControlTagCreationInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ tagDao.tagAdded(event.getObjectType(), event.getObjectId(), event.getTagDefinition().getName(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleControlTagDeletion(final ControlTagDeletionInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ tagDao.tagRemoved(event.getObjectType(), event.getObjectId(), event.getTagDefinition().getName(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleUserTagCreation(final UserTagCreationInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ tagDao.tagAdded(event.getObjectType(), event.getObjectId(), event.getTagDefinition().getName(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleUserTagDeletion(final UserTagDeletionInternalEvent event) {
+ updateWithAccountLock(event.getAccountRecordId(), new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ tagDao.tagRemoved(event.getObjectType(), event.getObjectId(), event.getTagDefinition().getName(), createCallContext(event));
+ return null;
+ }
+ });
+ }
+
+ private void handleControlTagDefinitionCreation(final ControlTagDefinitionCreationInternalEvent event) {
+ // Ignored for now
+ }
+
+ private void handleControlTagDefinitionDeletion(final ControlTagDefinitionDeletionInternalEvent event) {
+ // Ignored for now
+ }
+
+ private void handleUserTagDefinitionCreation(final UserTagDefinitionCreationInternalEvent event) {
+ // Ignored for now
+ }
+
+ private void handleUserTagDefinitionDeletion(final UserTagDefinitionDeletionInternalEvent event) {
+ // Ignored for now
+ }
+
+ private InternalCallContext createCallContext(final BusInternalEvent event) {
+ return internalCallContextFactory.createInternalCallContext(event.getTenantRecordId(), event.getAccountRecordId(),
+ "AnalyticsService", CallOrigin.INTERNAL, UserType.SYSTEM, event.getUserToken());
+ }
+
+ private <T> T updateWithAccountLock(final Long accountRecordId, final Callable<T> task) {
+ GlobalLock lock = null;
+ try {
+ final String lockKey = accountRecordId == null ? "0" : accountRecordId.toString();
+ lock = locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_ANALYTICS, lockKey, NB_LOCK_TRY);
+ return task.call();
+ } catch (Exception e) {
+ log.warn("Exception while refreshing analytics tables", e);
+ } finally {
+ if (lock != null) {
+ lock.release();
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultAnalyticsService.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultAnalyticsService.java
new file mode 100644
index 0000000..0e0b043
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultAnalyticsService.java
@@ -0,0 +1,66 @@
+/*
+ * 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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.analytics.api.AnalyticsService;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsListener;
+import com.ning.billing.util.svcsapi.bus.InternalBus;
+
+import com.google.inject.Inject;
+
+public class DefaultAnalyticsService implements AnalyticsService {
+
+ private static final Logger log = LoggerFactory.getLogger(DefaultAnalyticsService.class);
+
+ private static final String ANALYTICS_SERVICE = "analytics-service";
+
+ private final AnalyticsListener listener;
+ private final InternalBus eventBus;
+
+ @Inject
+ public DefaultAnalyticsService(final AnalyticsListener listener, final InternalBus eventBus) {
+ this.listener = listener;
+ this.eventBus = eventBus;
+ }
+
+ @Override
+ public String getName() {
+ return ANALYTICS_SERVICE;
+ }
+
+ @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.REGISTER_EVENTS)
+ public void registerForNotifications() {
+ try {
+ eventBus.register(listener);
+ } catch (InternalBus.EventBusException e) {
+ log.error("Unable to register to the EventBus!", e);
+ }
+ }
+
+ @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.UNREGISTER_EVENTS)
+ public void unregisterForNotifications() {
+ try {
+ eventBus.unregister(listener);
+ } catch (InternalBus.EventBusException e) {
+ throw new RuntimeException("Unable to unregister to the EventBus!", e);
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessAccount.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessAccount.java
new file mode 100644
index 0000000..be0e938
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessAccount.java
@@ -0,0 +1,180 @@
+/*
+ * 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.LocalDate;
+
+import com.ning.billing.analytics.api.BusinessAccount;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultBusinessAccount extends EntityBase implements BusinessAccount {
+
+ private final String externalKey;
+ private final String name;
+ private final String currency;
+ private final BigDecimal balance;
+ private final LocalDate lastInvoiceDate;
+ private final BigDecimal totalInvoiceBalance;
+ private final String lastPaymentStatus;
+ private final String defaultPaymentMethodType;
+ private final String defaultCreditCardType;
+ private final String defaultBillingAddressCountry;
+
+ public DefaultBusinessAccount(final BusinessAccountModelDao businessAccountModelDao) {
+ this.externalKey = businessAccountModelDao.getKey();
+ this.name = businessAccountModelDao.getName();
+ this.currency = businessAccountModelDao.getCurrency();
+ this.balance = businessAccountModelDao.getBalance();
+ this.lastInvoiceDate = businessAccountModelDao.getLastInvoiceDate();
+ this.totalInvoiceBalance = businessAccountModelDao.getTotalInvoiceBalance();
+ this.lastPaymentStatus = businessAccountModelDao.getLastPaymentStatus();
+ this.defaultPaymentMethodType = businessAccountModelDao.getPaymentMethod();
+ this.defaultCreditCardType = businessAccountModelDao.getCreditCardType();
+ this.defaultBillingAddressCountry = businessAccountModelDao.getBillingAddressCountry();
+ }
+
+ @Override
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getCurrency() {
+ return currency;
+ }
+
+ @Override
+ public BigDecimal getBalance() {
+ return balance;
+ }
+
+ @Override
+ public LocalDate getLastInvoiceDate() {
+ return lastInvoiceDate;
+ }
+
+ @Override
+ public BigDecimal getTotalInvoiceBalance() {
+ return totalInvoiceBalance;
+ }
+
+ @Override
+ public String getLastPaymentStatus() {
+ return lastPaymentStatus;
+ }
+
+ @Override
+ public String getDefaultPaymentMethodType() {
+ return defaultPaymentMethodType;
+ }
+
+ @Override
+ public String getDefaultCreditCardType() {
+ return defaultCreditCardType;
+ }
+
+ @Override
+ public String getDefaultBillingAddressCountry() {
+ return defaultBillingAddressCountry;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessAccount");
+ sb.append("{externalKey='").append(externalKey).append('\'');
+ sb.append(", name='").append(name).append('\'');
+ sb.append(", currency='").append(currency).append('\'');
+ sb.append(", balance=").append(balance);
+ sb.append(", lastInvoiceDate=").append(lastInvoiceDate);
+ sb.append(", totalInvoiceBalance=").append(totalInvoiceBalance);
+ sb.append(", lastPaymentStatus='").append(lastPaymentStatus).append('\'');
+ sb.append(", defaultPaymentMethodType='").append(defaultPaymentMethodType).append('\'');
+ sb.append(", defaultCreditCardType='").append(defaultCreditCardType).append('\'');
+ sb.append(", defaultBillingAddressCountry='").append(defaultBillingAddressCountry).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 DefaultBusinessAccount that = (DefaultBusinessAccount) o;
+
+ 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 (defaultBillingAddressCountry != null ? !defaultBillingAddressCountry.equals(that.defaultBillingAddressCountry) : that.defaultBillingAddressCountry != null) {
+ return false;
+ }
+ if (defaultCreditCardType != null ? !defaultCreditCardType.equals(that.defaultCreditCardType) : that.defaultCreditCardType != null) {
+ return false;
+ }
+ if (defaultPaymentMethodType != null ? !defaultPaymentMethodType.equals(that.defaultPaymentMethodType) : that.defaultPaymentMethodType != null) {
+ return false;
+ }
+ if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (lastInvoiceDate != null ? !lastInvoiceDate.equals(that.lastInvoiceDate) : that.lastInvoiceDate != null) {
+ return false;
+ }
+ if (lastPaymentStatus != null ? !lastPaymentStatus.equals(that.lastPaymentStatus) : that.lastPaymentStatus != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (totalInvoiceBalance != null ? !totalInvoiceBalance.equals(that.totalInvoiceBalance) : that.totalInvoiceBalance != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = externalKey != null ? externalKey.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
+ result = 31 * result + (balance != null ? balance.hashCode() : 0);
+ result = 31 * result + (lastInvoiceDate != null ? lastInvoiceDate.hashCode() : 0);
+ result = 31 * result + (totalInvoiceBalance != null ? totalInvoiceBalance.hashCode() : 0);
+ result = 31 * result + (lastPaymentStatus != null ? lastPaymentStatus.hashCode() : 0);
+ result = 31 * result + (defaultPaymentMethodType != null ? defaultPaymentMethodType.hashCode() : 0);
+ result = 31 * result + (defaultCreditCardType != null ? defaultCreditCardType.hashCode() : 0);
+ result = 31 * result + (defaultBillingAddressCountry != null ? defaultBillingAddressCountry.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessField.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessField.java
new file mode 100644
index 0000000..d74d409
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessField.java
@@ -0,0 +1,114 @@
+/*
+ * 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 com.ning.billing.ObjectType;
+import com.ning.billing.analytics.api.BusinessField;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentFieldModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionFieldModelDao;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultBusinessField extends EntityBase implements BusinessField {
+
+ private final ObjectType objectType;
+ private final String name;
+ private final String value;
+
+ DefaultBusinessField(final ObjectType objectType, final BusinessFieldModelDao businessFieldModelDao) {
+ super(businessFieldModelDao.getId());
+ this.objectType = objectType;
+ this.name = businessFieldModelDao.getName();
+ this.value = businessFieldModelDao.getValue();
+ }
+
+ public DefaultBusinessField(final BusinessAccountFieldModelDao businessAccountFieldModelDao) {
+ this(ObjectType.ACCOUNT, businessAccountFieldModelDao);
+ }
+
+ public DefaultBusinessField(final BusinessInvoiceFieldModelDao businessInvoiceFieldModelDao) {
+ this(ObjectType.INVOICE, businessInvoiceFieldModelDao);
+ }
+
+ public DefaultBusinessField(final BusinessInvoicePaymentFieldModelDao businessInvoicePaymentFieldModelDao) {
+ this(ObjectType.PAYMENT, businessInvoicePaymentFieldModelDao);
+ }
+
+ public DefaultBusinessField(final BusinessSubscriptionTransitionFieldModelDao businessSubscriptionTransitionFieldModelDao) {
+ this(ObjectType.BUNDLE, businessSubscriptionTransitionFieldModelDao);
+ }
+
+ @Override
+ public ObjectType getObjectType() {
+ return objectType;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessField");
+ sb.append("{objectType=").append(objectType);
+ sb.append(", name='").append(name).append('\'');
+ sb.append(", value='").append(value).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 DefaultBusinessField that = (DefaultBusinessField) o;
+
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (objectType != that.objectType) {
+ return false;
+ }
+ if (value != null ? !value.equals(that.value) : that.value != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = objectType != null ? objectType.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (value != null ? value.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessInvoice.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessInvoice.java
new file mode 100644
index 0000000..0c32410
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessInvoice.java
@@ -0,0 +1,296 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.LocalDate;
+
+import com.ning.billing.analytics.api.BusinessInvoice;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultBusinessInvoice extends EntityBase implements BusinessInvoice {
+
+ private final UUID invoiceId;
+ private final Integer invoiceNumber;
+ private final UUID accountId;
+ private final String accountKey;
+ private final LocalDate invoiceDate;
+ private final LocalDate targetDate;
+ private final Currency currency;
+ private final BigDecimal balance;
+ private final BigDecimal amountPaid;
+ private final BigDecimal amountCharged;
+ private final BigDecimal amountCredited;
+ private final List<BusinessInvoiceItem> invoiceItems;
+
+ public DefaultBusinessInvoice(final BusinessInvoiceModelDao businessInvoiceModelDao,
+ final Collection<BusinessInvoiceItemModelDao> businessInvoiceItemModelDaos) {
+ super(businessInvoiceModelDao.getInvoiceId(), businessInvoiceModelDao.getCreatedDate(), businessInvoiceModelDao.getUpdatedDate());
+ this.accountId = businessInvoiceModelDao.getAccountId();
+ this.accountKey = businessInvoiceModelDao.getAccountKey();
+ this.amountCharged = businessInvoiceModelDao.getAmountCharged();
+ this.amountCredited = businessInvoiceModelDao.getAmountCredited();
+ this.amountPaid = businessInvoiceModelDao.getAmountPaid();
+ this.balance = businessInvoiceModelDao.getBalance();
+ this.currency = businessInvoiceModelDao.getCurrency();
+ this.invoiceDate = businessInvoiceModelDao.getInvoiceDate();
+ this.invoiceId = businessInvoiceModelDao.getInvoiceId();
+ this.invoiceNumber = businessInvoiceModelDao.getInvoiceNumber();
+ this.targetDate = businessInvoiceModelDao.getTargetDate();
+ this.invoiceItems = toInvoiceItems(businessInvoiceItemModelDaos);
+ }
+
+ private List<BusinessInvoiceItem> toInvoiceItems(final Collection<BusinessInvoiceItemModelDao> businessInvoiceItemModelDaos) {
+ final List<BusinessInvoiceItem> businessInvoiceItems = new ArrayList<BusinessInvoiceItem>();
+ for (final BusinessInvoiceItemModelDao businessInvoiceItemModelDao : businessInvoiceItemModelDaos) {
+ businessInvoiceItems.add(new BusinessInvoiceItem() {
+ @Override
+ public UUID getItemId() {
+ return businessInvoiceItemModelDao.getItemId();
+ }
+
+ @Override
+ public UUID getInvoiceId() {
+ return businessInvoiceItemModelDao.getInvoiceId();
+ }
+
+ @Override
+ public String getItemType() {
+ return businessInvoiceItemModelDao.getItemType();
+ }
+
+ @Override
+ public String getExternalKey() {
+ return businessInvoiceItemModelDao.getExternalKey();
+ }
+
+ @Override
+ public String getProductName() {
+ return businessInvoiceItemModelDao.getProductName();
+ }
+
+ @Override
+ public String getProductType() {
+ return businessInvoiceItemModelDao.getProductType();
+ }
+
+ @Override
+ public String getProductCategory() {
+ return businessInvoiceItemModelDao.getProductCategory();
+ }
+
+ @Override
+ public String getSlug() {
+ return businessInvoiceItemModelDao.getSlug();
+ }
+
+ @Override
+ public String getPhase() {
+ return businessInvoiceItemModelDao.getPhase();
+ }
+
+ @Override
+ public String getBillingPeriod() {
+ return businessInvoiceItemModelDao.getBillingPeriod();
+ }
+
+ @Override
+ public LocalDate getStartDate() {
+ return businessInvoiceItemModelDao.getStartDate();
+ }
+
+ @Override
+ public LocalDate getEndDate() {
+ return businessInvoiceItemModelDao.getEndDate();
+ }
+
+ @Override
+ public BigDecimal getAmount() {
+ return businessInvoiceItemModelDao.getAmount();
+ }
+
+ @Override
+ public Currency getCurrency() {
+ return businessInvoiceItemModelDao.getCurrency();
+ }
+
+ @Override
+ public UUID getLinkedItemId() {
+ return businessInvoiceItemModelDao.getLinkedItemId();
+ }
+ });
+ }
+
+ return businessInvoiceItems;
+ }
+
+ @Override
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ @Override
+ public Integer getInvoiceNumber() {
+ return invoiceNumber;
+ }
+
+ @Override
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ @Override
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ @Override
+ public LocalDate getInvoiceDate() {
+ return invoiceDate;
+ }
+
+ @Override
+ public LocalDate getTargetDate() {
+ return targetDate;
+ }
+
+ @Override
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ @Override
+ public BigDecimal getBalance() {
+ return balance;
+ }
+
+ @Override
+ public BigDecimal getAmountPaid() {
+ return amountPaid;
+ }
+
+ @Override
+ public BigDecimal getAmountCharged() {
+ return amountCharged;
+ }
+
+ @Override
+ public BigDecimal getAmountCredited() {
+ return amountCredited;
+ }
+
+ @Override
+ public List<BusinessInvoiceItem> getInvoiceItems() {
+ return invoiceItems;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessInvoice");
+ sb.append("{invoiceId=").append(invoiceId);
+ sb.append(", invoiceNumber=").append(invoiceNumber);
+ sb.append(", accountId=").append(accountId);
+ sb.append(", accountKey='").append(accountKey).append('\'');
+ sb.append(", invoiceDate=").append(invoiceDate);
+ sb.append(", targetDate=").append(targetDate);
+ sb.append(", currency=").append(currency);
+ sb.append(", balance=").append(balance);
+ sb.append(", amountPaid=").append(amountPaid);
+ sb.append(", amountCharged=").append(amountCharged);
+ sb.append(", amountCredited=").append(amountCredited);
+ sb.append(", invoiceItemsSize=").append(invoiceItems.size());
+ 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 DefaultBusinessInvoice that = (DefaultBusinessInvoice) o;
+
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ 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 != that.currency) {
+ 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.size() != that.invoiceItems.size() : that.invoiceItems != null) {
+ return false;
+ }
+ if (invoiceNumber != null ? !invoiceNumber.equals(that.invoiceNumber) : that.invoiceNumber != null) {
+ return false;
+ }
+ if (targetDate != null ? !targetDate.equals(that.targetDate) : that.targetDate != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = invoiceId != null ? invoiceId.hashCode() : 0;
+ result = 31 * result + (invoiceNumber != null ? invoiceNumber.hashCode() : 0);
+ result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+ result = 31 * result + (accountKey != null ? accountKey.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 + (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/DefaultBusinessInvoicePayment.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessInvoicePayment.java
new file mode 100644
index 0000000..ed76e89
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessInvoicePayment.java
@@ -0,0 +1,278 @@
+/*
+ * 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 java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.analytics.api.BusinessInvoicePayment;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultBusinessInvoicePayment extends EntityBase implements BusinessInvoicePayment {
+
+ private final UUID paymentId;
+ private final String extFirstPaymentRefId;
+ private final String extSecondPaymentRefId;
+ private final String accountKey;
+ private final UUID invoiceId;
+ private final DateTime effectiveDate;
+ private final BigDecimal amount;
+ private final Currency currency;
+ private final String paymentError;
+ private final String processingStatus;
+ private final BigDecimal requestedAmount;
+ private final String pluginName;
+ private final String paymentType;
+ private final String paymentMethod;
+ private final String cardType;
+ private final String cardCountry;
+ private final String invoicePaymentType;
+ private final UUID linkedInvoicePaymentId;
+
+ public DefaultBusinessInvoicePayment(final BusinessInvoicePaymentModelDao businessInvoicePaymentModelDao) {
+ this.paymentId = businessInvoicePaymentModelDao.getPaymentId();
+ this.extFirstPaymentRefId = businessInvoicePaymentModelDao.getExtFirstPaymentRefId();
+ this.extSecondPaymentRefId = businessInvoicePaymentModelDao.getExtSecondPaymentRefId();
+ this.accountKey = businessInvoicePaymentModelDao.getAccountKey();
+ this.invoiceId = businessInvoicePaymentModelDao.getInvoiceId();
+ this.effectiveDate = businessInvoicePaymentModelDao.getEffectiveDate();
+ this.amount = businessInvoicePaymentModelDao.getAmount();
+ this.currency = businessInvoicePaymentModelDao.getCurrency();
+ this.paymentError = businessInvoicePaymentModelDao.getPaymentError();
+ this.processingStatus = businessInvoicePaymentModelDao.getProcessingStatus();
+ this.requestedAmount = businessInvoicePaymentModelDao.getRequestedAmount();
+ this.pluginName = businessInvoicePaymentModelDao.getPluginName();
+ this.paymentType = businessInvoicePaymentModelDao.getPaymentType();
+ this.paymentMethod = businessInvoicePaymentModelDao.getPaymentMethod();
+ this.cardType = businessInvoicePaymentModelDao.getCardType();
+ this.cardCountry = businessInvoicePaymentModelDao.getCardCountry();
+ this.invoicePaymentType = businessInvoicePaymentModelDao.getInvoicePaymentType();
+ this.linkedInvoicePaymentId = businessInvoicePaymentModelDao.getLinkedInvoicePaymentId();
+ }
+
+ @Override
+ public UUID getPaymentId() {
+ return paymentId;
+ }
+
+ @Override
+ public String getExtFirstPaymentRefId() {
+ return extFirstPaymentRefId;
+ }
+
+ @Override
+ public String getExtSecondPaymentRefId() {
+ return extSecondPaymentRefId;
+ }
+
+ @Override
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ @Override
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ @Override
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
+ }
+
+ @Override
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ @Override
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ @Override
+ public String getPaymentError() {
+ return paymentError;
+ }
+
+ @Override
+ public String getProcessingStatus() {
+ return processingStatus;
+ }
+
+ @Override
+ public BigDecimal getRequestedAmount() {
+ return requestedAmount;
+ }
+
+ @Override
+ public String getPluginName() {
+ return pluginName;
+ }
+
+ @Override
+ public String getPaymentType() {
+ return paymentType;
+ }
+
+ @Override
+ public String getPaymentMethod() {
+ return paymentMethod;
+ }
+
+ @Override
+ public String getCardType() {
+ return cardType;
+ }
+
+ @Override
+ public String getCardCountry() {
+ return cardCountry;
+ }
+
+ @Override
+ public String getInvoicePaymentType() {
+ return invoicePaymentType;
+ }
+
+ @Override
+ public UUID getLinkedInvoicePaymentId() {
+ return linkedInvoicePaymentId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessInvoicePayment");
+ sb.append("{paymentId=").append(paymentId);
+ sb.append(", extFirstPaymentRefId='").append(extFirstPaymentRefId).append('\'');
+ sb.append(", extSecondPaymentRefId='").append(extSecondPaymentRefId).append('\'');
+ sb.append(", accountKey='").append(accountKey).append('\'');
+ sb.append(", invoiceId=").append(invoiceId);
+ sb.append(", effectiveDate=").append(effectiveDate);
+ sb.append(", amount=").append(amount);
+ sb.append(", currency=").append(currency);
+ sb.append(", paymentError='").append(paymentError).append('\'');
+ sb.append(", processingStatus='").append(processingStatus).append('\'');
+ sb.append(", requestedAmount=").append(requestedAmount);
+ sb.append(", pluginName='").append(pluginName).append('\'');
+ sb.append(", paymentType='").append(paymentType).append('\'');
+ sb.append(", paymentMethod='").append(paymentMethod).append('\'');
+ sb.append(", cardType='").append(cardType).append('\'');
+ sb.append(", cardCountry='").append(cardCountry).append('\'');
+ sb.append(", invoicePaymentType='").append(invoicePaymentType).append('\'');
+ sb.append(", linkedInvoicePaymentId=").append(linkedInvoicePaymentId);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultBusinessInvoicePayment that = (DefaultBusinessInvoicePayment) o;
+
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+ return false;
+ }
+ if (cardCountry != null ? !cardCountry.equals(that.cardCountry) : that.cardCountry != null) {
+ return false;
+ }
+ if (cardType != null ? !cardType.equals(that.cardType) : that.cardType != null) {
+ return false;
+ }
+ if (currency != that.currency) {
+ return false;
+ }
+ if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
+ return false;
+ }
+ if (extFirstPaymentRefId != null ? !extFirstPaymentRefId.equals(that.extFirstPaymentRefId) : that.extFirstPaymentRefId != null) {
+ return false;
+ }
+ if (extSecondPaymentRefId != null ? !extSecondPaymentRefId.equals(that.extSecondPaymentRefId) : that.extSecondPaymentRefId != null) {
+ return false;
+ }
+ if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+ return false;
+ }
+ if (invoicePaymentType != null ? !invoicePaymentType.equals(that.invoicePaymentType) : that.invoicePaymentType != null) {
+ return false;
+ }
+ if (linkedInvoicePaymentId != null ? !linkedInvoicePaymentId.equals(that.linkedInvoicePaymentId) : that.linkedInvoicePaymentId != null) {
+ return false;
+ }
+ if (paymentError != null ? !paymentError.equals(that.paymentError) : that.paymentError != null) {
+ return false;
+ }
+ if (paymentId != null ? !paymentId.equals(that.paymentId) : that.paymentId != null) {
+ return false;
+ }
+ if (paymentMethod != null ? !paymentMethod.equals(that.paymentMethod) : that.paymentMethod != null) {
+ return false;
+ }
+ if (paymentType != null ? !paymentType.equals(that.paymentType) : that.paymentType != null) {
+ return false;
+ }
+ if (pluginName != null ? !pluginName.equals(that.pluginName) : that.pluginName != null) {
+ return false;
+ }
+ if (processingStatus != null ? !processingStatus.equals(that.processingStatus) : that.processingStatus != null) {
+ return false;
+ }
+ if (requestedAmount != null ? !requestedAmount.equals(that.requestedAmount) : that.requestedAmount != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = paymentId != null ? paymentId.hashCode() : 0;
+ result = 31 * result + (extFirstPaymentRefId != null ? extFirstPaymentRefId.hashCode() : 0);
+ result = 31 * result + (extSecondPaymentRefId != null ? extSecondPaymentRefId.hashCode() : 0);
+ result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
+ result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
+ result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
+ result = 31 * result + (paymentError != null ? paymentError.hashCode() : 0);
+ result = 31 * result + (processingStatus != null ? processingStatus.hashCode() : 0);
+ result = 31 * result + (requestedAmount != null ? requestedAmount.hashCode() : 0);
+ result = 31 * result + (pluginName != null ? pluginName.hashCode() : 0);
+ result = 31 * result + (paymentType != null ? paymentType.hashCode() : 0);
+ result = 31 * result + (paymentMethod != null ? paymentMethod.hashCode() : 0);
+ result = 31 * result + (cardType != null ? cardType.hashCode() : 0);
+ result = 31 * result + (cardCountry != null ? cardCountry.hashCode() : 0);
+ result = 31 * result + (invoicePaymentType != null ? invoicePaymentType.hashCode() : 0);
+ result = 31 * result + (linkedInvoicePaymentId != null ? linkedInvoicePaymentId.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessOverdueStatus.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessOverdueStatus.java
new file mode 100644
index 0000000..e96ce47
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessOverdueStatus.java
@@ -0,0 +1,123 @@
+/*
+ * 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 com.ning.billing.ObjectType;
+import com.ning.billing.analytics.api.BusinessOverdueStatus;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultBusinessOverdueStatus extends EntityBase implements BusinessOverdueStatus {
+
+ private final ObjectType objectType;
+ private final String accountKey;
+ private final String status;
+ private final DateTime startDate;
+ private final DateTime endDate;
+
+ public DefaultBusinessOverdueStatus(final BusinessOverdueStatusModelDao businessOverdueStatusModelDao) {
+ // TODO
+ super(businessOverdueStatusModelDao.getBundleId());
+ this.objectType = ObjectType.BUNDLE;
+
+ this.accountKey = businessOverdueStatusModelDao.getAccountKey();
+ this.status = businessOverdueStatusModelDao.getStatus();
+ this.startDate = businessOverdueStatusModelDao.getStartDate();
+ this.endDate = businessOverdueStatusModelDao.getEndDate();
+ }
+
+ @Override
+ public ObjectType getObjectType() {
+ return objectType;
+ }
+
+ @Override
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ @Override
+ public String getStatus() {
+ return status;
+ }
+
+ @Override
+ public DateTime getStartDate() {
+ return startDate;
+ }
+
+ @Override
+ public DateTime getEndDate() {
+ return endDate;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessOverdueStatus");
+ sb.append("{objectType=").append(objectType);
+ sb.append(", id='").append(id).append('\'');
+ sb.append(", accountKey='").append(accountKey).append('\'');
+ sb.append(", status='").append(status).append('\'');
+ sb.append(", startDate=").append(startDate);
+ sb.append(", endDate=").append(endDate);
+ 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 DefaultBusinessOverdueStatus that = (DefaultBusinessOverdueStatus) 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;
+ }
+ if (objectType != that.objectType) {
+ return false;
+ }
+ if (startDate != null ? !startDate.equals(that.startDate) : that.startDate != null) {
+ return false;
+ }
+ if (status != null ? !status.equals(that.status) : that.status != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ 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);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSnapshot.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSnapshot.java
new file mode 100644
index 0000000..807209d
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSnapshot.java
@@ -0,0 +1,153 @@
+/*
+ * 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.util.Collection;
+
+import com.ning.billing.analytics.api.BusinessAccount;
+import com.ning.billing.analytics.api.BusinessField;
+import com.ning.billing.analytics.api.BusinessInvoice;
+import com.ning.billing.analytics.api.BusinessInvoicePayment;
+import com.ning.billing.analytics.api.BusinessOverdueStatus;
+import com.ning.billing.analytics.api.BusinessSnapshot;
+import com.ning.billing.analytics.api.BusinessSubscriptionTransition;
+import com.ning.billing.analytics.api.BusinessTag;
+
+public class DefaultBusinessSnapshot implements BusinessSnapshot {
+
+ private final BusinessAccount businessAccount;
+ private final Collection<BusinessSubscriptionTransition> businessSubscriptionTransitions;
+ private final Collection<BusinessInvoice> businessInvoices;
+ private final Collection<BusinessInvoicePayment> businessInvoicePayments;
+ private final Collection<BusinessOverdueStatus> businessOverdueStatuses;
+ private final Collection<BusinessTag> businessTags;
+ private final Collection<BusinessField> businessFields;
+
+ public DefaultBusinessSnapshot(final BusinessAccount businessAccount,
+ final Collection<BusinessSubscriptionTransition> businessSubscriptionTransitions,
+ final Collection<BusinessInvoice> businessInvoices,
+ final Collection<BusinessInvoicePayment> businessInvoicePayments,
+ final Collection<BusinessOverdueStatus> businessOverdueStatuses,
+ final Collection<BusinessTag> businessTags,
+ final Collection<BusinessField> businessFields) {
+ this.businessAccount = businessAccount;
+ this.businessSubscriptionTransitions = businessSubscriptionTransitions;
+ this.businessInvoices = businessInvoices;
+ this.businessInvoicePayments = businessInvoicePayments;
+ this.businessOverdueStatuses = businessOverdueStatuses;
+ this.businessTags = businessTags;
+ this.businessFields = businessFields;
+ }
+
+ @Override
+ public BusinessAccount getBusinessAccount() {
+ return businessAccount;
+ }
+
+ @Override
+ public Collection<BusinessSubscriptionTransition> getBusinessSubscriptionTransitions() {
+ return businessSubscriptionTransitions;
+ }
+
+ @Override
+ public Collection<BusinessInvoice> getBusinessInvoices() {
+ return businessInvoices;
+ }
+
+ @Override
+ public Collection<BusinessInvoicePayment> getBusinessInvoicePayments() {
+ return businessInvoicePayments;
+ }
+
+ @Override
+ public Collection<BusinessOverdueStatus> getBusinessOverdueStatuses() {
+ return businessOverdueStatuses;
+ }
+
+ @Override
+ public Collection<BusinessTag> getBusinessTags() {
+ return businessTags;
+ }
+
+ @Override
+ public Collection<BusinessField> getBusinessFields() {
+ return businessFields;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessSnapshot");
+ sb.append("{businessAccount=").append(businessAccount);
+ sb.append(", businessSubscriptionTransitions=").append(businessSubscriptionTransitions);
+ sb.append(", businessInvoices=").append(businessInvoices);
+ sb.append(", businessInvoicePayments=").append(businessInvoicePayments);
+ sb.append(", businessOverdueStatuses=").append(businessOverdueStatuses);
+ sb.append(", businessTags=").append(businessTags);
+ sb.append(", businessFields=").append(businessFields);
+ 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 DefaultBusinessSnapshot that = (DefaultBusinessSnapshot) o;
+
+ if (businessAccount != null ? !businessAccount.equals(that.businessAccount) : that.businessAccount != null) {
+ return false;
+ }
+ if (businessFields != null ? !businessFields.equals(that.businessFields) : that.businessFields != null) {
+ return false;
+ }
+ if (businessInvoicePayments != null ? !businessInvoicePayments.equals(that.businessInvoicePayments) : that.businessInvoicePayments != null) {
+ return false;
+ }
+ if (businessInvoices != null ? !businessInvoices.equals(that.businessInvoices) : that.businessInvoices != null) {
+ return false;
+ }
+ if (businessOverdueStatuses != null ? !businessOverdueStatuses.equals(that.businessOverdueStatuses) : that.businessOverdueStatuses != null) {
+ return false;
+ }
+ if (businessSubscriptionTransitions != null ? !businessSubscriptionTransitions.equals(that.businessSubscriptionTransitions) : that.businessSubscriptionTransitions != null) {
+ return false;
+ }
+ if (businessTags != null ? !businessTags.equals(that.businessTags) : that.businessTags != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = businessAccount != null ? businessAccount.hashCode() : 0;
+ result = 31 * result + (businessSubscriptionTransitions != null ? businessSubscriptionTransitions.hashCode() : 0);
+ result = 31 * result + (businessInvoices != null ? businessInvoices.hashCode() : 0);
+ result = 31 * result + (businessInvoicePayments != null ? businessInvoicePayments.hashCode() : 0);
+ result = 31 * result + (businessOverdueStatuses != null ? businessOverdueStatuses.hashCode() : 0);
+ result = 31 * result + (businessTags != null ? businessTags.hashCode() : 0);
+ result = 31 * result + (businessFields != null ? businessFields.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSubscriptionTransition.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSubscriptionTransition.java
new file mode 100644
index 0000000..48ffed4
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessSubscriptionTransition.java
@@ -0,0 +1,497 @@
+/*
+ * 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 java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.analytics.api.BusinessSubscriptionTransition;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultBusinessSubscriptionTransition extends EntityBase implements BusinessSubscriptionTransition {
+
+ private final long totalOrdering;
+ private final UUID bundleId;
+ private final String externalKey;
+ private final UUID accountId;
+ private final String accountKey;
+ private final UUID subscriptionId;
+
+ private final DateTime requestedTimestamp;
+ private final String eventType;
+ private final String category;
+
+ private final String prevProductName;
+ private final String prevProductType;
+ private final String prevProductCategory;
+ private final String prevSlug;
+ private final String prevPhase;
+ private final String prevBillingPeriod;
+ private final BigDecimal prevPrice;
+ private final String prevPriceList;
+ private final BigDecimal prevMrr;
+ private final String prevCurrency;
+ private final DateTime prevStartDate;
+ private final String prevState;
+
+ private final String nextProductName;
+ private final String nextProductType;
+ private final String nextProductCategory;
+ private final String nextSlug;
+ private final String nextPhase;
+ private final String nextBillingPeriod;
+ private final BigDecimal nextPrice;
+ private final String nextPriceList;
+ private final BigDecimal nextMrr;
+ private final String nextCurrency;
+ private final DateTime nextStartDate;
+ private final String nextState;
+
+ public DefaultBusinessSubscriptionTransition(final BusinessSubscriptionTransitionModelDao bstModelDao) {
+ this.totalOrdering = bstModelDao.getTotalOrdering();
+ this.bundleId = bstModelDao.getBundleId();
+ this.externalKey = bstModelDao.getExternalKey();
+ this.accountId = bstModelDao.getAccountId();
+ this.accountKey = bstModelDao.getAccountKey();
+ this.subscriptionId = bstModelDao.getSubscriptionId();
+
+ this.requestedTimestamp = bstModelDao.getRequestedTimestamp();
+ this.eventType = bstModelDao.getEvent().getEventType().toString();
+ if (bstModelDao.getEvent().getCategory() != null) {
+ this.category = bstModelDao.getEvent().getCategory().toString();
+ } else {
+ this.category = null;
+ }
+
+ if (bstModelDao.getPreviousSubscription() != null) {
+ this.prevProductName = bstModelDao.getPreviousSubscription().getProductName();
+ this.prevProductType = bstModelDao.getPreviousSubscription().getProductType();
+ this.prevProductCategory = bstModelDao.getPreviousSubscription().getProductCategory().toString();
+ this.prevSlug = bstModelDao.getPreviousSubscription().getSlug();
+ this.prevPhase = bstModelDao.getPreviousSubscription().getPhase();
+ this.prevBillingPeriod = bstModelDao.getPreviousSubscription().getBillingPeriod();
+ this.prevPrice = bstModelDao.getPreviousSubscription().getPrice();
+ this.prevPriceList = bstModelDao.getPreviousSubscription().getPriceList();
+ this.prevMrr = bstModelDao.getPreviousSubscription().getMrr();
+ this.prevCurrency = bstModelDao.getPreviousSubscription().getCurrency();
+ this.prevStartDate = bstModelDao.getPreviousSubscription().getStartDate();
+ this.prevState = bstModelDao.getPreviousSubscription().getState().toString();
+ } else {
+ this.prevProductName = null;
+ this.prevProductType = null;
+ this.prevProductCategory = null;
+ this.prevSlug = null;
+ this.prevPhase = null;
+ this.prevBillingPeriod = null;
+ this.prevPrice = null;
+ this.prevPriceList = null;
+ this.prevMrr = null;
+ this.prevCurrency = null;
+ this.prevStartDate = null;
+ this.prevState = null;
+ }
+
+ if (bstModelDao.getNextSubscription() != null) {
+ this.nextProductName = bstModelDao.getNextSubscription().getProductName();
+ this.nextProductType = bstModelDao.getNextSubscription().getProductType();
+ this.nextProductCategory = bstModelDao.getNextSubscription().getProductCategory().toString();
+ this.nextSlug = bstModelDao.getNextSubscription().getSlug();
+ this.nextPhase = bstModelDao.getNextSubscription().getPhase();
+ this.nextBillingPeriod = bstModelDao.getNextSubscription().getBillingPeriod();
+ this.nextPrice = bstModelDao.getNextSubscription().getPrice();
+ this.nextPriceList = bstModelDao.getNextSubscription().getPriceList();
+ this.nextMrr = bstModelDao.getNextSubscription().getMrr();
+ this.nextCurrency = bstModelDao.getNextSubscription().getCurrency();
+ this.nextStartDate = bstModelDao.getNextSubscription().getStartDate();
+ this.nextState = bstModelDao.getNextSubscription().getState().toString();
+ } else {
+ this.nextProductName = null;
+ this.nextProductType = null;
+ this.nextProductCategory = null;
+ this.nextSlug = null;
+ this.nextPhase = null;
+ this.nextBillingPeriod = null;
+ this.nextPrice = null;
+ this.nextPriceList = null;
+ this.nextMrr = null;
+ this.nextCurrency = null;
+ this.nextStartDate = null;
+ this.nextState = null;
+ }
+ }
+
+ @Override
+ public long getTotalOrdering() {
+ return totalOrdering;
+ }
+
+ @Override
+ public UUID getBundleId() {
+ return bundleId;
+ }
+
+ @Override
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ @Override
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ @Override
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ @Override
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ @Override
+ public DateTime getRequestedTimestamp() {
+ return requestedTimestamp;
+ }
+
+ @Override
+ public String getEventType() {
+ return eventType;
+ }
+
+ @Override
+ public String getCategory() {
+ return category;
+ }
+
+ @Override
+ public String getPrevProductName() {
+ return prevProductName;
+ }
+
+ @Override
+ public String getPrevProductType() {
+ return prevProductType;
+ }
+
+ @Override
+ public String getPrevProductCategory() {
+ return prevProductCategory;
+ }
+
+ @Override
+ public String getPrevSlug() {
+ return prevSlug;
+ }
+
+ @Override
+ public String getPrevPhase() {
+ return prevPhase;
+ }
+
+ @Override
+ public String getPrevBillingPeriod() {
+ return prevBillingPeriod;
+ }
+
+ @Override
+ public BigDecimal getPrevPrice() {
+ return prevPrice;
+ }
+
+ @Override
+ public String getPrevPriceList() {
+ return prevPriceList;
+ }
+
+ @Override
+ public BigDecimal getPrevMrr() {
+ return prevMrr;
+ }
+
+ @Override
+ public String getPrevCurrency() {
+ return prevCurrency;
+ }
+
+ @Override
+ public DateTime getPrevStartDate() {
+ return prevStartDate;
+ }
+
+ @Override
+ public String getPrevState() {
+ return prevState;
+ }
+
+ @Override
+ public String getNextProductName() {
+ return nextProductName;
+ }
+
+ @Override
+ public String getNextProductType() {
+ return nextProductType;
+ }
+
+ @Override
+ public String getNextProductCategory() {
+ return nextProductCategory;
+ }
+
+ @Override
+ public String getNextSlug() {
+ return nextSlug;
+ }
+
+ @Override
+ public String getNextPhase() {
+ return nextPhase;
+ }
+
+ @Override
+ public String getNextBillingPeriod() {
+ return nextBillingPeriod;
+ }
+
+ @Override
+ public BigDecimal getNextPrice() {
+ return nextPrice;
+ }
+
+ @Override
+ public String getNextPriceList() {
+ return nextPriceList;
+ }
+
+ @Override
+ public BigDecimal getNextMrr() {
+ return nextMrr;
+ }
+
+ @Override
+ public String getNextCurrency() {
+ return nextCurrency;
+ }
+
+ @Override
+ public DateTime getNextStartDate() {
+ return nextStartDate;
+ }
+
+ @Override
+ public String getNextState() {
+ return nextState;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessSubscriptionTransition");
+ sb.append("{totalOrdering=").append(totalOrdering);
+ sb.append(", bundleId=").append(bundleId);
+ sb.append(", externalKey='").append(externalKey).append('\'');
+ sb.append(", accountId=").append(accountId);
+ sb.append(", accountKey='").append(accountKey).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(", 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(", nextStartDate=").append(nextStartDate);
+ 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;
+ }
+
+ final DefaultBusinessSubscriptionTransition that = (DefaultBusinessSubscriptionTransition) o;
+
+ if (totalOrdering != that.totalOrdering) {
+ return false;
+ }
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != 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 (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (nextBillingPeriod != null ? !nextBillingPeriod.equals(that.nextBillingPeriod) : that.nextBillingPeriod != null) {
+ return false;
+ }
+ if (nextCurrency != null ? !nextCurrency.equals(that.nextCurrency) : that.nextCurrency != 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 (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 = (int) (totalOrdering ^ (totalOrdering >>> 32));
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+ result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
+ result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+ result = 31 * result + (accountKey != null ? accountKey.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 + (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 + (nextStartDate != null ? nextStartDate.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/DefaultBusinessTag.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessTag.java
new file mode 100644
index 0000000..d2c5ab8
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultBusinessTag.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.ning.billing.ObjectType;
+import com.ning.billing.analytics.api.BusinessTag;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessTagModelDao;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultBusinessTag extends EntityBase implements BusinessTag {
+
+ private final ObjectType objectType;
+ private final String name;
+
+ DefaultBusinessTag(final ObjectType objectType, final BusinessTagModelDao businessTagModelDao) {
+ super(businessTagModelDao.getId());
+ this.objectType = objectType;
+ this.name = businessTagModelDao.getName();
+ }
+
+ public DefaultBusinessTag(final BusinessAccountTagModelDao businessAccountTagModelDao) {
+ this(ObjectType.ACCOUNT, businessAccountTagModelDao);
+ }
+
+ public DefaultBusinessTag(final BusinessInvoiceTagModelDao businessInvoiceTagModelDao) {
+ this(ObjectType.INVOICE, businessInvoiceTagModelDao);
+ }
+
+ public DefaultBusinessTag(final BusinessInvoicePaymentTagModelDao businessInvoicePaymentTagModelDao) {
+ this(ObjectType.PAYMENT, businessInvoicePaymentTagModelDao);
+ }
+
+ public DefaultBusinessTag(final BusinessSubscriptionTransitionTagModelDao businessSubscriptionTransitionTagModelDao) {
+ this(ObjectType.BUNDLE, businessSubscriptionTransitionTagModelDao);
+ }
+
+ @Override
+ public ObjectType getObjectType() {
+ return objectType;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultBusinessTag");
+ sb.append("{objectType=").append(objectType);
+ sb.append(", name='").append(name).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 DefaultBusinessTag that = (DefaultBusinessTag) o;
+
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (objectType != that.objectType) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = objectType != null ? objectType.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultTimeSeriesData.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultTimeSeriesData.java
new file mode 100644
index 0000000..6b98f05
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/DefaultTimeSeriesData.java
@@ -0,0 +1,89 @@
+/*
+ * 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.util.LinkedList;
+import java.util.List;
+
+import org.joda.time.LocalDate;
+
+import com.ning.billing.analytics.api.TimeSeriesData;
+import com.ning.billing.osgi.bundles.analytics.dao.TimeSeriesTuple;
+
+public class DefaultTimeSeriesData implements TimeSeriesData {
+
+ private final List<LocalDate> dates;
+ private final List<Double> values;
+
+ public DefaultTimeSeriesData(final List<TimeSeriesTuple> dataOverTime) {
+ // We assume dataOverTime is sorted by time
+ dates = new LinkedList<LocalDate>();
+ values = new LinkedList<Double>();
+ for (final TimeSeriesTuple data : dataOverTime) {
+ dates.add(data.getLocalDate());
+ values.add(data.getValue());
+ }
+ }
+
+ @Override
+ public List<LocalDate> getDates() {
+ return dates;
+ }
+
+ @Override
+ public List<Double> getValues() {
+ return values;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultTimeSeriesData");
+ sb.append("{dates=").append(dates);
+ sb.append(", values=").append(values);
+ 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 DefaultTimeSeriesData that = (DefaultTimeSeriesData) o;
+
+ if (dates != null ? !dates.equals(that.dates) : that.dates != null) {
+ return false;
+ }
+ if (values != null ? !values.equals(that.values) : that.values != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = dates != null ? dates.hashCode() : 0;
+ result = 31 * result + (values != null ? values.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/sanity/DefaultAnalyticsSanityApi.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/sanity/DefaultAnalyticsSanityApi.java
new file mode 100644
index 0000000..f48e9bd
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/sanity/DefaultAnalyticsSanityApi.java
@@ -0,0 +1,82 @@
+/*
+ * 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.sanity;
+
+import java.util.Collection;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import com.ning.billing.analytics.api.sanity.AnalyticsSanityApi;
+import com.ning.billing.osgi.bundles.analytics.dao.AnalyticsSanityDao;
+import com.ning.billing.util.callcontext.InternalCallContextFactory;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.TenantContext;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class DefaultAnalyticsSanityApi implements AnalyticsSanityApi {
+
+ private final AnalyticsSanityDao dao;
+ private final InternalCallContextFactory internalCallContextFactory;
+
+ @Inject
+ public DefaultAnalyticsSanityApi(final AnalyticsSanityDao dao,
+ final InternalCallContextFactory internalCallContextFactory) {
+ this.dao = dao;
+ this.internalCallContextFactory = internalCallContextFactory;
+ }
+
+ @Override
+ public Collection<UUID> checkAnalyticsInSyncWithEntitlement(final TenantContext context) {
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(context);
+ return dao.checkBstMatchesSubscriptionEvents(internalTenantContext);
+ }
+
+ @Override
+ public Collection<UUID> checkAnalyticsInSyncWithInvoice(final TenantContext context) {
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(context);
+ return dao.checkBiiMatchesInvoiceItems(internalTenantContext);
+ }
+
+ @Override
+ public Collection<UUID> checkAnalyticsInSyncWithPayment(final TenantContext context) {
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(context);
+ final Collection<UUID> check1 = dao.checkBipMatchesInvoicePayments(internalTenantContext);
+ final Collection<UUID> check2 = dao.checkBinAmountPaidMatchesInvoicePayments(internalTenantContext);
+ final Collection<UUID> check3 = dao.checkBinAmountChargedMatchesInvoicePayments(internalTenantContext);
+
+ return ImmutableSet.<UUID>copyOf(Iterables.<UUID>concat(check1, check2, check3));
+ }
+
+ @Override
+ public Collection<UUID> checkAnalyticsInSyncWithTag(final TenantContext context) {
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(context);
+ return dao.checkBacTagsMatchesTags(internalTenantContext);
+ }
+
+ @Override
+ public Collection<UUID> checkAnalyticsConsistency(final TenantContext context) {
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(context);
+ final Collection<UUID> check1 = dao.checkBinBiiBalanceConsistency(internalTenantContext);
+ final Collection<UUID> check2 = dao.checkBinBiiAmountCreditedConsistency(internalTenantContext);
+ final Collection<UUID> check3 = dao.checkBacBinBiiConsistency(internalTenantContext);
+
+ return ImmutableSet.<UUID>copyOf(Iterables.<UUID>concat(check1, check2, check3));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/user/DefaultAnalyticsUserApi.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/user/DefaultAnalyticsUserApi.java
new file mode 100644
index 0000000..0364521
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/api/user/DefaultAnalyticsUserApi.java
@@ -0,0 +1,395 @@
+/*
+ * 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.user;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.analytics.api.BusinessAccount;
+import com.ning.billing.analytics.api.BusinessField;
+import com.ning.billing.analytics.api.BusinessInvoice;
+import com.ning.billing.analytics.api.BusinessInvoicePayment;
+import com.ning.billing.analytics.api.BusinessOverdueStatus;
+import com.ning.billing.analytics.api.BusinessSnapshot;
+import com.ning.billing.analytics.api.BusinessSubscriptionTransition;
+import com.ning.billing.analytics.api.BusinessTag;
+import com.ning.billing.analytics.api.TimeSeriesData;
+import com.ning.billing.analytics.api.user.AnalyticsUserApi;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.osgi.bundles.analytics.BusinessAccountDao;
+import com.ning.billing.osgi.bundles.analytics.BusinessInvoiceDao;
+import com.ning.billing.osgi.bundles.analytics.BusinessInvoicePaymentDao;
+import com.ning.billing.osgi.bundles.analytics.BusinessOverdueStatusDao;
+import com.ning.billing.osgi.bundles.analytics.BusinessSubscriptionTransitionDao;
+import com.ning.billing.osgi.bundles.analytics.BusinessTagDao;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultBusinessAccount;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultBusinessInvoice;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultBusinessInvoicePayment;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultBusinessOverdueStatus;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultBusinessSnapshot;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultBusinessSubscriptionTransition;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultBusinessTag;
+import com.ning.billing.osgi.bundles.analytics.dao.AnalyticsDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.payment.api.Payment;
+import com.ning.billing.payment.api.PaymentApiException;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalCallContextFactory;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.TenantContext;
+import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
+import com.ning.billing.util.svcapi.payment.PaymentInternalApi;
+import com.ning.billing.util.svcapi.tag.TagInternalApi;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDefinition;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+
+public class DefaultAnalyticsUserApi implements AnalyticsUserApi {
+
+ private static final Logger log = LoggerFactory.getLogger(DefaultAnalyticsUserApi.class);
+
+ private final AnalyticsDao analyticsDao;
+ private final BusinessSubscriptionTransitionDao bstDao;
+ private final BusinessAccountDao bacDao;
+ private final BusinessInvoiceDao invoiceDao;
+ private final BusinessOverdueStatusDao bosDao;
+ private final BusinessInvoicePaymentDao bipDao;
+ private final BusinessTagDao tagDao;
+ private final EntitlementInternalApi entitlementInternalApi;
+ private final PaymentInternalApi paymentApi;
+ private final TagInternalApi tagInternalApi;
+ private final InternalCallContextFactory internalCallContextFactory;
+
+ @Inject
+ public DefaultAnalyticsUserApi(final AnalyticsDao analyticsDao,
+ final BusinessSubscriptionTransitionDao bstDao,
+ final BusinessAccountDao bacDao,
+ final BusinessInvoiceDao invoiceDao,
+ final BusinessOverdueStatusDao bosDao,
+ final BusinessInvoicePaymentDao bipDao,
+ final BusinessTagDao tagDao,
+ final EntitlementInternalApi entitlementInternalApi,
+ final PaymentInternalApi paymentApi,
+ final TagInternalApi tagInternalApi,
+ final InternalCallContextFactory internalCallContextFactory) {
+ this.analyticsDao = analyticsDao;
+ this.bstDao = bstDao;
+ this.bacDao = bacDao;
+ this.invoiceDao = invoiceDao;
+ this.bosDao = bosDao;
+ this.bipDao = bipDao;
+ this.tagDao = tagDao;
+ this.entitlementInternalApi = entitlementInternalApi;
+ this.paymentApi = paymentApi;
+ this.tagInternalApi = tagInternalApi;
+ this.internalCallContextFactory = internalCallContextFactory;
+ }
+
+ @Override
+ public BusinessSnapshot getBusinessSnapshot(final Account account, final TenantContext context) {
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(context);
+
+ // Find account
+ final BusinessAccount businessAccount = getAccountByKey(account.getExternalKey(), context);
+
+ // Find all transitions for all bundles for that account, and associated overdue statuses
+ final List<SubscriptionBundle> bundles = entitlementInternalApi.getBundlesForAccount(account.getId(), internalTenantContext);
+ final Collection<BusinessSubscriptionTransition> businessSubscriptionTransitions = new ArrayList<BusinessSubscriptionTransition>();
+ final Collection<BusinessOverdueStatus> businessOverdueStatuses = new ArrayList<BusinessOverdueStatus>();
+ for (final SubscriptionBundle bundle : bundles) {
+ businessSubscriptionTransitions.addAll(getTransitionsForBundle(bundle.getExternalKey(), context));
+ businessOverdueStatuses.addAll(getOverdueStatusesForBundle(bundle.getExternalKey(), context));
+ }
+
+ // Find all invoices for that account
+ final Collection<BusinessInvoice> businessInvoices = getInvoicesForAccount(account.getExternalKey(), context);
+
+ // Find all payments for that account
+ final Collection<BusinessInvoicePayment> businessInvoicePayments = getInvoicePaymentsForAccount(account.getExternalKey(), context);
+
+ // Find all tags for that account
+ // TODO add other tag types
+ final Collection<BusinessTag> businessTags = getTagsForAccount(account.getExternalKey(), context);
+
+ // TODO find custom fields
+ final Collection<BusinessField> businessFields = ImmutableList.<BusinessField>of();
+
+ return new DefaultBusinessSnapshot(businessAccount, businessSubscriptionTransitions, businessInvoices, businessInvoicePayments,
+ businessOverdueStatuses, businessTags, businessFields);
+ }
+
+ @Override
+ public BusinessAccount getAccountByKey(final String accountKey, final TenantContext context) {
+ final BusinessAccountModelDao accountByKey = analyticsDao.getAccountByKey(accountKey, internalCallContextFactory.createInternalTenantContext(context));
+ if (accountByKey == null) {
+ return null;
+ } else {
+ return new DefaultBusinessAccount(accountByKey);
+ }
+ }
+
+ @Override
+ public List<BusinessSubscriptionTransition> getTransitionsForBundle(final String externalKey, final TenantContext context) {
+ final List<BusinessSubscriptionTransitionModelDao> transitionsByKey = analyticsDao.getTransitionsByKey(externalKey, internalCallContextFactory.createInternalTenantContext(context));
+ return ImmutableList.<BusinessSubscriptionTransition>copyOf(Collections2.transform(transitionsByKey, new Function<BusinessSubscriptionTransitionModelDao, BusinessSubscriptionTransition>() {
+ @Override
+ public BusinessSubscriptionTransition apply(@Nullable final BusinessSubscriptionTransitionModelDao input) {
+ return new DefaultBusinessSubscriptionTransition(input);
+ }
+ }));
+ }
+
+ @Override
+ public List<BusinessInvoice> getInvoicesForAccount(final String accountKey, final TenantContext context) {
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(context);
+ final List<BusinessInvoiceModelDao> invoicesByKey = analyticsDao.getInvoicesByKey(accountKey, internalTenantContext);
+ return ImmutableList.<BusinessInvoice>copyOf(Collections2.transform(invoicesByKey, new Function<BusinessInvoiceModelDao, BusinessInvoice>() {
+ @Override
+ public BusinessInvoice apply(@Nullable final BusinessInvoiceModelDao input) {
+ return new DefaultBusinessInvoice(input, input == null ? null : analyticsDao.getInvoiceItemsForInvoice(input.getInvoiceId().toString(), internalTenantContext));
+ }
+ }));
+ }
+
+ @Override
+ public List<BusinessInvoicePayment> getInvoicePaymentsForAccount(final String accountKey, final TenantContext context) {
+ final List<BusinessInvoicePaymentModelDao> invoicePaymentsForAccountByKey = analyticsDao.getInvoicePaymentsForAccountByKey(accountKey, internalCallContextFactory.createInternalTenantContext(context));
+ return ImmutableList.<BusinessInvoicePayment>copyOf(Collections2.transform(invoicePaymentsForAccountByKey, new Function<BusinessInvoicePaymentModelDao, BusinessInvoicePayment>() {
+ @Override
+ public BusinessInvoicePayment apply(@Nullable final BusinessInvoicePaymentModelDao input) {
+ return new DefaultBusinessInvoicePayment(input);
+ }
+ }));
+ }
+
+ @Override
+ public List<BusinessOverdueStatus> getOverdueStatusesForBundle(final String externalKey, final TenantContext context) {
+ final List<BusinessOverdueStatusModelDao> overdueStatusesForBundleByKey = analyticsDao.getOverdueStatusesForBundleByKey(externalKey, internalCallContextFactory.createInternalTenantContext(context));
+ return ImmutableList.<BusinessOverdueStatus>copyOf(Collections2.transform(overdueStatusesForBundleByKey, new Function<BusinessOverdueStatusModelDao, BusinessOverdueStatus>() {
+ @Override
+ public BusinessOverdueStatus apply(@Nullable final BusinessOverdueStatusModelDao input) {
+ return new DefaultBusinessOverdueStatus(input);
+ }
+ }));
+ }
+
+ @Override
+ public List<BusinessTag> getTagsForAccount(final String accountKey, final TenantContext context) {
+ final List<BusinessAccountTagModelDao> tagsForAccount = analyticsDao.getTagsForAccount(accountKey, internalCallContextFactory.createInternalTenantContext(context));
+ return ImmutableList.<BusinessTag>copyOf(Collections2.transform(tagsForAccount, new Function<BusinessAccountTagModelDao, BusinessTag>() {
+ @Override
+ public BusinessTag apply(@Nullable final BusinessAccountTagModelDao input) {
+ return new DefaultBusinessTag(input);
+ }
+ }));
+ }
+
+ @Override
+ public TimeSeriesData getAccountsCreatedOverTime(final TenantContext context) {
+ return analyticsDao.getAccountsCreatedOverTime(internalCallContextFactory.createInternalTenantContext(context));
+ }
+
+ @Override
+ public TimeSeriesData getSubscriptionsCreatedOverTime(final String productType, final String slug, final TenantContext context) {
+ return analyticsDao.getSubscriptionsCreatedOverTime(productType, slug, internalCallContextFactory.createInternalTenantContext(context));
+ }
+
+ @Override
+ public void rebuildAnalyticsForAccount(final Account account, final CallContext context) {
+ final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), context);
+
+ // Update the BAC row
+ bacDao.accountUpdated(account.getId(), internalCallContext);
+
+ // Update BST for all bundles
+ final Set<UUID> bundleIds = updateBST(account, internalCallContext);
+
+ // Update BIN and BII for all invoices
+ invoiceDao.rebuildInvoicesForAccount(account.getId(), internalCallContext);
+
+ // Update BIP for all invoices
+ try {
+ updateBIP(account, internalCallContext);
+ } catch (PaymentApiException e) {
+ // Log and ignore
+ log.warn(e.toString());
+ }
+
+ // Update BOS for all bundles (only blockable supported today)
+ // TODO: support other blockables
+ for (final UUID bundleId : bundleIds) {
+ bosDao.overdueStatusChanged(Type.SUBSCRIPTION_BUNDLE, bundleId, internalCallContext);
+ }
+
+ // Update bac_tags
+ // TODO: refresh all tags
+ updateTags(account, internalCallContext);
+ }
+
+ private Set<UUID> updateBST(final Account account, final InternalCallContext internalCallContext) {
+ // Find the current state of bundles in entitlement
+ final Collection<UUID> entitlementBundlesId = Collections2.transform(entitlementInternalApi.getBundlesForAccount(account.getId(), internalCallContext),
+ new Function<SubscriptionBundle, UUID>() {
+ @Override
+ public UUID apply(@Nullable final SubscriptionBundle input) {
+ if (input == null) {
+ return null;
+ } else {
+ return input.getId();
+ }
+ }
+ });
+
+ // Find the current state of bundles in analytics
+ final Collection<UUID> analyticsBundlesId = Collections2.transform(analyticsDao.getTransitionsForAccount(account.getExternalKey(), internalCallContext),
+ new Function<BusinessSubscriptionTransitionModelDao, UUID>() {
+ @Override
+ public UUID apply(@Nullable final BusinessSubscriptionTransitionModelDao input) {
+ if (input == null) {
+ return null;
+ } else {
+ return input.getBundleId();
+ }
+ }
+ });
+
+ // Update BST for all bundles found
+ final Set<UUID> bundlesId = new HashSet<UUID>();
+ bundlesId.addAll(entitlementBundlesId);
+ bundlesId.addAll(analyticsBundlesId);
+ for (final UUID bundleId : bundlesId) {
+ bstDao.rebuildTransitionsForBundle(bundleId, internalCallContext);
+ }
+
+ return bundlesId;
+ }
+
+ private void updateBIP(final Account account, final InternalCallContext internalCallContext) throws PaymentApiException {
+ final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), internalCallContext);
+ final Map<UUID, Payment> payments = new HashMap<UUID, Payment>();
+ for (final Payment payment : accountPayments) {
+ payments.put(payment.getId(), payment);
+ }
+
+ // Find the current state of payments in payment
+ final Collection<UUID> paymentPaymentsId = Collections2.transform(accountPayments,
+ new Function<Payment, UUID>() {
+ @Override
+ public UUID apply(@Nullable final Payment input) {
+ if (input == null) {
+ return null;
+ } else {
+ return input.getId();
+ }
+ }
+ });
+
+ // Find the current state of payments in analytics
+ final Collection<UUID> analyticsPaymentsId = Collections2.transform(analyticsDao.getInvoicePaymentsForAccountByKey(account.getExternalKey(), internalCallContext),
+ new Function<BusinessInvoicePaymentModelDao, UUID>() {
+ @Override
+ public UUID apply(@Nullable final BusinessInvoicePaymentModelDao input) {
+ if (input == null) {
+ return null;
+ } else {
+ return input.getPaymentId();
+ }
+ }
+ });
+
+ // Update BIP for all payments found
+ final Set<UUID> paymentsId = new HashSet<UUID>();
+ paymentsId.addAll(paymentPaymentsId);
+ paymentsId.addAll(analyticsPaymentsId);
+ for (final UUID paymentId : paymentsId) {
+ final Payment paymentInfo = payments.get(paymentId);
+ bipDao.invoicePaymentPosted(paymentInfo.getAccountId(),
+ paymentInfo.getId(),
+ paymentInfo.getPaymentStatus().toString(),
+ internalCallContext);
+ }
+ }
+
+ private void updateTags(final Account account, final InternalCallContext internalCallContext) {
+ // Find the current state of tags from util
+ final List<TagDefinition> tagDefinitions = tagInternalApi.getTagDefinitions(internalCallContext);
+ final Collection<String> utilTags = Collections2.transform(tagInternalApi.getTags(account.getId(), ObjectType.ACCOUNT, internalCallContext),
+ new Function<Tag, String>() {
+ @Override
+ public String apply(@Nullable final Tag input) {
+ if (input == null) {
+ return "";
+ }
+
+ for (final TagDefinition tagDefinition : tagDefinitions) {
+ if (tagDefinition.getId().equals(input.getTagDefinitionId())) {
+ return tagDefinition.getName();
+ }
+ }
+ return "";
+ }
+ });
+
+ // Find the current state of tags in analytics
+ final Collection<String> analyticsTags = Collections2.transform(analyticsDao.getTagsForAccount(account.getExternalKey(), internalCallContext),
+ new Function<BusinessAccountTagModelDao, String>() {
+ @Override
+ public String apply(@Nullable final BusinessAccountTagModelDao input) {
+ if (input == null) {
+ return null;
+ } else {
+ return input.getName();
+ }
+ }
+ });
+
+ // Remove non existing tags
+ for (final String tag : Sets.difference(new HashSet<String>(analyticsTags), new HashSet<String>(utilTags))) {
+ tagDao.tagRemoved(ObjectType.ACCOUNT, account.getId(), tag, internalCallContext);
+ }
+
+ // Add missing ones
+ for (final String tag : Sets.difference(new HashSet<String>(utilTags), new HashSet<String>(analyticsTags))) {
+ tagDao.tagAdded(ObjectType.ACCOUNT, account.getId(), tag, internalCallContext);
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessAccountDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessAccountDao.java
new file mode 100644
index 0000000..0bce215
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessAccountDao.java
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountSqlDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.payment.api.Payment;
+import com.ning.billing.payment.api.PaymentApiException;
+import com.ning.billing.payment.api.PaymentMethod;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
+import com.ning.billing.util.svcapi.payment.PaymentInternalApi;
+
+import com.google.inject.Inject;
+
+public class BusinessAccountDao {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessAccountDao.class);
+
+ private final BusinessAccountSqlDao sqlDao;
+ private final AccountInternalApi accountApi;
+ private final InvoiceInternalApi invoiceApi;
+ private final PaymentInternalApi paymentApi;
+
+ @Inject
+ public BusinessAccountDao(final BusinessAccountSqlDao sqlDao, final AccountInternalApi accountApi,
+ final InvoiceInternalApi invoiceApi, final PaymentInternalApi paymentApi) {
+ this.sqlDao = sqlDao;
+ this.accountApi = accountApi;
+ this.invoiceApi = invoiceApi;
+ this.paymentApi = paymentApi;
+ }
+
+ public void accountUpdated(final UUID accountId, final InternalCallContext context) {
+ final Account account;
+ try {
+ account = accountApi.getAccountById(accountId, context);
+ } catch (AccountApiException e) {
+ log.warn("Error encountered creating BusinessAccountModelDao", e);
+ return;
+ }
+
+ final BusinessAccountModelDao bac = createBusinessAccountFromAccount(account, context);
+ sqlDao.inTransaction(new Transaction<Void, BusinessAccountSqlDao>() {
+ @Override
+ public Void inTransaction(final BusinessAccountSqlDao transactional, final TransactionStatus status) throws Exception {
+ updateAccountInTransaction(bac, transactional, context);
+ return null;
+ }
+ });
+ }
+
+ // Called also from BusinessInvoiceDao and BusinessInvoicePaymentDao.
+ // Note: computing the BusinessAccountModelDao object is fairly expensive, hence should be done outside of the transaction
+ public void updateAccountInTransaction(final BusinessAccountModelDao bac, final BusinessAccountSqlDao transactional, final InternalCallContext context) {
+ log.info("ACCOUNT UPDATE " + bac);
+ transactional.deleteAccount(bac.getAccountId().toString(), context);
+ // Note! There is a window of doom here since we use read committed transactional level by default
+ transactional.createAccount(bac, context);
+ }
+
+ public BusinessAccountModelDao createBusinessAccountFromAccount(final Account account, final InternalTenantContext context) {
+ final BusinessAccountModelDao bac = new BusinessAccountModelDao(account);
+
+ try {
+ LocalDate lastInvoiceDate = bac.getLastInvoiceDate();
+ BigDecimal totalInvoiceBalance = bac.getTotalInvoiceBalance();
+ String lastPaymentStatus = bac.getLastPaymentStatus();
+ String paymentMethodType = bac.getPaymentMethod();
+ String creditCardType = bac.getCreditCardType();
+ String billingAddressCountry = bac.getBillingAddressCountry();
+
+ // Retrieve invoices information
+ final Collection<Invoice> invoices = invoiceApi.getInvoicesByAccountId(account.getId(), context);
+ if (invoices != null && invoices.size() > 0) {
+ for (final Invoice invoice : invoices) {
+ totalInvoiceBalance = totalInvoiceBalance.add(invoice.getBalance());
+
+ if (lastInvoiceDate == null || invoice.getInvoiceDate().isAfter(lastInvoiceDate)) {
+ lastInvoiceDate = invoice.getInvoiceDate();
+ }
+ }
+
+ // Retrieve payments information for these invoices
+ DateTime lastPaymentDate = null;
+
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), context);
+ if (payments != null) {
+ for (final Payment cur : payments) {
+ // Use the last payment method/type/country as the default one for the account
+ if (lastPaymentDate == null || cur.getEffectiveDate().isAfter(lastPaymentDate)) {
+ lastPaymentDate = cur.getEffectiveDate();
+ lastPaymentStatus = cur.getPaymentStatus().toString();
+ }
+ }
+ }
+ }
+
+ // Retrieve payment methods
+ for (final PaymentMethod paymentMethod : paymentApi.getPaymentMethods(account, context)) {
+ if (paymentMethod.getId().equals(account.getPaymentMethodId()) && paymentMethod.getPluginDetail() != null) {
+ paymentMethodType = PaymentMethodUtils.getPaymentMethodType(paymentMethod.getPluginDetail());
+ creditCardType = PaymentMethodUtils.getCardType(paymentMethod.getPluginDetail());
+ billingAddressCountry = PaymentMethodUtils.getCardCountry(paymentMethod.getPluginDetail());
+ break;
+ }
+ }
+
+ bac.setLastPaymentStatus(lastPaymentStatus);
+ bac.setPaymentMethod(paymentMethodType);
+ bac.setCreditCardType(creditCardType);
+ bac.setBillingAddressCountry(billingAddressCountry);
+ bac.setLastInvoiceDate(lastInvoiceDate);
+ bac.setTotalInvoiceBalance(totalInvoiceBalance);
+
+ bac.setBalance(invoiceApi.getAccountBalance(account.getId(), context));
+ } catch (PaymentApiException ex) {
+ log.error(String.format("Failed to handle account update for account %s", account.getId()), ex);
+ }
+
+ return bac;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoiceDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoiceDao.java
new file mode 100644
index 0000000..efbb85e
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoiceDao.java
@@ -0,0 +1,221 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceItemSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
+import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class BusinessInvoiceDao {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessInvoiceDao.class);
+
+ private final AccountInternalApi accountApi;
+ private final EntitlementInternalApi entitlementApi;
+ private final InvoiceInternalApi invoiceApi;
+ private final BusinessAccountDao businessAccountDao;
+ private final BusinessInvoiceSqlDao sqlDao;
+ private final CatalogService catalogService;
+
+ @Inject
+ public BusinessInvoiceDao(final AccountInternalApi accountApi,
+ final EntitlementInternalApi entitlementApi,
+ final InvoiceInternalApi invoiceApi,
+ final BusinessAccountDao businessAccountDao,
+ final BusinessInvoiceSqlDao sqlDao,
+ final CatalogService catalogService) {
+ this.accountApi = accountApi;
+ this.entitlementApi = entitlementApi;
+ this.invoiceApi = invoiceApi;
+ this.businessAccountDao = businessAccountDao;
+ this.sqlDao = sqlDao;
+ this.catalogService = catalogService;
+ }
+
+ public void rebuildInvoicesForAccount(final UUID accountId, final InternalCallContext context) {
+ // Lookup the associated account
+ final Account account;
+ try {
+ account = accountApi.getAccountById(accountId, context);
+ } catch (AccountApiException e) {
+ log.warn("Ignoring invoice update for account id {} (account does not exist)", accountId);
+ return;
+ }
+
+ // Lookup the invoices for that account
+ final Collection<Invoice> invoices = invoiceApi.getInvoicesByAccountId(account.getId(), context);
+
+ // Create the business invoice and associated business invoice items
+ final Map<BusinessInvoiceModelDao, Collection<BusinessInvoiceItemModelDao>> businessInvoices = new HashMap<BusinessInvoiceModelDao, Collection<BusinessInvoiceItemModelDao>>();
+ for (final Invoice invoice : invoices) {
+ final BusinessInvoiceModelDao businessInvoice = new BusinessInvoiceModelDao(account.getExternalKey(), invoice);
+
+ final List<BusinessInvoiceItemModelDao> businessInvoiceItems = new ArrayList<BusinessInvoiceItemModelDao>();
+ for (final InvoiceItem invoiceItem : invoice.getInvoiceItems()) {
+ final BusinessInvoiceItemModelDao businessInvoiceItem = createBusinessInvoiceItem(invoiceItem, context);
+ if (businessInvoiceItem != null) {
+ businessInvoiceItems.add(businessInvoiceItem);
+ }
+ }
+
+ businessInvoices.put(businessInvoice, businessInvoiceItems);
+ }
+
+ // Update the account record
+ final BusinessAccountModelDao bac = businessAccountDao.createBusinessAccountFromAccount(account, context);
+
+ // Delete and recreate invoice and invoice items in the transaction
+ sqlDao.inTransaction(new Transaction<Void, BusinessInvoiceSqlDao>() {
+ @Override
+ public Void inTransaction(final BusinessInvoiceSqlDao transactional, final TransactionStatus status) throws Exception {
+ rebuildInvoicesForAccountInTransaction(account, businessInvoices, transactional, context);
+
+ // Update balance, last invoice date and total invoice balance in BAC
+ final BusinessAccountSqlDao accountSqlDao = transactional.become(BusinessAccountSqlDao.class);
+ businessAccountDao.updateAccountInTransaction(bac, accountSqlDao, context);
+ return null;
+ }
+ });
+ }
+
+ // Used by BIP Recorder
+ public void rebuildInvoiceInTransaction(final String accountKey, final Invoice invoice,
+ final BusinessInvoiceSqlDao transactional, final InternalCallContext context) {
+ // Delete the invoice
+ transactional.deleteInvoice(invoice.getId().toString(), context);
+
+ // Re-create it - this will update the various amounts
+ transactional.createInvoice(new BusinessInvoiceModelDao(accountKey, invoice), context);
+ }
+
+ private void rebuildInvoicesForAccountInTransaction(final Account account, final Map<BusinessInvoiceModelDao, Collection<BusinessInvoiceItemModelDao>> businessInvoices,
+ final BusinessInvoiceSqlDao transactional, final InternalCallContext context) {
+ log.info("Started rebuilding invoices for account id {}", account.getId());
+ deleteInvoicesAndInvoiceItemsForAccountInTransaction(transactional, account.getId(), context);
+
+ for (final BusinessInvoiceModelDao businessInvoice : businessInvoices.keySet()) {
+ createInvoiceInTransaction(transactional, businessInvoice, businessInvoices.get(businessInvoice), context);
+ }
+
+ log.info("Finished rebuilding invoices for account id {}", account.getId());
+ }
+
+ private void deleteInvoicesAndInvoiceItemsForAccountInTransaction(final BusinessInvoiceSqlDao transactional,
+ final UUID accountId, final InternalCallContext context) {
+ // We don't use on cascade delete here as we don't want the database layer to be generic - hence we have
+ // to delete the invoice items manually.
+ // Note: invoice items should go first (see query)
+ final BusinessInvoiceItemSqlDao invoiceItemSqlDao = transactional.become(BusinessInvoiceItemSqlDao.class);
+ log.info("Deleting invoice items for account {}", accountId);
+ invoiceItemSqlDao.deleteInvoiceItemsForAccount(accountId.toString(), context);
+
+ log.info("Deleting invoices for account {}", accountId);
+ transactional.deleteInvoicesForAccount(accountId.toString(), context);
+ }
+
+ private void createInvoiceInTransaction(final BusinessInvoiceSqlDao transactional, final BusinessInvoiceModelDao invoice,
+ final Iterable<BusinessInvoiceItemModelDao> invoiceItems, final InternalCallContext context) {
+ // Create the invoice
+ log.info("Adding invoice {}", invoice);
+ transactional.createInvoice(invoice, context);
+
+ // Add associated invoice items
+ final BusinessInvoiceItemSqlDao invoiceItemSqlDao = transactional.become(BusinessInvoiceItemSqlDao.class);
+ for (final BusinessInvoiceItemModelDao invoiceItem : invoiceItems) {
+ log.info("Adding invoice item {}", invoiceItem);
+ invoiceItemSqlDao.createInvoiceItem(invoiceItem, context);
+ }
+ }
+
+ @VisibleForTesting
+ BusinessInvoiceItemModelDao createBusinessInvoiceItem(final InvoiceItem invoiceItem, final InternalTenantContext context) {
+ String externalKey = null;
+ Plan plan = null;
+ PlanPhase planPhase = null;
+
+ // Subscription and bundle could be null for e.g. credits or adjustments
+ if (invoiceItem.getBundleId() != null) {
+ try {
+ final SubscriptionBundle bundle = entitlementApi.getBundleFromId(invoiceItem.getBundleId(), context);
+ externalKey = bundle.getExternalKey();
+ } catch (EntitlementUserApiException e) {
+ log.warn("Ignoring subscription fields for invoice item {} for bundle {} (bundle does not exist)",
+ invoiceItem.getId().toString(),
+ invoiceItem.getBundleId().toString());
+ }
+ }
+
+ if (invoiceItem.getPlanName() != null) {
+ try {
+ plan = catalogService.getFullCatalog().findPlan(invoiceItem.getPlanName(), invoiceItem.getStartDate().toDateTimeAtStartOfDay());
+ } catch (CatalogApiException e) {
+ log.warn("Unable to retrieve plan for invoice item {}", invoiceItem.getId());
+ }
+ }
+
+ if (invoiceItem.getSubscriptionId() != null && invoiceItem.getPhaseName() != null) {
+ final Subscription subscription;
+ try {
+ subscription = entitlementApi.getSubscriptionFromId(invoiceItem.getSubscriptionId(), context);
+ planPhase = catalogService.getFullCatalog().findPhase(invoiceItem.getPhaseName(), invoiceItem.getStartDate().toDateTimeAtStartOfDay(), subscription.getStartDate());
+ } catch (EntitlementUserApiException e) {
+ log.warn("Ignoring subscription fields for invoice item {} for subscription {} (subscription does not exist)",
+ invoiceItem.getId().toString(),
+ invoiceItem.getSubscriptionId().toString());
+ } catch (CatalogApiException e) {
+ log.warn("Unable to retrieve phase for invoice item {}", invoiceItem.getId());
+ }
+ }
+
+ return new BusinessInvoiceItemModelDao(externalKey, invoiceItem, plan, planPhase);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoicePaymentDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoicePaymentDao.java
new file mode 100644
index 0000000..b39ad51
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessInvoicePaymentDao.java
@@ -0,0 +1,203 @@
+/*
+ * 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;
+
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.invoice.api.InvoicePayment;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.payment.api.Payment;
+import com.ning.billing.payment.api.PaymentApiException;
+import com.ning.billing.payment.api.PaymentMethod;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
+import com.ning.billing.util.svcapi.payment.PaymentInternalApi;
+
+public class BusinessInvoicePaymentDao {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessInvoicePaymentDao.class);
+
+ private final BusinessInvoicePaymentSqlDao invoicePaymentSqlDao;
+ private final AccountInternalApi accountApi;
+ private final InvoiceInternalApi invoiceApi;
+ private final PaymentInternalApi paymentApi;
+ private final Clock clock;
+ private final BusinessInvoiceDao invoiceDao;
+ private final BusinessAccountDao accountDao;
+
+ @Inject
+ public BusinessInvoicePaymentDao(final BusinessInvoicePaymentSqlDao invoicePaymentSqlDao, final AccountInternalApi accountApi,
+ final InvoiceInternalApi invoiceApi, final PaymentInternalApi paymentApi,
+ final Clock clock, final BusinessInvoiceDao invoiceDao, final BusinessAccountDao accountDao) {
+ this.invoicePaymentSqlDao = invoicePaymentSqlDao;
+ this.accountApi = accountApi;
+ this.invoiceApi = invoiceApi;
+ this.paymentApi = paymentApi;
+ this.clock = clock;
+ this.invoiceDao = invoiceDao;
+ this.accountDao = accountDao;
+ }
+
+ public void invoicePaymentPosted(final UUID accountId, @Nullable final UUID paymentId, final String message, final InternalCallContext context) {
+ // Payment attempt with no default payment method. Ignore.
+ if (paymentId == null) {
+ return;
+ }
+
+ final Account account;
+ try {
+ account = accountApi.getAccountById(accountId, context);
+ } catch (AccountApiException e) {
+ log.warn("Ignoring payment {}: account {} does not exist", paymentId, accountId);
+ return;
+ }
+
+ final Payment payment;
+ try {
+ payment = paymentApi.getPayment(paymentId, context);
+ } catch (PaymentApiException e) {
+ log.warn("Ignoring payment {}: payment does not exist", paymentId);
+ return;
+ }
+
+ PaymentMethod paymentMethod = null;
+ try {
+ paymentMethod = paymentApi.getPaymentMethodById(payment.getPaymentMethodId(), context);
+ } catch (PaymentApiException e) {
+ log.info("For payment {}: payment method {} does not exist", paymentId, payment.getPaymentMethodId());
+ }
+
+ Invoice invoice = null;
+ InvoicePayment invoicePayment = null;
+ try {
+ invoicePayment = invoiceApi.getInvoicePaymentForAttempt(paymentId, context);
+ if (invoicePayment != null) {
+ invoice = invoiceApi.getInvoiceById(invoicePayment.getInvoiceId(), context);
+ }
+ } catch (InvoiceApiException e) {
+ log.warn("Unable to find invoice {} for payment {}",
+ invoicePayment != null ? invoicePayment.getInvoiceId() : "unknown", paymentId);
+ }
+
+ createPayment(account, invoice, invoicePayment, payment, paymentMethod, message, context);
+ }
+
+ private void createPayment(final Account account, @Nullable final Invoice invoice, @Nullable final InvoicePayment invoicePayment, final Payment payment,
+ @Nullable final PaymentMethod paymentMethod,
+ final String message, final InternalCallContext context) {
+ // paymentMethod may be null if the payment method has been deleted
+ final String cardCountry;
+ final String cardType;
+ final String paymentMethodString;
+ if (paymentMethod != null) {
+ final PaymentMethodPlugin pluginDetail = paymentMethod.getPluginDetail();
+ cardCountry = PaymentMethodUtils.getCardCountry(pluginDetail);
+ cardType = PaymentMethodUtils.getCardType(pluginDetail);
+ paymentMethodString = PaymentMethodUtils.getPaymentMethodType(pluginDetail);
+ } else {
+ cardCountry = null;
+ cardType = null;
+ paymentMethodString = null;
+ }
+
+ // invoicePayment may be null on payment failures
+ final String invoicePaymentType;
+ final UUID linkedInvoicePaymentId;
+ final DateTime createdDate;
+ final DateTime updatedDate;
+ if (invoicePayment != null) {
+ invoicePaymentType = invoicePayment.getType().toString();
+ linkedInvoicePaymentId = invoicePayment.getLinkedInvoicePaymentId();
+ createdDate = invoicePayment.getCreatedDate();
+ updatedDate = invoicePayment.getUpdatedDate();
+ } else {
+ invoicePaymentType = null;
+ linkedInvoicePaymentId = null;
+ // TODO PIERRE
+ createdDate = clock.getUTCNow();
+ updatedDate = createdDate;
+ }
+
+ final BusinessInvoicePaymentModelDao businessInvoicePayment = new BusinessInvoicePaymentModelDao(
+ account.getExternalKey(),
+ payment.getAmount(),
+ cardCountry,
+ cardType,
+ createdDate,
+ payment.getCurrency(),
+ payment.getEffectiveDate(),
+ payment.getInvoiceId(),
+ message,
+ payment.getId(),
+ paymentMethodString,
+ "Electronic",
+ paymentMethod == null ? null : paymentMethod.getPluginName(),
+ payment.getPaymentStatus().toString(),
+ payment.getAmount(),
+ updatedDate,
+ invoicePaymentType,
+ linkedInvoicePaymentId);
+
+ // Update the account record
+ final BusinessAccountModelDao bac = accountDao.createBusinessAccountFromAccount(account, context);
+
+ // Make sure to limit the scope of the transaction to avoid InnoDB deadlocks
+ invoicePaymentSqlDao.inTransaction(new Transaction<Void, BusinessInvoicePaymentSqlDao>() {
+ @Override
+ public Void inTransaction(final BusinessInvoicePaymentSqlDao transactional, final TransactionStatus status) throws Exception {
+ // Delete the existing payment if it exists - this is to make the call idempotent
+ transactional.deleteInvoicePayment(payment.getId().toString(), context);
+
+ // Create the bip record
+ transactional.createInvoicePayment(businessInvoicePayment, context);
+
+ if (invoice != null) {
+ // Update bin to get the latest invoice balance
+ final BusinessInvoiceSqlDao invoiceSqlDao = transactional.become(BusinessInvoiceSqlDao.class);
+ invoiceDao.rebuildInvoiceInTransaction(account.getExternalKey(), invoice, invoiceSqlDao, context);
+ }
+
+ // Update bac to get the latest account balance, total invoice balance, etc.
+ final BusinessAccountSqlDao accountSqlDao = transactional.become(BusinessAccountSqlDao.class);
+ accountDao.updateAccountInTransaction(bac, accountSqlDao, context);
+
+ log.info("Added payment {}", businessInvoicePayment);
+ return null;
+ }
+ });
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessOverdueStatusDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessOverdueStatusDao.java
new file mode 100644
index 0000000..16a8303
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessOverdueStatusDao.java
@@ -0,0 +1,120 @@
+/*
+ * 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;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessOverdueStatusSqlDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
+import com.ning.billing.util.svcapi.junction.BlockingInternalApi;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+public class BusinessOverdueStatusDao {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessOverdueStatusDao.class);
+
+ private final BusinessOverdueStatusSqlDao overdueStatusSqlDao;
+
+ private final AccountInternalApi accountApi;
+ private final EntitlementInternalApi entitlementApi;
+ private final BlockingInternalApi blockingApi;
+
+ @Inject
+ public BusinessOverdueStatusDao(final BusinessOverdueStatusSqlDao overdueStatusSqlDao, final AccountInternalApi accountApi,
+ final EntitlementInternalApi entitlementApi, final BlockingInternalApi blockingApi) {
+
+ this.overdueStatusSqlDao = overdueStatusSqlDao;
+ this.accountApi = accountApi;
+ this.entitlementApi = entitlementApi;
+ this.blockingApi = blockingApi;
+ }
+
+ public void overdueStatusChanged(final Blockable.Type objectType, final UUID objectId, final InternalCallContext context) {
+ if (Blockable.Type.SUBSCRIPTION_BUNDLE.equals(objectType)) {
+ overdueStatusChangedForBundle(objectId, context);
+ } else {
+ log.info("Ignoring overdue status change for object id {} (type {})", objectId.toString(), objectType.toString());
+ }
+ }
+
+ private void overdueStatusChangedForBundle(final UUID bundleId, final InternalCallContext context) {
+ final SubscriptionBundle bundle;
+ try {
+ bundle = entitlementApi.getBundleFromId(bundleId, context);
+ } catch (EntitlementUserApiException e) {
+ log.warn("Ignoring update for bundle {}: bundle does not exist", bundleId);
+ return;
+ }
+
+ final Account account;
+ try {
+ account = accountApi.getAccountById(bundle.getAccountId(), context);
+ } catch (AccountApiException e) {
+ log.warn("Ignoring update for bundle {}: account {} does not exist", bundleId, bundle.getAccountId());
+ return;
+ }
+
+ final String accountKey = account.getExternalKey();
+ final String externalKey = bundle.getExternalKey();
+
+ overdueStatusSqlDao.inTransaction(new Transaction<Void, BusinessOverdueStatusSqlDao>() {
+ @Override
+ public Void inTransaction(final BusinessOverdueStatusSqlDao transactional, final TransactionStatus status) throws Exception {
+ log.info("Started rebuilding overdue statuses for bundle id {}", bundleId);
+ transactional.deleteOverdueStatusesForBundle(bundleId.toString(), context);
+ final List<BlockingState> blockingHistory = blockingApi.getBlockingHistory(bundleId, context);
+ if (blockingHistory != null && blockingHistory.size() > 0) {
+ final List<BlockingState> overdueStates = ImmutableList.<BlockingState>copyOf(blockingHistory);
+ final List<BlockingState> overdueStatesReversed = Lists.reverse(overdueStates);
+
+ DateTime previousStartDate = null;
+ for (final BlockingState state : overdueStatesReversed) {
+ final BusinessOverdueStatusModelDao overdueStatus = new BusinessOverdueStatusModelDao(accountKey, bundleId, previousStartDate,
+ externalKey, state.getTimestamp(), state.getStateName());
+ log.info("Adding overdue state {}", overdueStatus);
+ overdueStatusSqlDao.createOverdueStatus(overdueStatus, context);
+
+ previousStartDate = state.getTimestamp();
+ }
+ }
+
+ log.info("Finished rebuilding overdue statuses for bundle id {}", bundleId);
+ return null;
+ }
+ });
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessSubscriptionTransitionDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessSubscriptionTransitionDao.java
new file mode 100644
index 0000000..cdf110f
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessSubscriptionTransitionDao.java
@@ -0,0 +1,261 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionSqlDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscription;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionEvent;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.events.EffectiveSubscriptionInternalEvent;
+import com.ning.billing.util.events.SubscriptionInternalEvent;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
+
+import com.google.inject.Inject;
+
+public class BusinessSubscriptionTransitionDao {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessSubscriptionTransitionDao.class);
+
+ private final BusinessSubscriptionTransitionSqlDao sqlDao;
+ private final EntitlementInternalApi entitlementApi;
+ private final AccountInternalApi accountApi;
+ private final CatalogService catalogService;
+
+ @Inject
+ public BusinessSubscriptionTransitionDao(final BusinessSubscriptionTransitionSqlDao sqlDao,
+ final CatalogService catalogService,
+ final EntitlementInternalApi entitlementApi,
+ final AccountInternalApi accountApi) {
+ this.sqlDao = sqlDao;
+ this.catalogService = catalogService;
+ this.entitlementApi = entitlementApi;
+ this.accountApi = accountApi;
+ }
+
+ public void rebuildTransitionsForBundle(final UUID bundleId, final InternalCallContext context) {
+ final SubscriptionBundle bundle;
+ try {
+ bundle = entitlementApi.getBundleFromId(bundleId, context);
+ } catch (EntitlementUserApiException e) {
+ log.warn("Ignoring update for bundle {}: bundle does not exist", bundleId);
+ return;
+ }
+
+ final Account account;
+ try {
+ account = accountApi.getAccountById(bundle.getAccountId(), context);
+ } catch (AccountApiException e) {
+ log.warn("Ignoring update for bundle {}: account {} does not exist", bundleId, bundle.getAccountId());
+ return;
+ }
+
+ final List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(bundleId, context);
+
+ final Currency currency = account.getCurrency();
+
+ sqlDao.inTransaction(new Transaction<Void, BusinessSubscriptionTransitionSqlDao>() {
+ @Override
+ public Void inTransaction(final BusinessSubscriptionTransitionSqlDao transactional, final TransactionStatus status) throws Exception {
+ log.info("Started rebuilding transitions for bundle id {}", bundleId);
+ transactional.deleteTransitionsForBundle(bundleId.toString(), context);
+
+ final ArrayList<BusinessSubscriptionTransitionModelDao> transitions = new ArrayList<BusinessSubscriptionTransitionModelDao>();
+ for (final Subscription subscription : subscriptions) {
+ // TODO remove API call from within transaction, although this is NOT a real issue as this call wil not hit the DB
+ for (final EffectiveSubscriptionInternalEvent event : entitlementApi.getAllTransitions(subscription, context)) {
+ final BusinessSubscriptionEvent businessEvent = getBusinessSubscriptionFromEvent(event);
+ if (businessEvent == null) {
+ continue;
+ }
+
+ final BusinessSubscription prevSubscription = createPreviousBusinessSubscription(event, businessEvent, transitions, currency);
+ final BusinessSubscription nextSubscription = createNextBusinessSubscription(event, businessEvent, currency);
+ final BusinessSubscriptionTransitionModelDao transition = new BusinessSubscriptionTransitionModelDao(
+ event.getTotalOrdering(),
+ bundleId,
+ bundle.getExternalKey(),
+ bundle.getAccountId(),
+ account.getExternalKey(),
+ subscription.getId(),
+ event.getRequestedTransitionTime(),
+ businessEvent,
+ prevSubscription,
+ nextSubscription
+ );
+
+ transactional.createTransition(transition, context);
+ transitions.add(transition);
+ log.info("Adding transition {}", transition);
+
+ // We need to manually add the system cancel event
+ if (SubscriptionTransitionType.CANCEL.equals(event.getTransitionType())) {
+ final BusinessSubscriptionTransitionModelDao systemCancelTransition = new BusinessSubscriptionTransitionModelDao(
+ event.getTotalOrdering(),
+ bundleId,
+ bundle.getExternalKey(),
+ bundle.getAccountId(),
+ account.getExternalKey(),
+ subscription.getId(),
+ // Note! The system cancel event requested time is the effective time when the subscription
+ // is cancelled, which is the effective time of the cancel event
+ event.getEffectiveTransitionTime(),
+ new BusinessSubscriptionEvent(BusinessSubscriptionEvent.EventType.SYSTEM_CANCEL, businessEvent.getCategory()),
+ prevSubscription,
+ nextSubscription
+ );
+ transactional.createTransition(systemCancelTransition, context);
+ transitions.add(systemCancelTransition);
+ log.info("Adding transition {}", systemCancelTransition);
+ }
+ }
+ }
+
+ log.info("Finished rebuilding transitions for bundle id {}", bundleId);
+ return null;
+ }
+ });
+ }
+
+ private BusinessSubscriptionEvent getBusinessSubscriptionFromEvent(final SubscriptionInternalEvent event) throws AccountApiException, EntitlementUserApiException {
+ switch (event.getTransitionType()) {
+ // A subscription enters either through migration or as newly created subscription
+ case MIGRATE_ENTITLEMENT:
+ return subscriptionMigrated(event);
+ case CREATE:
+ return subscriptionCreated(event);
+ case RE_CREATE:
+ return subscriptionRecreated(event);
+ case TRANSFER:
+ return subscriptionTransfered(event);
+ case CANCEL:
+ return subscriptionCancelled(event);
+ case CHANGE:
+ return subscriptionChanged(event);
+ case PHASE:
+ return subscriptionPhaseChanged(event);
+ // TODO - should we really ignore these?
+ case MIGRATE_BILLING:
+ case UNCANCEL:
+ return null;
+ default:
+ log.warn("Unexpected event type " + event.getTransitionType());
+ return null;
+ }
+ }
+
+ private BusinessSubscriptionEvent subscriptionMigrated(final SubscriptionInternalEvent created) throws AccountApiException, EntitlementUserApiException {
+ return BusinessSubscriptionEvent.subscriptionMigrated(created.getNextPlan(), catalogService.getFullCatalog(), created.getEffectiveTransitionTime(), created.getSubscriptionStartDate());
+ }
+
+ private BusinessSubscriptionEvent subscriptionCreated(final SubscriptionInternalEvent created) throws AccountApiException, EntitlementUserApiException {
+ return BusinessSubscriptionEvent.subscriptionCreated(created.getNextPlan(), catalogService.getFullCatalog(), created.getEffectiveTransitionTime(), created.getSubscriptionStartDate());
+ }
+
+ private BusinessSubscriptionEvent subscriptionRecreated(final SubscriptionInternalEvent recreated) throws AccountApiException, EntitlementUserApiException {
+ return BusinessSubscriptionEvent.subscriptionRecreated(recreated.getNextPlan(), catalogService.getFullCatalog(), recreated.getEffectiveTransitionTime(), recreated.getSubscriptionStartDate());
+ }
+
+ private BusinessSubscriptionEvent subscriptionTransfered(final SubscriptionInternalEvent transfered) throws AccountApiException, EntitlementUserApiException {
+ return BusinessSubscriptionEvent.subscriptionTransfered(transfered.getNextPlan(), catalogService.getFullCatalog(), transfered.getEffectiveTransitionTime(), transfered.getSubscriptionStartDate());
+ }
+
+ private BusinessSubscriptionEvent subscriptionCancelled(final SubscriptionInternalEvent cancelled) throws AccountApiException, EntitlementUserApiException {
+ // cancelled.getNextPlan() is null here - need to look at the previous one to create the correct event name
+ return BusinessSubscriptionEvent.subscriptionCancelled(cancelled.getPreviousPlan(), catalogService.getFullCatalog(), cancelled.getEffectiveTransitionTime(), cancelled.getSubscriptionStartDate());
+ }
+
+ private BusinessSubscriptionEvent subscriptionChanged(final SubscriptionInternalEvent changed) throws AccountApiException, EntitlementUserApiException {
+ return BusinessSubscriptionEvent.subscriptionChanged(changed.getNextPlan(), catalogService.getFullCatalog(), changed.getEffectiveTransitionTime(), changed.getSubscriptionStartDate());
+ }
+
+ private BusinessSubscriptionEvent subscriptionPhaseChanged(final SubscriptionInternalEvent phaseChanged) throws AccountApiException, EntitlementUserApiException {
+ return BusinessSubscriptionEvent.subscriptionPhaseChanged(phaseChanged.getNextPlan(), phaseChanged.getNextState(), catalogService.getFullCatalog(), phaseChanged.getEffectiveTransitionTime(), phaseChanged.getSubscriptionStartDate());
+ }
+
+ private BusinessSubscription createNextBusinessSubscription(final EffectiveSubscriptionInternalEvent event, final BusinessSubscriptionEvent businessEvent, final Currency currency) {
+ final BusinessSubscription nextSubscription;
+ if (BusinessSubscriptionEvent.EventType.CANCEL.equals(businessEvent.getEventType()) ||
+ BusinessSubscriptionEvent.EventType.SYSTEM_CANCEL.equals(businessEvent.getEventType())) {
+ nextSubscription = null;
+ } else {
+ nextSubscription = new BusinessSubscription(event.getNextPriceList(), event.getNextPlan(), event.getNextPhase(),
+ currency, event.getEffectiveTransitionTime(), event.getNextState(),
+ catalogService.getFullCatalog());
+ }
+
+ return nextSubscription;
+ }
+
+ private BusinessSubscription createPreviousBusinessSubscription(final EffectiveSubscriptionInternalEvent event,
+ final BusinessSubscriptionEvent businessEvent,
+ final ArrayList<BusinessSubscriptionTransitionModelDao> transitions,
+ final Currency currency) {
+ if (BusinessSubscriptionEvent.EventType.MIGRATE.equals(businessEvent.getEventType()) ||
+ BusinessSubscriptionEvent.EventType.ADD.equals(businessEvent.getEventType()) ||
+ BusinessSubscriptionEvent.EventType.RE_ADD.equals(businessEvent.getEventType()) ||
+ BusinessSubscriptionEvent.EventType.TRANSFER.equals(businessEvent.getEventType())) {
+ return null;
+ }
+
+ final BusinessSubscriptionTransitionModelDao prevTransition = getPreviousBusinessSubscriptionTransitionForEvent(event, transitions);
+ return new BusinessSubscription(event.getPreviousPriceList(), event.getPreviousPlan(), event.getPreviousPhase(),
+ currency, prevTransition.getNextSubscription().getStartDate(), event.getPreviousState(),
+ catalogService.getFullCatalog());
+ }
+
+ private BusinessSubscriptionTransitionModelDao getPreviousBusinessSubscriptionTransitionForEvent(final EffectiveSubscriptionInternalEvent event,
+ final ArrayList<BusinessSubscriptionTransitionModelDao> transitions) {
+ BusinessSubscriptionTransitionModelDao transition = null;
+ for (final BusinessSubscriptionTransitionModelDao candidate : transitions) {
+ final BusinessSubscription nextSubscription = candidate.getNextSubscription();
+ if (nextSubscription == null || !nextSubscription.getStartDate().isBefore(event.getEffectiveTransitionTime())) {
+ continue;
+ }
+
+ if (candidate.getSubscriptionId().equals(event.getSubscriptionId())) {
+ transition = candidate;
+ }
+ }
+
+ if (transition == null) {
+ log.error("Unable to retrieve the previous transition - THIS SHOULD NEVER HAPPEN");
+ // Fall back to the latest one?
+ transition = transitions.get(transitions.size() - 1);
+ }
+
+ return transition;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessTagDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessTagDao.java
new file mode 100644
index 0000000..66bccd4
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/BusinessTagDao.java
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionTagSqlDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
+
+public class BusinessTagDao {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessTagDao.class);
+
+ private final BusinessAccountTagSqlDao accountTagSqlDao;
+ private final BusinessInvoiceTagSqlDao invoiceTagSqlDao;
+ private final BusinessInvoicePaymentTagSqlDao invoicePaymentTagSqlDao;
+ private final BusinessSubscriptionTransitionTagSqlDao subscriptionTransitionTagSqlDao;
+ private final AccountInternalApi accountApi;
+ private final EntitlementInternalApi entitlementApi;
+
+ @Inject
+ public BusinessTagDao(final BusinessAccountTagSqlDao accountTagSqlDao,
+ final BusinessInvoicePaymentTagSqlDao invoicePaymentTagSqlDao,
+ final BusinessInvoiceTagSqlDao invoiceTagSqlDao,
+ final BusinessSubscriptionTransitionTagSqlDao subscriptionTransitionTagSqlDao,
+ final AccountInternalApi accountApi,
+ final EntitlementInternalApi entitlementApi) {
+ this.accountTagSqlDao = accountTagSqlDao;
+ this.invoicePaymentTagSqlDao = invoicePaymentTagSqlDao;
+ this.invoiceTagSqlDao = invoiceTagSqlDao;
+ this.subscriptionTransitionTagSqlDao = subscriptionTransitionTagSqlDao;
+ this.accountApi = accountApi;
+ this.entitlementApi = entitlementApi;
+ }
+
+ public void tagAdded(final ObjectType objectType, final UUID objectId, final String name, final InternalCallContext context) {
+ if (objectType.equals(ObjectType.ACCOUNT)) {
+ tagAddedForAccount(objectId, name, context);
+ } else if (objectType.equals(ObjectType.BUNDLE)) {
+ tagAddedForBundle(objectId, name, context);
+ } else if (objectType.equals(ObjectType.INVOICE)) {
+ tagAddedForInvoice(objectId, name, context);
+ } else if (objectType.equals(ObjectType.PAYMENT)) {
+ tagAddedForPayment(objectId, name, context);
+ } else {
+ log.info("Ignoring tag addition of {} for object id {} (type {})", new Object[]{name, objectId.toString(), objectType.toString()});
+ }
+ }
+
+ public void tagRemoved(final ObjectType objectType, final UUID objectId, final String name, final InternalCallContext context) {
+ if (objectType.equals(ObjectType.ACCOUNT)) {
+ tagRemovedForAccount(objectId, name, context);
+ } else if (objectType.equals(ObjectType.BUNDLE)) {
+ tagRemovedForBundle(objectId, name, context);
+ } else if (objectType.equals(ObjectType.INVOICE)) {
+ tagRemovedForInvoice(objectId, name, context);
+ } else if (objectType.equals(ObjectType.PAYMENT)) {
+ tagRemovedForPayment(objectId, name, context);
+ } else {
+ log.info("Ignoring tag removal of {} for object id {} (type {})", new Object[]{name, objectId.toString(), objectType.toString()});
+ }
+ }
+
+ private void tagAddedForAccount(final UUID accountId, final String name, final InternalCallContext context) {
+ final Account account;
+ try {
+ account = accountApi.getAccountById(accountId, context);
+ } catch (AccountApiException e) {
+ log.warn("Ignoring tag addition of {} for account id {} (account does not exist)", name, accountId.toString());
+ return;
+ }
+
+ final String accountKey = account.getExternalKey();
+ accountTagSqlDao.addTag(accountId.toString(), accountKey, name, context);
+ }
+
+ private void tagRemovedForAccount(final UUID accountId, final String name, final InternalCallContext context) {
+ accountTagSqlDao.removeTag(accountId.toString(), name, context);
+ }
+
+ private void tagAddedForBundle(final UUID bundleId, final String name, final InternalCallContext context) {
+ final SubscriptionBundle bundle;
+ try {
+ bundle = entitlementApi.getBundleFromId(bundleId, context);
+ } catch (EntitlementUserApiException e) {
+ log.warn("Ignoring tag addition of {} for bundle id {} (bundle does not exist)", name, bundleId.toString());
+ return;
+ }
+
+ final Account account;
+ try {
+ account = accountApi.getAccountById(bundle.getAccountId(), context);
+ } catch (AccountApiException e) {
+ log.warn("Ignoring tag addition of {} for bundle id {} and account id {} (account does not exist)", new Object[]{name, bundleId.toString(), bundle.getAccountId()});
+ return;
+ }
+
+ /*
+ * Note: we store tags associated to bundles, not to subscriptions.
+ */
+ final String accountKey = account.getExternalKey();
+ final String externalKey = bundle.getExternalKey();
+ subscriptionTransitionTagSqlDao.addTag(accountKey, bundleId.toString(), externalKey, name, context);
+ }
+
+ private void tagRemovedForBundle(final UUID bundleId, final String name, final InternalCallContext context) {
+ subscriptionTransitionTagSqlDao.removeTag(bundleId.toString(), name, context);
+ }
+
+ private void tagAddedForInvoice(final UUID objectId, final String name, final InternalCallContext context) {
+ invoiceTagSqlDao.addTag(objectId.toString(), name, context);
+ }
+
+ private void tagRemovedForInvoice(final UUID objectId, final String name, final InternalCallContext context) {
+ invoiceTagSqlDao.removeTag(objectId.toString(), name, context);
+ }
+
+ private void tagAddedForPayment(final UUID objectId, final String name, final InternalCallContext context) {
+ invoicePaymentTagSqlDao.addTag(objectId.toString(), name, context);
+ }
+
+ private void tagRemovedForPayment(final UUID objectId, final String name, final InternalCallContext context) {
+ invoicePaymentTagSqlDao.removeTag(objectId.toString(), name, context);
+ }
+}
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
new file mode 100644
index 0000000..0541d46
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsDao.java
@@ -0,0 +1,52 @@
+/*
+ * 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.util.List;
+
+import com.ning.billing.analytics.api.TimeSeriesData;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+
+public interface AnalyticsDao {
+
+ TimeSeriesData getAccountsCreatedOverTime(InternalTenantContext context);
+
+ TimeSeriesData getSubscriptionsCreatedOverTime(String productType, String slug, InternalTenantContext context);
+
+ BusinessAccountModelDao getAccountByKey(String accountKey, InternalTenantContext context);
+
+ List<BusinessSubscriptionTransitionModelDao> getTransitionsByKey(String externalKey, InternalTenantContext context);
+
+ List<BusinessSubscriptionTransitionModelDao> getTransitionsForAccount(String accountKey, InternalTenantContext context);
+
+ List<BusinessInvoiceModelDao> getInvoicesByKey(String accountKey, InternalTenantContext context);
+
+ List<BusinessInvoiceItemModelDao> getInvoiceItemsForInvoice(String invoiceId, InternalTenantContext context);
+
+ List<BusinessInvoicePaymentModelDao> getInvoicePaymentsForAccountByKey(String accountKey, InternalTenantContext context);
+
+ List<BusinessOverdueStatusModelDao> getOverdueStatusesForBundleByKey(String externalKey, InternalTenantContext context);
+
+ List<BusinessAccountTagModelDao> getTagsForAccount(String accountKey, InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanityDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanityDao.java
new file mode 100644
index 0000000..8d5e177
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanityDao.java
@@ -0,0 +1,43 @@
+/*
+ * 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.util.Collection;
+import java.util.UUID;
+
+import com.ning.billing.util.callcontext.InternalTenantContext;
+
+public interface AnalyticsSanityDao {
+
+ public Collection<UUID> checkBstMatchesSubscriptionEvents(InternalTenantContext context);
+
+ public Collection<UUID> checkBiiMatchesInvoiceItems(InternalTenantContext context);
+
+ public Collection<UUID> checkBipMatchesInvoicePayments(InternalTenantContext context);
+
+ public Collection<UUID> checkBinAmountPaidMatchesInvoicePayments(InternalTenantContext context);
+
+ public Collection<UUID> checkBinAmountChargedMatchesInvoicePayments(InternalTenantContext context);
+
+ public Collection<UUID> checkBinBiiBalanceConsistency(InternalTenantContext context);
+
+ public Collection<UUID> checkBinBiiAmountCreditedConsistency(InternalTenantContext context);
+
+ public Collection<UUID> checkBacBinBiiConsistency(InternalTenantContext context);
+
+ public Collection<UUID> checkBacTagsMatchesTags(InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.java
new file mode 100644
index 0000000..dcc1b12
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.java
@@ -0,0 +1,62 @@
+/*
+ * 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.util.Collection;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+import com.ning.billing.util.dao.UuidMapper;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(UuidMapper.class)
+public interface AnalyticsSanitySqlDao extends Transactional<AnalyticsSanitySqlDao>, Transmogrifier {
+
+ @SqlQuery
+ public Collection<UUID> checkBstMatchesSubscriptionEvents(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBiiMatchesInvoiceItems(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBipMatchesInvoicePayments(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBinAmountPaidMatchesInvoicePayments(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBinAmountChargedMatchesInvoicePayments(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBinBiiBalanceConsistency(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBinBiiAmountCreditedConsistency(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBacBinBiiConsistency(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ public Collection<UUID> checkBacTagsMatchesTags(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountBinder.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountBinder.java
new file mode 100644
index 0000000..d0356d1
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountBinder.java
@@ -0,0 +1,78 @@
+/*
+ * 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.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.Types;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+
+@BindingAnnotation(BusinessAccountBinder.BacBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface BusinessAccountBinder {
+
+ public static class BacBinderFactory implements BinderFactory {
+
+ public Binder build(final Annotation annotation) {
+ return new Binder<BusinessAccountBinder, BusinessAccountModelDao>() {
+ public void bind(final SQLStatement q, final BusinessAccountBinder bind, final BusinessAccountModelDao account) {
+ final DateTime dateTimeNow = new DateTime(DateTimeZone.UTC);
+
+ if (account.getCreatedDate() != null) {
+ q.bind("created_date", account.getCreatedDate().getMillis());
+ } else {
+ q.bind("created_date", dateTimeNow.getMillis());
+ }
+
+ if (account.getUpdatedDate() != null) {
+ q.bind("updated_date", account.getUpdatedDate().getMillis());
+ } else {
+ q.bind("updated_date", dateTimeNow.getMillis());
+ }
+
+ q.bind("account_id", account.getAccountId().toString());
+ q.bind("account_key", account.getKey());
+ q.bind("balance", account.getRoundedBalance());
+ q.bind("name", account.getName());
+ if (account.getLastInvoiceDate() != null) {
+ q.bind("last_invoice_date", account.getLastInvoiceDate().toDate());
+ } else {
+ q.bindNull("last_invoice_date", Types.DATE);
+ }
+ q.bind("total_invoice_balance", account.getRoundedTotalInvoiceBalance());
+ q.bind("last_payment_status", account.getLastPaymentStatus());
+ q.bind("payment_method", account.getPaymentMethod());
+ q.bind("credit_card_type", account.getCreditCardType());
+ q.bind("billing_address_country", account.getBillingAddressCountry());
+ q.bind("currency", account.getCurrency());
+ }
+ };
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldMapper.java
new file mode 100644
index 0000000..d59636c
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldMapper.java
@@ -0,0 +1,38 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountFieldModelDao;
+
+public class BusinessAccountFieldMapper implements ResultSetMapper<BusinessAccountFieldModelDao> {
+
+ @Override
+ public BusinessAccountFieldModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID accountId = UUID.fromString(r.getString(1));
+ final String accountKey = r.getString(2);
+ final String name = r.getString(3);
+ final String value = r.getString(4);
+ return new BusinessAccountFieldModelDao(accountId, accountKey, name, value);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.java
new file mode 100644
index 0000000..c2a0b9d
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountFieldModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessAccountFieldMapper.class)
+public interface BusinessAccountFieldSqlDao {
+
+ @SqlQuery
+ List<BusinessAccountFieldModelDao> getFieldsForAccountByKey(@Bind("account_key") final String accountKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addField(@Bind("account_id") final String accountId,
+ @Bind("account_key") final String accountKey,
+ @Bind("name") final String name,
+ @Bind("value") final String value,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeField(@Bind("account_id") final String accountId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountMapper.java
new file mode 100644
index 0000000..d0b1b9a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountMapper.java
@@ -0,0 +1,52 @@
+/*
+ * 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 java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.util.dao.MapperBase;
+
+public class BusinessAccountMapper extends MapperBase implements ResultSetMapper<BusinessAccountModelDao> {
+
+ @Override
+ public BusinessAccountModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ return new BusinessAccountModelDao(
+ UUID.fromString(r.getString(1)),
+ r.getString(2),
+ r.getString(6),
+ BigDecimal.valueOf(r.getDouble(5)),
+ getDate(r, "last_invoice_date"),
+ BigDecimal.valueOf(r.getDouble(8)),
+ r.getString(9),
+ r.getString(10),
+ r.getString(11),
+ r.getString(12),
+ r.getString(13),
+ new DateTime(r.getLong(3), DateTimeZone.UTC),
+ new DateTime(r.getLong(4), DateTimeZone.UTC)
+ );
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.java
new file mode 100644
index 0000000..b17cc54
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.java
@@ -0,0 +1,63 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper({BusinessAccountMapper.class, TimeSeriesTupleMapper.class})
+public interface BusinessAccountSqlDao extends Transactional<BusinessAccountSqlDao>, Transmogrifier {
+
+ @SqlQuery
+ List<TimeSeriesTuple> getAccountsCreatedOverTime(@InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ BusinessAccountModelDao getAccount(@Bind("account_id") final String accountId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ BusinessAccountModelDao getAccountByKey(@Bind("account_key") String accountKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int createAccount(@BusinessAccountBinder final BusinessAccountModelDao account,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int saveAccount(@BusinessAccountBinder final BusinessAccountModelDao account,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int deleteAccount(@Bind("account_id") final String accountId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagMapper.java
new file mode 100644
index 0000000..e698c69
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagMapper.java
@@ -0,0 +1,37 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountTagModelDao;
+
+public class BusinessAccountTagMapper implements ResultSetMapper<BusinessAccountTagModelDao> {
+
+ @Override
+ public BusinessAccountTagModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID accountId = UUID.fromString(r.getString(1));
+ final String accountKey = r.getString(2);
+ final String name = r.getString(3);
+ return new BusinessAccountTagModelDao(accountId, accountKey, name);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.java
new file mode 100644
index 0000000..68dce2a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.java
@@ -0,0 +1,53 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountTagModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessAccountTagMapper.class)
+public interface BusinessAccountTagSqlDao {
+
+ @SqlQuery
+ List<BusinessAccountTagModelDao> getTagsForAccountByKey(@Bind("account_key") final String accountKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addTag(@Bind("account_id") final String accountId,
+ @Bind("account_key") final String accountKey,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeTag(@Bind("account_id") final String accountId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceBinder.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceBinder.java
new file mode 100644
index 0000000..4c258f5
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceBinder.java
@@ -0,0 +1,91 @@
+/*
+ * 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.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.Types;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+
+@BindingAnnotation(BusinessInvoiceBinder.BinBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface BusinessInvoiceBinder {
+
+ public static class BinBinderFactory implements BinderFactory {
+
+ public Binder build(final Annotation annotation) {
+ return new Binder<BusinessInvoiceBinder, BusinessInvoiceModelDao>() {
+ public void bind(final SQLStatement q, final BusinessInvoiceBinder bind, final BusinessInvoiceModelDao invoice) {
+ q.bind("invoice_id", invoice.getInvoiceId().toString());
+
+ if (invoice.getInvoiceNumber() != null) {
+ q.bind("invoice_number", invoice.getInvoiceNumber());
+ } else {
+ q.bindNull("invoice_number", Types.BIGINT);
+ }
+
+ final DateTime dateTimeNow = new DateTime(DateTimeZone.UTC);
+ if (invoice.getCreatedDate() != null) {
+ q.bind("created_date", invoice.getCreatedDate().getMillis());
+ } else {
+ q.bind("created_date", dateTimeNow.getMillis());
+ }
+
+ if (invoice.getUpdatedDate() != null) {
+ q.bind("updated_date", invoice.getUpdatedDate().getMillis());
+ } else {
+ q.bind("updated_date", dateTimeNow.getMillis());
+ }
+
+ q.bind("account_id", invoice.getAccountId().toString());
+ q.bind("account_key", invoice.getAccountKey());
+
+ if (invoice.getInvoiceDate() != null) {
+ q.bind("invoice_date", invoice.getInvoiceDate().toDate());
+ } else {
+ q.bindNull("invoice_date", Types.DATE);
+ }
+
+ if (invoice.getTargetDate() != null) {
+ q.bind("target_date", invoice.getTargetDate().toDate());
+ } else {
+ q.bindNull("target_date", Types.DATE);
+ }
+
+ q.bind("currency", invoice.getCurrency().toString());
+ q.bind("balance", Rounder.round(invoice.getBalance()));
+ q.bind("amount_paid", Rounder.round(invoice.getAmountPaid()));
+ q.bind("amount_charged", Rounder.round(invoice.getAmountCharged()));
+ q.bind("amount_credited", Rounder.round(invoice.getAmountCredited()));
+ }
+ };
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldMapper.java
new file mode 100644
index 0000000..edcf683
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldMapper.java
@@ -0,0 +1,34 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceFieldModelDao;
+
+public class BusinessInvoiceFieldMapper implements ResultSetMapper<BusinessInvoiceFieldModelDao> {
+
+ @Override
+ public BusinessInvoiceFieldModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ return new BusinessInvoiceFieldModelDao(UUID.fromString(r.getString(1)), r.getString(2), r.getString(3));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.java
new file mode 100644
index 0000000..1796169
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.java
@@ -0,0 +1,53 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceFieldModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessInvoiceFieldMapper.class)
+public interface BusinessInvoiceFieldSqlDao {
+
+ @SqlQuery
+ List<BusinessInvoiceFieldModelDao> getFieldsForInvoice(@Bind("invoice_id") final String invoiceId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addField(@Bind("invoice_id") final String invoiceId,
+ @Bind("name") final String name,
+ @Bind("value") final String value,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeField(@Bind("invoice_id") final String invoiceId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemBinder.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemBinder.java
new file mode 100644
index 0000000..8563d8b
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemBinder.java
@@ -0,0 +1,94 @@
+/*
+ * 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.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.Types;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+
+@BindingAnnotation(BusinessInvoiceItemBinder.BiiBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface BusinessInvoiceItemBinder {
+
+ public static class BiiBinderFactory implements BinderFactory {
+
+ public Binder build(final Annotation annotation) {
+ return new Binder<BusinessInvoiceItemBinder, BusinessInvoiceItemModelDao>() {
+ public void bind(final SQLStatement q, final BusinessInvoiceItemBinder bind, final BusinessInvoiceItemModelDao invoiceItem) {
+ q.bind("item_id", invoiceItem.getItemId().toString());
+ if (invoiceItem.getLinkedItemId() != null) {
+ q.bind("linked_item_id", invoiceItem.getLinkedItemId().toString());
+ } else {
+ q.bindNull("linked_item_id", Types.VARCHAR);
+ }
+
+ final DateTime dateTimeNow = new DateTime(DateTimeZone.UTC);
+ if (invoiceItem.getCreatedDate() != null) {
+ q.bind("created_date", invoiceItem.getCreatedDate().getMillis());
+ } else {
+ q.bind("created_date", dateTimeNow.getMillis());
+ }
+
+ if (invoiceItem.getUpdatedDate() != null) {
+ q.bind("updated_date", invoiceItem.getUpdatedDate().getMillis());
+ } else {
+ q.bind("updated_date", dateTimeNow.getMillis());
+ }
+
+ q.bind("invoice_id", invoiceItem.getInvoiceId().toString());
+ q.bind("item_type", invoiceItem.getItemType());
+ q.bind("external_key", invoiceItem.getExternalKey());
+ q.bind("product_name", invoiceItem.getProductName());
+ q.bind("product_type", invoiceItem.getProductType());
+ q.bind("product_category", invoiceItem.getProductCategory());
+ q.bind("slug", invoiceItem.getSlug());
+ q.bind("phase", invoiceItem.getPhase());
+ q.bind("billing_period", invoiceItem.getBillingPeriod());
+
+ if (invoiceItem.getStartDate() != null) {
+ q.bind("start_date", invoiceItem.getStartDate().toDate());
+ } else {
+ q.bindNull("start_date", Types.DATE);
+ }
+
+ if (invoiceItem.getEndDate() != null) {
+ q.bind("end_date", invoiceItem.getEndDate().toDate());
+ } else {
+ q.bindNull("end_date", Types.DATE);
+ }
+
+ q.bind("amount", Rounder.round(invoiceItem.getAmount()));
+ q.bind("currency", invoiceItem.getCurrency().toString());
+ }
+ };
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemMapper.java
new file mode 100644
index 0000000..c6b25f0
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemMapper.java
@@ -0,0 +1,60 @@
+/*
+ * 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 java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+import com.ning.billing.util.dao.MapperBase;
+
+public class BusinessInvoiceItemMapper extends MapperBase implements ResultSetMapper<BusinessInvoiceItemModelDao> {
+
+ @Override
+ public BusinessInvoiceItemModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID itemId = getUUID(r, "item_id");
+ final UUID linkedItemId = getUUID(r, "linked_item_id");
+ final DateTime createdDate = new DateTime(r.getLong("created_date"), DateTimeZone.UTC);
+ final DateTime updatedDate = new DateTime(r.getLong("updated_date"), DateTimeZone.UTC);
+ final UUID invoiceId = getUUID(r, "invoice_id");
+ final String itemType = r.getString("item_type");
+ final String externalKey = r.getString("external_key");
+ final String productName = r.getString("product_name");
+ final String productType = r.getString("product_type");
+ final String productCategory = r.getString("product_category");
+ final String slug = r.getString("slug");
+ final String phase = r.getString("phase");
+ final String billingPeriod = r.getString("billing_period");
+ final LocalDate startDate = getDate(r, "start_date");
+ final LocalDate endDate = getDate(r, "end_date");
+ final BigDecimal amount = BigDecimal.valueOf(r.getDouble("amount"));
+ final Currency currency = Currency.valueOf(r.getString("currency"));
+
+ return new BusinessInvoiceItemModelDao(amount, billingPeriod, createdDate, currency, endDate, externalKey, invoiceId,
+ itemId, linkedItemId, itemType, phase, productCategory, productName, productType, slug,
+ startDate, updatedDate);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.java
new file mode 100644
index 0000000..fbf750f
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.java
@@ -0,0 +1,64 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessInvoiceItemMapper.class)
+public interface BusinessInvoiceItemSqlDao extends Transactional<BusinessInvoiceItemSqlDao>, Transmogrifier {
+
+ @SqlQuery
+ BusinessInvoiceItemModelDao getInvoiceItem(@Bind("item_id") final String itemId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessInvoiceItemModelDao> getInvoiceItemsForInvoice(@Bind("invoice_id") final String invoiceId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessInvoiceItemModelDao> getInvoiceItemsForBundleByKey(@Bind("external_key") final String externalKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int createInvoiceItem(@BusinessInvoiceItemBinder final BusinessInvoiceItemModelDao invoiceItem,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int deleteInvoiceItem(@Bind("item_id") final String itemId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void deleteInvoiceItemsForAccount(@Bind("account_id") final String accountId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceMapper.java
new file mode 100644
index 0000000..58a8b83
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceMapper.java
@@ -0,0 +1,55 @@
+/*
+ * 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 java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.util.dao.MapperBase;
+
+public class BusinessInvoiceMapper extends MapperBase implements ResultSetMapper<BusinessInvoiceModelDao> {
+
+ @Override
+ public BusinessInvoiceModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID invoiceId = UUID.fromString(r.getString(1));
+ final Integer invoiceNumber = r.getInt(2);
+ final DateTime createdDate = new DateTime(r.getLong(3), DateTimeZone.UTC);
+ final DateTime updatedDate = new DateTime(r.getLong(4), DateTimeZone.UTC);
+ final UUID accountId = UUID.fromString(r.getString(5));
+ final String accountKey = r.getString(6);
+ final LocalDate invoiceDate = getDate(r, "invoice_date");
+ final LocalDate targetDate = getDate(r, "target_date");
+ final Currency currency = Currency.valueOf(r.getString(9));
+ final BigDecimal balance = BigDecimal.valueOf(r.getDouble(10));
+ final BigDecimal amountPaid = BigDecimal.valueOf(r.getDouble(11));
+ final BigDecimal amountCharged = BigDecimal.valueOf(r.getDouble(12));
+ final BigDecimal amountCredited = BigDecimal.valueOf(r.getDouble(13));
+
+ return new BusinessInvoiceModelDao(accountId, accountKey, amountCharged, amountCredited, amountPaid, balance, createdDate, currency,
+ invoiceDate, invoiceId, invoiceNumber, targetDate, updatedDate);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentBinder.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentBinder.java
new file mode 100644
index 0000000..08b3693
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentBinder.java
@@ -0,0 +1,97 @@
+/*
+ * 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.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.Types;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+
+@BindingAnnotation(BusinessInvoicePaymentBinder.BipBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface BusinessInvoicePaymentBinder {
+
+ public static class BipBinderFactory implements BinderFactory {
+
+ @Override
+ public Binder build(final Annotation annotation) {
+ return new Binder<BusinessInvoicePaymentBinder, BusinessInvoicePaymentModelDao>() {
+ @Override
+ public void bind(final SQLStatement q, final BusinessInvoicePaymentBinder bind, final BusinessInvoicePaymentModelDao invoicePayment) {
+ q.bind("payment_id", invoicePayment.getPaymentId().toString());
+
+ final DateTime dateTimeNow = new DateTime(DateTimeZone.UTC);
+ if (invoicePayment.getCreatedDate() != null) {
+ q.bind("created_date", invoicePayment.getCreatedDate().getMillis());
+ } else {
+ q.bind("created_date", dateTimeNow.getMillis());
+ }
+
+ if (invoicePayment.getUpdatedDate() != null) {
+ q.bind("updated_date", invoicePayment.getUpdatedDate().getMillis());
+ } else {
+ q.bind("updated_date", dateTimeNow.getMillis());
+ }
+
+ q.bind("ext_first_payment_ref_id", invoicePayment.getExtFirstPaymentRefId());
+ q.bind("ext_second_payment_ref_id", invoicePayment.getExtSecondPaymentRefId());
+ q.bind("account_key", invoicePayment.getAccountKey());
+ q.bind("invoice_id", invoicePayment.getInvoiceId().toString());
+
+ if (invoicePayment.getEffectiveDate() != null) {
+ q.bind("effective_date", invoicePayment.getEffectiveDate().getMillis());
+ } else {
+ q.bindNull("effective_date", Types.BIGINT);
+ }
+
+ q.bind("amount", Rounder.round(invoicePayment.getAmount()));
+ q.bind("currency", invoicePayment.getCurrency().toString());
+ q.bind("payment_error", invoicePayment.getPaymentError());
+ q.bind("processing_status", invoicePayment.getProcessingStatus());
+ q.bind("requested_amount", Rounder.round(invoicePayment.getRequestedAmount()));
+ q.bind("plugin_name", invoicePayment.getPluginName());
+ q.bind("payment_type", invoicePayment.getPaymentType());
+ q.bind("payment_method", invoicePayment.getPaymentMethod());
+ q.bind("card_type", invoicePayment.getCardType());
+ q.bind("card_country", invoicePayment.getCardCountry());
+ q.bind("invoice_payment_type", invoicePayment.getInvoicePaymentType());
+
+ final UUID linkedInvoicePaymentId = invoicePayment.getLinkedInvoicePaymentId();
+ if (linkedInvoicePaymentId != null) {
+ q.bind("linked_invoice_payment_id", linkedInvoicePaymentId.toString());
+ } else {
+ q.bindNull("linked_invoice_payment_id", Types.VARCHAR);
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldMapper.java
new file mode 100644
index 0000000..d948982
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldMapper.java
@@ -0,0 +1,34 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentFieldModelDao;
+
+public class BusinessInvoicePaymentFieldMapper implements ResultSetMapper<BusinessInvoicePaymentFieldModelDao> {
+
+ @Override
+ public BusinessInvoicePaymentFieldModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ return new BusinessInvoicePaymentFieldModelDao(UUID.fromString(r.getString(1)), r.getString(2), r.getString(3));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.java
new file mode 100644
index 0000000..67d1c07
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.java
@@ -0,0 +1,53 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentFieldModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessInvoicePaymentFieldMapper.class)
+public interface BusinessInvoicePaymentFieldSqlDao {
+
+ @SqlQuery
+ List<BusinessInvoicePaymentFieldModelDao> getFieldsForInvoicePayment(@Bind("payment_id") final String paymentId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addField(@Bind("payment_id") final String paymentId,
+ @Bind("name") final String name,
+ @Bind("value") final String value,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeField(@Bind("payment_id") final String paymentId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentMapper.java
new file mode 100644
index 0000000..c033499
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentMapper.java
@@ -0,0 +1,69 @@
+/*
+ * 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 java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+
+public class BusinessInvoicePaymentMapper implements ResultSetMapper<BusinessInvoicePaymentModelDao> {
+
+ @Override
+ public BusinessInvoicePaymentModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID paymentId = UUID.fromString(r.getString(1));
+ final DateTime createdDate = new DateTime(r.getLong(2), DateTimeZone.UTC);
+ final DateTime updatedDate = new DateTime(r.getLong(3), DateTimeZone.UTC);
+ final String extFirstPaymentRefId = r.getString(4);
+ final String extSecondPaymentRefId = r.getString(5);
+ final String accountKey = r.getString(6);
+ final UUID invoiceId = UUID.fromString(r.getString(7));
+ final DateTime effectiveDate = new DateTime(r.getLong(8), DateTimeZone.UTC);
+ final BigDecimal amount = BigDecimal.valueOf(r.getDouble(9));
+ final Currency currency = Currency.valueOf(r.getString(10));
+ final String paymentError = r.getString(11);
+ final String processingStatus = r.getString(12);
+ final BigDecimal requestedAmount = BigDecimal.valueOf(r.getDouble(13));
+ final String pluginName = r.getString(14);
+ final String paymentType = r.getString(15);
+ final String paymentMethod = r.getString(16);
+ final String cardType = r.getString(17);
+ final String cardCountry = r.getString(18);
+ final String invoicePaymentType = r.getString(19);
+ final String linkedInvoicePaymentIdString = r.getString(20);
+
+ final UUID linkedInvoicePaymentId;
+ if (linkedInvoicePaymentIdString != null) {
+ linkedInvoicePaymentId = UUID.fromString(linkedInvoicePaymentIdString);
+ } else {
+ linkedInvoicePaymentId = null;
+ }
+
+ return new BusinessInvoicePaymentModelDao(accountKey, amount, cardCountry, cardType, createdDate, currency,
+ effectiveDate, invoiceId, paymentError, paymentId, paymentMethod, paymentType,
+ pluginName, processingStatus, requestedAmount, updatedDate, invoicePaymentType,
+ linkedInvoicePaymentId);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.java
new file mode 100644
index 0000000..ea7256a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.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;
+
+import java.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessInvoicePaymentMapper.class)
+public interface BusinessInvoicePaymentSqlDao extends Transactional<BusinessInvoicePaymentSqlDao>, Transmogrifier {
+
+ @SqlQuery
+ BusinessInvoicePaymentModelDao getInvoicePayment(@Bind("payment_id") final String paymentId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessInvoicePaymentModelDao> getInvoicePaymentsForAccountByKey(@Bind("account_key") final String accountKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int createInvoicePayment(@BusinessInvoicePaymentBinder final BusinessInvoicePaymentModelDao payment,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int deleteInvoicePayment(@Bind("payment_id") final String paymentId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagMapper.java
new file mode 100644
index 0000000..12df373
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagMapper.java
@@ -0,0 +1,34 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentTagModelDao;
+
+public class BusinessInvoicePaymentTagMapper implements ResultSetMapper<BusinessInvoicePaymentTagModelDao> {
+
+ @Override
+ public BusinessInvoicePaymentTagModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ return new BusinessInvoicePaymentTagModelDao(UUID.fromString(r.getString(1)), r.getString(2));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.java
new file mode 100644
index 0000000..2961a18
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.java
@@ -0,0 +1,52 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentTagModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessInvoicePaymentTagMapper.class)
+public interface BusinessInvoicePaymentTagSqlDao {
+
+ @SqlQuery
+ List<BusinessInvoicePaymentTagModelDao> getTagsForInvoicePayment(@Bind("payment_id") final String paymentId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addTag(@Bind("payment_id") final String paymentId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeTag(@Bind("payment_id") final String paymentId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.java
new file mode 100644
index 0000000..083ffed
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.java
@@ -0,0 +1,64 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessInvoiceMapper.class)
+public interface BusinessInvoiceSqlDao extends Transactional<BusinessInvoiceSqlDao>, Transmogrifier {
+
+ @SqlQuery
+ BusinessInvoiceModelDao getInvoice(@Bind("invoice_id") final String invoiceId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessInvoiceModelDao> getInvoicesForAccount(@Bind("account_id") final String accountId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessInvoiceModelDao> getInvoicesForAccountByKey(@Bind("account_key") final String accountKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int createInvoice(@BusinessInvoiceBinder final BusinessInvoiceModelDao invoice,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int deleteInvoice(@Bind("invoice_id") final String invoiceId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void deleteInvoicesForAccount(@Bind("account_id") final String accountId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagMapper.java
new file mode 100644
index 0000000..6a050e7
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagMapper.java
@@ -0,0 +1,34 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceTagModelDao;
+
+public class BusinessInvoiceTagMapper implements ResultSetMapper<BusinessInvoiceTagModelDao> {
+
+ @Override
+ public BusinessInvoiceTagModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ return new BusinessInvoiceTagModelDao(UUID.fromString(r.getString(1)), r.getString(2));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.java
new file mode 100644
index 0000000..73cc1b6
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.java
@@ -0,0 +1,52 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceTagModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessInvoiceTagMapper.class)
+public interface BusinessInvoiceTagSqlDao {
+
+ @SqlQuery
+ List<BusinessInvoiceTagModelDao> getTagsForInvoice(@Bind("invoice_id") final String invoiceId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addTag(@Bind("invoice_id") final String invoiceId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeTag(@Bind("invoice_id") final String invoiceId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusBinder.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusBinder.java
new file mode 100644
index 0000000..ba5ff4b
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusBinder.java
@@ -0,0 +1,63 @@
+/*
+ * 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.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.Types;
+
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+
+@BindingAnnotation(BusinessOverdueStatusBinder.BosBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface BusinessOverdueStatusBinder {
+
+ public static class BosBinderFactory implements BinderFactory {
+
+ public Binder build(final Annotation annotation) {
+ return new Binder<BusinessOverdueStatusBinder, BusinessOverdueStatusModelDao>() {
+ public void bind(final SQLStatement q, final BusinessOverdueStatusBinder bind, final BusinessOverdueStatusModelDao overdueStatus) {
+ q.bind("account_key", overdueStatus.getAccountKey());
+ q.bind("bundle_id", overdueStatus.getBundleId().toString());
+ q.bind("external_key", overdueStatus.getExternalKey());
+ q.bind("status", overdueStatus.getStatus());
+
+ if (overdueStatus.getStartDate() != null) {
+ q.bind("start_date", overdueStatus.getStartDate().getMillis());
+ } else {
+ q.bindNull("start_date", Types.BIGINT);
+ }
+
+ if (overdueStatus.getEndDate() != null) {
+ q.bind("end_date", overdueStatus.getEndDate().getMillis());
+ } else {
+ q.bindNull("end_date", Types.BIGINT);
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusMapper.java
new file mode 100644
index 0000000..83f4fac
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusMapper.java
@@ -0,0 +1,43 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+
+public class BusinessOverdueStatusMapper implements ResultSetMapper<BusinessOverdueStatusModelDao> {
+
+ @Override
+ public BusinessOverdueStatusModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID bundleId = UUID.fromString(r.getString(1));
+ final String externalKey = r.getString(2);
+ final String accountKey = r.getString(3);
+ final String status = r.getString(4);
+ final DateTime startDate = new DateTime(r.getLong(5), DateTimeZone.UTC);
+ final DateTime endDate = new DateTime(r.getLong(6), DateTimeZone.UTC);
+
+ return new BusinessOverdueStatusModelDao(accountKey, bundleId, endDate, externalKey, startDate, status);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.java
new file mode 100644
index 0000000..b3da2a5
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.java
@@ -0,0 +1,52 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessOverdueStatusMapper.class)
+public interface BusinessOverdueStatusSqlDao extends Transactional<BusinessOverdueStatusSqlDao>, Transmogrifier {
+
+ @SqlQuery
+ List<BusinessOverdueStatusModelDao> getOverdueStatusesForBundleByKey(@Bind("external_key") final String externalKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int createOverdueStatus(@BusinessOverdueStatusBinder final BusinessOverdueStatusModelDao status,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void deleteOverdueStatusesForBundle(@Bind("bundle_id") final String bundleId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSqlProvider.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSqlProvider.java
new file mode 100644
index 0000000..242c522
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSqlProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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 org.skife.jdbi.v2.IDBI;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+public class BusinessSqlProvider<T> implements Provider<T> {
+
+ @Inject
+ private IDBI dbi;
+
+ private final Class clazz;
+
+ public BusinessSqlProvider(final Class<T> clazz) {
+ this.clazz = clazz;
+ }
+
+ @Override
+ public T get() {
+ return (T) dbi.onDemand(clazz);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionBinder.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionBinder.java
new file mode 100644
index 0000000..f37fa31
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionBinder.java
@@ -0,0 +1,138 @@
+/*
+ * 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.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.Types;
+
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscription;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+
+@BindingAnnotation(BusinessSubscriptionTransitionBinder.BstBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface BusinessSubscriptionTransitionBinder {
+
+ public static class BstBinderFactory implements BinderFactory {
+
+ public Binder build(final Annotation annotation) {
+ return new Binder<BusinessSubscriptionTransitionBinder, BusinessSubscriptionTransitionModelDao>() {
+ public void bind(final SQLStatement q, final BusinessSubscriptionTransitionBinder bind, final BusinessSubscriptionTransitionModelDao arg) {
+ q.bind("total_ordering", arg.getTotalOrdering());
+ q.bind("bundle_id", arg.getBundleId().toString());
+ q.bind("external_key", arg.getExternalKey());
+ q.bind("account_id", arg.getAccountId().toString());
+ q.bind("account_key", arg.getAccountKey());
+ q.bind("subscription_id", arg.getSubscriptionId().toString());
+ q.bind("requested_timestamp", arg.getRequestedTimestamp().getMillis());
+ q.bind("event", arg.getEvent().toString());
+
+ final BusinessSubscription previousSubscription = arg.getPreviousSubscription();
+ if (previousSubscription == null) {
+ q.bindNull("prev_product_name", Types.VARCHAR);
+ q.bindNull("prev_product_type", Types.VARCHAR);
+ q.bindNull("prev_product_category", Types.VARCHAR);
+ q.bindNull("prev_slug", Types.VARCHAR);
+ q.bindNull("prev_phase", Types.VARCHAR);
+ q.bindNull("prev_billing_period", Types.VARCHAR);
+ q.bindNull("prev_price", Types.NUMERIC);
+ q.bindNull("prev_price_list", Types.VARCHAR);
+ q.bindNull("prev_mrr", Types.NUMERIC);
+ q.bindNull("prev_currency", Types.VARCHAR);
+ q.bindNull("prev_start_date", Types.BIGINT);
+ q.bindNull("prev_state", Types.VARCHAR);
+ } else {
+ q.bind("prev_product_name", previousSubscription.getProductName());
+ q.bind("prev_product_type", previousSubscription.getProductType());
+ if (previousSubscription.getProductCategory() == null) {
+ q.bindNull("prev_product_category", Types.VARCHAR);
+ } else {
+ q.bind("prev_product_category", previousSubscription.getProductCategory().toString());
+ }
+ q.bind("prev_slug", previousSubscription.getSlug());
+ q.bind("prev_phase", previousSubscription.getPhase());
+ q.bind("prev_billing_period", previousSubscription.getBillingPeriod());
+ q.bind("prev_price", previousSubscription.getRoundedPrice());
+ q.bind("prev_price_list", previousSubscription.getPriceList());
+ q.bind("prev_mrr", previousSubscription.getRoundedMrr());
+ q.bind("prev_currency", previousSubscription.getCurrency());
+ if (previousSubscription.getStartDate() == null) {
+ q.bindNull("prev_start_date", Types.BIGINT);
+ } else {
+ q.bind("prev_start_date", previousSubscription.getStartDate().getMillis());
+ }
+ if (previousSubscription.getState() == null) {
+ q.bindNull("prev_state", Types.VARCHAR);
+ } else {
+ q.bind("prev_state", previousSubscription.getState().toString());
+ }
+ }
+
+ final BusinessSubscription nextSubscription = arg.getNextSubscription();
+ if (nextSubscription == null) {
+ q.bindNull("next_product_name", Types.VARCHAR);
+ q.bindNull("next_product_type", Types.VARCHAR);
+ q.bindNull("next_product_category", Types.VARCHAR);
+ q.bindNull("next_slug", Types.VARCHAR);
+ q.bindNull("next_phase", Types.VARCHAR);
+ q.bindNull("next_billing_period", Types.VARCHAR);
+ q.bindNull("next_price", Types.NUMERIC);
+ q.bindNull("next_price_list", Types.VARCHAR);
+ q.bindNull("next_mrr", Types.NUMERIC);
+ q.bindNull("next_currency", Types.VARCHAR);
+ q.bindNull("next_start_date", Types.BIGINT);
+ q.bindNull("next_state", Types.VARCHAR);
+ } else {
+ q.bind("next_product_name", nextSubscription.getProductName());
+ q.bind("next_product_type", nextSubscription.getProductType());
+ if (nextSubscription.getProductCategory() == null) {
+ q.bindNull("next_product_category", Types.VARCHAR);
+ } else {
+ q.bind("next_product_category", nextSubscription.getProductCategory().toString());
+ }
+ q.bind("next_slug", nextSubscription.getSlug());
+ q.bind("next_phase", nextSubscription.getPhase());
+ q.bind("next_billing_period", nextSubscription.getBillingPeriod());
+ q.bind("next_price", nextSubscription.getRoundedPrice());
+ q.bind("next_price_list", nextSubscription.getPriceList());
+ q.bind("next_mrr", nextSubscription.getRoundedMrr());
+ q.bind("next_currency", nextSubscription.getCurrency());
+ if (nextSubscription.getStartDate() == null) {
+ q.bindNull("next_start_date", Types.BIGINT);
+ } else {
+ q.bind("next_start_date", nextSubscription.getStartDate().getMillis());
+ }
+ if (nextSubscription.getState() == null) {
+ q.bindNull("next_state", Types.VARCHAR);
+ } else {
+ q.bind("next_state", nextSubscription.getState().toString());
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldMapper.java
new file mode 100644
index 0000000..7699bc6
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldMapper.java
@@ -0,0 +1,39 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionFieldModelDao;
+
+public class BusinessSubscriptionTransitionFieldMapper implements ResultSetMapper<BusinessSubscriptionTransitionFieldModelDao> {
+
+ @Override
+ public BusinessSubscriptionTransitionFieldModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID bundleId = UUID.fromString(r.getString(1));
+ final String externalKey = r.getString(2);
+ final String accountKey = r.getString(3);
+ final String name = r.getString(4);
+ final String value = r.getString(5);
+ return new BusinessSubscriptionTransitionFieldModelDao(accountKey, bundleId, externalKey, name, value);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.java
new file mode 100644
index 0000000..3f1ac43
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.java
@@ -0,0 +1,55 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionFieldModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessSubscriptionTransitionFieldMapper.class)
+public interface BusinessSubscriptionTransitionFieldSqlDao {
+
+ @SqlQuery
+ List<BusinessSubscriptionTransitionFieldModelDao> getFieldsForBusinessSubscriptionTransitionByKey(@Bind("external_key") final String externalKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addField(@Bind("account_key") final String accountKey,
+ @Bind("bundle_id") final String bundleId,
+ @Bind("external_key") final String externalKey,
+ @Bind("name") final String name,
+ @Bind("value") final String value,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeField(@Bind("bundle_id") final String bundleId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionMapper.java
new file mode 100644
index 0000000..f70c85e
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionMapper.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;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscription;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionEvent;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+
+import static com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+
+public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<BusinessSubscriptionTransitionModelDao> {
+
+ @Override
+ public BusinessSubscriptionTransitionModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ BusinessSubscription prev = new BusinessSubscription(
+ r.getString(9), // productName
+ r.getString(10), // productType
+ r.getString(11) == null ? null : ProductCategory.valueOf(r.getString(11)), // productCategory
+ r.getString(12), // slug
+ r.getString(13), // phase
+ r.getString(14), // billing period
+ BigDecimal.valueOf(r.getDouble(15)), // price
+ r.getString(16), // priceList
+ BigDecimal.valueOf(r.getDouble(17)), // mrr
+ r.getString(18), // currency
+ r.getLong(19) == 0 ? null : new DateTime(r.getLong(19), DateTimeZone.UTC), // startDate
+ r.getString(20) == null ? null : SubscriptionState.valueOf(r.getString(20)) // state
+ );
+
+ // Avoid creating a dummy subscriptions with all null fields
+ if (prev.getProductName() == null && prev.getSlug() == null) {
+ prev = null;
+ }
+
+ BusinessSubscription next = new BusinessSubscription(
+ r.getString(21), // productName
+ r.getString(22), // productType
+ r.getString(23) == null ? null : ProductCategory.valueOf(r.getString(23)), // productCategory
+ r.getString(24), // slug8
+ r.getString(25), // phase
+ r.getString(26), // billing period
+ BigDecimal.valueOf(r.getDouble(27)), // price
+ r.getString(28), // priceList
+ BigDecimal.valueOf(r.getDouble(29)), // mrr
+ r.getString(30), // currency
+ r.getLong(31) == 0 ? null : new DateTime(r.getLong(31), DateTimeZone.UTC), // startDate
+ r.getString(32) == null ? null : SubscriptionState.valueOf(r.getString(32)) // state
+ );
+
+ // Avoid creating a dummy subscriptions with all null fields
+ if (next.getProductName() == null && next.getSlug() == null) {
+ next = null;
+ }
+
+ final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf(r.getString(8));
+
+ return new BusinessSubscriptionTransitionModelDao(
+ r.getLong(1),
+ UUID.fromString(r.getString(2)),
+ r.getString(3),
+ UUID.fromString(r.getString(4)),
+ r.getString(5),
+ UUID.fromString(r.getString(6)),
+ new DateTime(r.getLong(7), DateTimeZone.UTC),
+ event,
+ prev,
+ next
+ );
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.java
new file mode 100644
index 0000000..7dc48f4
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.java
@@ -0,0 +1,64 @@
+/*
+ * 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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper({BusinessSubscriptionTransitionMapper.class, TimeSeriesTupleMapper.class})
+public interface BusinessSubscriptionTransitionSqlDao extends Transactional<BusinessSubscriptionTransitionSqlDao> {
+
+ @SqlQuery
+ List<TimeSeriesTuple> getSubscriptionsCreatedOverTime(@Bind("product_type") final String productType,
+ @Bind("slug") final String slug,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessSubscriptionTransitionModelDao> getTransitionsByKey(@Bind("external_key") final String externalKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessSubscriptionTransitionModelDao> getTransitionForSubscription(@Bind("subscription_id") final String subscriptionId,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlQuery
+ List<BusinessSubscriptionTransitionModelDao> getTransitionsForAccount(@Bind("account_key") final String accountKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int createTransition(@BusinessSubscriptionTransitionBinder final BusinessSubscriptionTransitionModelDao transition,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void deleteTransitionsForBundle(@Bind("bundle_id") final String bundleId,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagMapper.java
new file mode 100644
index 0000000..8b6d9b5
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagMapper.java
@@ -0,0 +1,38 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionTagModelDao;
+
+public class BusinessSubscriptionTransitionTagMapper implements ResultSetMapper<BusinessSubscriptionTransitionTagModelDao> {
+
+ @Override
+ public BusinessSubscriptionTransitionTagModelDao map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final UUID bundleId = UUID.fromString(r.getString(1));
+ final String externalKey = r.getString(2);
+ final String accountKey = r.getString(3);
+ final String name = r.getString(4);
+ return new BusinessSubscriptionTransitionTagModelDao(accountKey, bundleId, externalKey, name);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.java
new file mode 100644
index 0000000..4d42b39
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.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.util.List;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionTagModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessSubscriptionTransitionTagMapper.class)
+public interface BusinessSubscriptionTransitionTagSqlDao {
+
+ @SqlQuery
+ List<BusinessSubscriptionTransitionTagModelDao> getTagsForBusinessSubscriptionTransitionByKey(@Bind("external_key") final String externalKey,
+ @InternalTenantContextBinder final InternalTenantContext context);
+
+ @SqlUpdate
+ int addTag(@Bind("account_key") final String accountKey,
+ @Bind("bundle_id") final String bundleId,
+ @Bind("external_key") final String externalKey,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ int removeTag(@Bind("bundle_id") final String bundleId,
+ @Bind("name") final String name,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ void test(@InternalTenantContextBinder final InternalTenantContext context);
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsDao.java
new file mode 100644
index 0000000..b710f85
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsDao.java
@@ -0,0 +1,110 @@
+/*
+ * 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.util.List;
+
+import javax.inject.Inject;
+
+import com.ning.billing.analytics.api.TimeSeriesData;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultTimeSeriesData;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountTagModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+
+public class DefaultAnalyticsDao implements AnalyticsDao {
+
+ private final BusinessAccountSqlDao accountSqlDao;
+ private final BusinessSubscriptionTransitionSqlDao subscriptionTransitionSqlDao;
+ private final BusinessInvoiceSqlDao invoiceSqlDao;
+ private final BusinessInvoiceItemSqlDao invoiceItemSqlDao;
+ private final BusinessAccountTagSqlDao accountTagSqlDao;
+ private final BusinessOverdueStatusSqlDao overdueStatusSqlDao;
+ private final BusinessInvoicePaymentSqlDao invoicePaymentSqlDao;
+
+ @Inject
+ public DefaultAnalyticsDao(final BusinessAccountSqlDao accountSqlDao,
+ final BusinessSubscriptionTransitionSqlDao subscriptionTransitionSqlDao,
+ final BusinessInvoiceSqlDao invoiceSqlDao,
+ final BusinessInvoiceItemSqlDao invoiceItemSqlDao,
+ final BusinessAccountTagSqlDao accountTagSqlDao,
+ final BusinessOverdueStatusSqlDao overdueStatusSqlDao,
+ final BusinessInvoicePaymentSqlDao invoicePaymentSqlDao) {
+ this.accountSqlDao = accountSqlDao;
+ this.subscriptionTransitionSqlDao = subscriptionTransitionSqlDao;
+ this.invoiceSqlDao = invoiceSqlDao;
+ this.invoiceItemSqlDao = invoiceItemSqlDao;
+ this.accountTagSqlDao = accountTagSqlDao;
+ this.overdueStatusSqlDao = overdueStatusSqlDao;
+ this.invoicePaymentSqlDao = invoicePaymentSqlDao;
+ }
+
+ @Override
+ public TimeSeriesData getAccountsCreatedOverTime(final InternalTenantContext context) {
+ return new DefaultTimeSeriesData(accountSqlDao.getAccountsCreatedOverTime(context));
+ }
+
+ @Override
+ public TimeSeriesData getSubscriptionsCreatedOverTime(final String productType, final String slug, final InternalTenantContext context) {
+ return new DefaultTimeSeriesData(subscriptionTransitionSqlDao.getSubscriptionsCreatedOverTime(productType, slug, context));
+ }
+
+ @Override
+ public BusinessAccountModelDao getAccountByKey(final String accountKey, final InternalTenantContext context) {
+ return accountSqlDao.getAccountByKey(accountKey, context);
+ }
+
+ @Override
+ public List<BusinessSubscriptionTransitionModelDao> getTransitionsByKey(final String externalKey, final InternalTenantContext context) {
+ return subscriptionTransitionSqlDao.getTransitionsByKey(externalKey, context);
+ }
+
+ @Override
+ public List<BusinessSubscriptionTransitionModelDao> getTransitionsForAccount(final String accountKey, final InternalTenantContext context) {
+ return subscriptionTransitionSqlDao.getTransitionsForAccount(accountKey, context);
+ }
+
+ @Override
+ public List<BusinessInvoiceModelDao> getInvoicesByKey(final String accountKey, final InternalTenantContext context) {
+ return invoiceSqlDao.getInvoicesForAccountByKey(accountKey, context);
+ }
+
+ @Override
+ public List<BusinessAccountTagModelDao> getTagsForAccount(final String accountKey, final InternalTenantContext context) {
+ return accountTagSqlDao.getTagsForAccountByKey(accountKey, context);
+ }
+
+ @Override
+ public List<BusinessInvoiceItemModelDao> getInvoiceItemsForInvoice(final String invoiceId, final InternalTenantContext context) {
+ return invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceId, context);
+ }
+
+ @Override
+ public List<BusinessOverdueStatusModelDao> getOverdueStatusesForBundleByKey(final String externalKey, final InternalTenantContext context) {
+ return overdueStatusSqlDao.getOverdueStatusesForBundleByKey(externalKey, context);
+ }
+
+ @Override
+ public List<BusinessInvoicePaymentModelDao> getInvoicePaymentsForAccountByKey(final String accountKey, final InternalTenantContext context) {
+ return invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(accountKey, context);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsSanityDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsSanityDao.java
new file mode 100644
index 0000000..6068276
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/DefaultAnalyticsSanityDao.java
@@ -0,0 +1,81 @@
+/*
+ * 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.util.Collection;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.skife.jdbi.v2.IDBI;
+
+import com.ning.billing.util.callcontext.InternalTenantContext;
+
+public class DefaultAnalyticsSanityDao implements AnalyticsSanityDao {
+
+ private final AnalyticsSanitySqlDao sqlDao;
+
+ @Inject
+ public DefaultAnalyticsSanityDao(final IDBI dbi) {
+ sqlDao = dbi.onDemand(AnalyticsSanitySqlDao.class);
+ }
+
+ @Override
+ public Collection<UUID> checkBstMatchesSubscriptionEvents(final InternalTenantContext context) {
+ return sqlDao.checkBstMatchesSubscriptionEvents(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBiiMatchesInvoiceItems(final InternalTenantContext context) {
+ return sqlDao.checkBiiMatchesInvoiceItems(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBipMatchesInvoicePayments(final InternalTenantContext context) {
+ return sqlDao.checkBipMatchesInvoicePayments(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBinAmountPaidMatchesInvoicePayments(final InternalTenantContext context) {
+ return sqlDao.checkBinAmountPaidMatchesInvoicePayments(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBinAmountChargedMatchesInvoicePayments(final InternalTenantContext context) {
+ return sqlDao.checkBinAmountChargedMatchesInvoicePayments(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBinBiiBalanceConsistency(final InternalTenantContext context) {
+ return sqlDao.checkBinBiiBalanceConsistency(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBinBiiAmountCreditedConsistency(final InternalTenantContext context) {
+ return sqlDao.checkBinBiiAmountCreditedConsistency(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBacBinBiiConsistency(final InternalTenantContext context) {
+ return sqlDao.checkBacBinBiiConsistency(context);
+ }
+
+ @Override
+ public Collection<UUID> checkBacTagsMatchesTags(final InternalTenantContext context) {
+ return sqlDao.checkBacTagsMatchesTags(context);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTuple.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTuple.java
new file mode 100644
index 0000000..1ad845a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTuple.java
@@ -0,0 +1,76 @@
+/*
+ * 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 org.joda.time.LocalDate;
+
+public class TimeSeriesTuple {
+
+ private final LocalDate localDate;
+ private final Double value;
+
+ public TimeSeriesTuple(final LocalDate localDate, final Double value) {
+ this.localDate = localDate;
+ this.value = value;
+ }
+
+ public LocalDate getLocalDate() {
+ return localDate;
+ }
+
+ public Double getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TimeSeriesTuple");
+ sb.append("{localDate=").append(localDate);
+ sb.append(", value=").append(value);
+ 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 TimeSeriesTuple that = (TimeSeriesTuple) o;
+
+ if (localDate != null ? !localDate.equals(that.localDate) : that.localDate != null) {
+ return false;
+ }
+ if (value != null ? !value.equals(that.value) : that.value != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = localDate != null ? localDate.hashCode() : 0;
+ result = 31 * result + (value != null ? value.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTupleMapper.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTupleMapper.java
new file mode 100644
index 0000000..b24ffe2
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/TimeSeriesTupleMapper.java
@@ -0,0 +1,32 @@
+/*
+ * 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.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.joda.time.LocalDate;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+public class TimeSeriesTupleMapper implements ResultSetMapper<TimeSeriesTuple> {
+
+ @Override
+ public TimeSeriesTuple map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ return new TimeSeriesTuple(new LocalDate(r.getDate(1)), r.getDouble(2));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountFieldModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountFieldModelDao.java
new file mode 100644
index 0000000..5384aff
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountFieldModelDao.java
@@ -0,0 +1,87 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessAccountFieldModelDao extends BusinessFieldModelDao {
+
+ private final UUID accountId;
+ private final String accountKey;
+
+ public BusinessAccountFieldModelDao(final UUID accountId, final String accountKey, final String name, final String value) {
+ super(accountId, name, value);
+ this.accountId = accountId;
+ this.accountKey = accountKey;
+ }
+
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessAccountFieldModelDao");
+ sb.append("{accountId='").append(accountId).append('\'');
+ sb.append(", accountKey='").append(accountKey).append('\'');
+ sb.append(", name='").append(getName()).append('\'');
+ sb.append(", value='").append(getValue()).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 BusinessAccountFieldModelDao that = (BusinessAccountFieldModelDao) o;
+
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+ if (getValue() != null ? !getValue().equals(that.getValue()) : that.getValue() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = accountId != null ? accountId.hashCode() : 0;
+ result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountModelDao.java
new file mode 100644
index 0000000..3536f29
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountModelDao.java
@@ -0,0 +1,257 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+import com.ning.billing.util.entity.EntityBase;
+
+import com.google.common.base.Objects;
+
+public class BusinessAccountModelDao extends EntityBase {
+
+ private final UUID accountId;
+ private String key;
+ private String name;
+ private BigDecimal balance;
+ private LocalDate lastInvoiceDate;
+ private BigDecimal totalInvoiceBalance;
+ private String lastPaymentStatus;
+ private String paymentMethod;
+ private String creditCardType;
+ private String billingAddressCountry;
+ private String currency;
+
+ public BusinessAccountModelDao(final UUID accountId, final String key, final String name, final BigDecimal balance,
+ final LocalDate lastInvoiceDate, final BigDecimal totalInvoiceBalance, final String lastPaymentStatus,
+ final String paymentMethod, final String creditCardType, final String billingAddressCountry,
+ final String currency, final DateTime createdDt, final DateTime updatedDt) {
+ super(accountId, createdDt, updatedDt);
+ this.accountId = accountId;
+ this.key = key;
+ this.balance = balance;
+ this.billingAddressCountry = billingAddressCountry;
+ this.creditCardType = creditCardType;
+ this.lastInvoiceDate = lastInvoiceDate;
+ this.lastPaymentStatus = lastPaymentStatus;
+ this.name = name;
+ this.paymentMethod = paymentMethod;
+ this.totalInvoiceBalance = totalInvoiceBalance;
+ this.currency = currency;
+ }
+
+ public BusinessAccountModelDao(final Account account) {
+ super(account.getId(), account.getCreatedDate(), account.getUpdatedDate());
+ this.accountId = account.getId();
+ this.name = account.getName();
+ this.key = account.getExternalKey();
+ if (account.getCurrency() != null) {
+ this.currency = account.getCurrency().toString();
+ }
+ }
+
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(final String key) {
+ this.key = key;
+ }
+
+ public BigDecimal getBalance() {
+ return Objects.firstNonNull(balance, BigDecimal.ZERO);
+ }
+
+ public Double getRoundedBalance() {
+ return Rounder.round(balance);
+ }
+
+ public void setBalance(final BigDecimal balance) {
+ this.balance = balance;
+ }
+
+ public String getBillingAddressCountry() {
+ return billingAddressCountry;
+ }
+
+ public void setBillingAddressCountry(final String billingAddressCountry) {
+ this.billingAddressCountry = billingAddressCountry;
+ }
+
+ public String getCreditCardType() {
+ return creditCardType;
+ }
+
+ public void setCreditCardType(final String creditCardType) {
+ this.creditCardType = creditCardType;
+ }
+
+ public String getCurrency() {
+ return currency;
+ }
+
+ public void setCurrency(final String currency) {
+ this.currency = currency;
+ }
+
+ public LocalDate getLastInvoiceDate() {
+ return lastInvoiceDate;
+ }
+
+ public void setLastInvoiceDate(final LocalDate lastInvoiceDate) {
+ this.lastInvoiceDate = lastInvoiceDate;
+ }
+
+ public String getLastPaymentStatus() {
+ return lastPaymentStatus;
+ }
+
+ public void setLastPaymentStatus(final String lastPaymentStatus) {
+ this.lastPaymentStatus = lastPaymentStatus;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getPaymentMethod() {
+ return paymentMethod;
+ }
+
+ public void setPaymentMethod(final String paymentMethod) {
+ this.paymentMethod = paymentMethod;
+ }
+
+ public BigDecimal getTotalInvoiceBalance() {
+ return Objects.firstNonNull(totalInvoiceBalance, BigDecimal.ZERO);
+ }
+
+ public Double getRoundedTotalInvoiceBalance() {
+ return Rounder.round(totalInvoiceBalance);
+ }
+
+ public void setTotalInvoiceBalance(final BigDecimal totalInvoiceBalance) {
+ this.totalInvoiceBalance = totalInvoiceBalance;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessAccountModelDao");
+ sb.append("{balance=").append(balance);
+ sb.append(", createdDate=").append(createdDate);
+ sb.append(", updatedDate=").append(updatedDate);
+ sb.append(", accountId='").append(accountId).append('\'');
+ sb.append(", key='").append(key).append('\'');
+ sb.append(", name='").append(name).append('\'');
+ sb.append(", lastInvoiceDate=").append(lastInvoiceDate);
+ sb.append(", totalInvoiceBalance=").append(totalInvoiceBalance);
+ sb.append(", lastPaymentStatus='").append(lastPaymentStatus).append('\'');
+ sb.append(", paymentMethod='").append(paymentMethod).append('\'');
+ sb.append(", creditCardType='").append(creditCardType).append('\'');
+ sb.append(", billingAddressCountry='").append(billingAddressCountry).append('\'');
+ 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;
+ }
+
+ final BusinessAccountModelDao that = (BusinessAccountModelDao) o;
+
+ if (balance == null ? that.balance != null : balance.compareTo(that.balance) != 0) {
+ return false;
+ }
+ if (billingAddressCountry != null ? !billingAddressCountry.equals(that.billingAddressCountry) : that.billingAddressCountry != null) {
+ return false;
+ }
+ if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
+ return false;
+ }
+ if (creditCardType != null ? !creditCardType.equals(that.creditCardType) : that.creditCardType != null) {
+ return false;
+ }
+ if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
+ return false;
+ }
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (key != null ? !key.equals(that.key) : that.key != null) {
+ return false;
+ }
+ if (lastInvoiceDate != null ? lastInvoiceDate.compareTo(that.lastInvoiceDate) != 0 : that.lastInvoiceDate != null) {
+ return false;
+ }
+ if (lastPaymentStatus != null ? !lastPaymentStatus.equals(that.lastPaymentStatus) : that.lastPaymentStatus != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (paymentMethod != null ? !paymentMethod.equals(that.paymentMethod) : that.paymentMethod != null) {
+ return false;
+ }
+ if (totalInvoiceBalance == null ? that.totalInvoiceBalance != null : totalInvoiceBalance.compareTo(that.totalInvoiceBalance) != 0) {
+ return false;
+ }
+ if (updatedDate != null ? updatedDate.compareTo(that.updatedDate) != 0 : that.updatedDate != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = createdDate != null ? createdDate.hashCode() : 0;
+ result = 31 * result + (updatedDate != null ? updatedDate.hashCode() : 0);
+ result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+ result = 31 * result + (key != null ? key.hashCode() : 0);
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (balance != null ? balance.hashCode() : 0);
+ result = 31 * result + (lastInvoiceDate != null ? lastInvoiceDate.hashCode() : 0);
+ result = 31 * result + (totalInvoiceBalance != null ? totalInvoiceBalance.hashCode() : 0);
+ result = 31 * result + (lastPaymentStatus != null ? lastPaymentStatus.hashCode() : 0);
+ result = 31 * result + (paymentMethod != null ? paymentMethod.hashCode() : 0);
+ result = 31 * result + (creditCardType != null ? creditCardType.hashCode() : 0);
+ result = 31 * result + (billingAddressCountry != null ? billingAddressCountry.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/model/BusinessAccountTagModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountTagModelDao.java
new file mode 100644
index 0000000..8b419d7
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessAccountTagModelDao.java
@@ -0,0 +1,82 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessAccountTagModelDao extends BusinessTagModelDao {
+
+ private final UUID accountId;
+ private final String accountKey;
+
+ public BusinessAccountTagModelDao(final UUID accountId, final String accountKey, final String name) {
+ super(name);
+ this.accountId = accountId;
+ this.accountKey = accountKey;
+ }
+
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessAccountTagModelDao");
+ sb.append("{accountId='").append(accountId).append('\'');
+ sb.append(", accountKey='").append(accountKey).append('\'');
+ sb.append(", name='").append(getName()).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 BusinessAccountTagModelDao that = (BusinessAccountTagModelDao) o;
+
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = accountId != null ? accountId.hashCode() : 0;
+ result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessFieldModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessFieldModelDao.java
new file mode 100644
index 0000000..ed0293a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessFieldModelDao.java
@@ -0,0 +1,41 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import com.ning.billing.util.entity.EntityBase;
+
+public abstract class BusinessFieldModelDao extends EntityBase {
+
+ private final String name;
+ private final String value;
+
+ public BusinessFieldModelDao(final UUID id, final String name, final String value) {
+ super(id);
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceFieldModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceFieldModelDao.java
new file mode 100644
index 0000000..5bdaeab
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceFieldModelDao.java
@@ -0,0 +1,76 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessInvoiceFieldModelDao extends BusinessFieldModelDao {
+
+ private final UUID invoiceId;
+
+ public BusinessInvoiceFieldModelDao(final UUID invoiceId, final String name, final String value) {
+ super(invoiceId, name, value);
+ this.invoiceId = invoiceId;
+ }
+
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessInvoiceFieldModelDao");
+ sb.append("{invoiceId='").append(invoiceId).append('\'');
+ sb.append(", name='").append(getName()).append('\'');
+ sb.append(", value='").append(getValue()).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 BusinessInvoiceFieldModelDao that = (BusinessInvoiceFieldModelDao) o;
+
+ if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+ if (getValue() != null ? !getValue().equals(that.getValue()) : that.getValue() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = invoiceId != null ? invoiceId.hashCode() : 0;
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceItemModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceItemModelDao.java
new file mode 100644
index 0000000..53f58e6
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceItemModelDao.java
@@ -0,0 +1,257 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+import com.ning.billing.util.entity.EntityBase;
+
+public class BusinessInvoiceItemModelDao extends EntityBase {
+
+ private final UUID itemId;
+ private final UUID invoiceId;
+ private final String itemType;
+ private final String externalKey;
+ private final String productName;
+ private final String productType;
+ private final String productCategory;
+ private final String slug;
+ private final String phase;
+ private final String billingPeriod;
+ private final LocalDate startDate;
+ private final LocalDate endDate;
+ private final BigDecimal amount;
+ private final Currency currency;
+ private final UUID linkedItemId;
+
+ public BusinessInvoiceItemModelDao(final BigDecimal amount, @Nullable final String billingPeriod, final DateTime createdDate,
+ final Currency currency, final LocalDate endDate, final String externalKey,
+ final UUID invoiceId, final UUID itemId, @Nullable final UUID linkedItemId, final String itemType,
+ @Nullable final String phase, @Nullable final String productCategory, @Nullable final String productName,
+ @Nullable final String productType, @Nullable final String slug, final LocalDate startDate, final DateTime updatedDate) {
+ super(itemId, createdDate, updatedDate);
+ this.amount = amount;
+ this.billingPeriod = billingPeriod;
+ this.currency = currency;
+ this.endDate = endDate;
+ this.externalKey = externalKey;
+ this.invoiceId = invoiceId;
+ this.itemId = itemId;
+ this.linkedItemId = linkedItemId;
+ this.itemType = itemType;
+ this.phase = phase;
+ this.productCategory = productCategory;
+ this.productName = productName;
+ this.productType = productType;
+ this.slug = slug;
+ this.startDate = startDate;
+ }
+
+ public BusinessInvoiceItemModelDao(@Nullable final String externalKey, final InvoiceItem invoiceItem, @Nullable final Plan plan, @Nullable final PlanPhase planPhase) {
+ this(invoiceItem.getAmount(), planPhase != null ? planPhase.getBillingPeriod().toString() : null, invoiceItem.getCreatedDate(), invoiceItem.getCurrency(),
+ /* 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(),
+ externalKey, invoiceItem.getInvoiceId(), invoiceItem.getId(), invoiceItem.getLinkedItemId(), invoiceItem.getInvoiceItemType().toString(),
+ planPhase != null ? planPhase.getPhaseType().toString() : null, plan != null ? plan.getProduct().getCategory().toString() : null,
+ plan != null ? plan.getProduct().getName() : null, plan != null ? plan.getProduct().getCatalogName() : null,
+ planPhase != null ? planPhase.getName() : null, invoiceItem.getStartDate(), invoiceItem.getUpdatedDate());
+ }
+
+ public UUID getItemId() {
+ return itemId;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public String getBillingPeriod() {
+ return billingPeriod;
+ }
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public LocalDate getEndDate() {
+ return endDate;
+ }
+
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ public String getItemType() {
+ return itemType;
+ }
+
+ public UUID getLinkedItemId() {
+ return linkedItemId;
+ }
+
+ public String getPhase() {
+ return phase;
+ }
+
+ public String getProductCategory() {
+ return productCategory;
+ }
+
+ public String getProductName() {
+ return productName;
+ }
+
+ public String getProductType() {
+ return productType;
+ }
+
+ public String getSlug() {
+ return slug;
+ }
+
+ public LocalDate getStartDate() {
+ return startDate;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessInvoiceItemModelDao");
+ sb.append("{amount=").append(amount);
+ sb.append(", itemId=").append(itemId);
+ sb.append(", createdDate=").append(createdDate);
+ sb.append(", updatedDate=").append(updatedDate);
+ sb.append(", invoiceId=").append(invoiceId);
+ sb.append(", itemType='").append(itemType).append('\'');
+ sb.append(", externalKey='").append(externalKey).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(", currency=").append(currency);
+ sb.append(", linkedItemId=").append(linkedItemId);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final BusinessInvoiceItemModelDao that = (BusinessInvoiceItemModelDao) o;
+
+ if (amount != null ? Rounder.round(amount) != (Rounder.round(that.amount)) : that.amount != null) {
+ return false;
+ }
+ if (billingPeriod != null ? !billingPeriod.equals(that.billingPeriod) : that.billingPeriod != null) {
+ return false;
+ }
+ if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
+ return false;
+ }
+ if (currency != that.currency) {
+ return false;
+ }
+ if (endDate != null ? !endDate.equals(that.endDate) : that.endDate != null) {
+ return false;
+ }
+ if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != 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 (slug != null ? !slug.equals(that.slug) : that.slug != null) {
+ return false;
+ }
+ if (startDate != null ? !startDate.equals(that.startDate) : that.startDate != null) {
+ return false;
+ }
+ if (updatedDate != null ? !updatedDate.equals(that.updatedDate) : that.updatedDate != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = itemId != null ? itemId.hashCode() : 0;
+ result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
+ result = 31 * result + (updatedDate != null ? updatedDate.hashCode() : 0);
+ result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
+ result = 31 * result + (itemType != null ? itemType.hashCode() : 0);
+ result = 31 * result + (externalKey != null ? externalKey.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/model/BusinessInvoiceModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceModelDao.java
new file mode 100644
index 0000000..4515283
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceModelDao.java
@@ -0,0 +1,204 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+import com.ning.billing.util.entity.EntityBase;
+
+public class BusinessInvoiceModelDao extends EntityBase {
+
+ private final UUID invoiceId;
+ private final Integer invoiceNumber;
+ private final UUID accountId;
+ private final String accountKey;
+ private final LocalDate invoiceDate;
+ private final LocalDate targetDate;
+ private final Currency currency;
+ private final BigDecimal balance;
+ private final BigDecimal amountPaid;
+ private final BigDecimal amountCharged;
+ private final BigDecimal amountCredited;
+
+ public BusinessInvoiceModelDao(final UUID accountId, final String accountKey, final BigDecimal amountCharged, final BigDecimal amountCredited,
+ final BigDecimal amountPaid, final BigDecimal balance, final DateTime createdDate,
+ final Currency currency, final LocalDate invoiceDate, final UUID invoiceId, final Integer invoiceNumber,
+ final LocalDate targetDate, final DateTime updatedDate) {
+ super(invoiceId, createdDate, updatedDate);
+ this.accountId = accountId;
+ this.accountKey = accountKey;
+ this.amountCharged = amountCharged;
+ this.amountCredited = amountCredited;
+ this.amountPaid = amountPaid;
+ this.balance = balance;
+ this.currency = currency;
+ this.invoiceDate = invoiceDate;
+ this.invoiceId = invoiceId;
+ this.invoiceNumber = invoiceNumber;
+ this.targetDate = targetDate;
+ }
+
+ public BusinessInvoiceModelDao(final String accountKey, final Invoice invoice) {
+ this(invoice.getAccountId(), accountKey, invoice.getChargedAmount(), invoice.getCreditAdjAmount(), invoice.getPaidAmount(), invoice.getBalance(),
+ invoice.getCreatedDate(), invoice.getCurrency(), invoice.getInvoiceDate(), invoice.getId(), invoice.getInvoiceNumber(), invoice.getTargetDate(),
+ invoice.getUpdatedDate());
+ }
+
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ public BigDecimal getAmountCharged() {
+ return amountCharged;
+ }
+
+ public BigDecimal getAmountCredited() {
+ return amountCredited;
+ }
+
+ public BigDecimal getAmountPaid() {
+ return amountPaid;
+ }
+
+ public BigDecimal getBalance() {
+ return balance;
+ }
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public LocalDate getInvoiceDate() {
+ return invoiceDate;
+ }
+
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ public Integer getInvoiceNumber() {
+ return invoiceNumber;
+ }
+
+ public LocalDate getTargetDate() {
+ return targetDate;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessInvoiceModelDao");
+ sb.append("{accountId=").append(accountId);
+ sb.append(", invoiceId=").append(invoiceId);
+ sb.append(", invoiceNumber=").append(invoiceNumber);
+ sb.append(", createdDate=").append(createdDate);
+ sb.append(", updatedDate=").append(updatedDate);
+ sb.append(", accountKey='").append(accountKey).append('\'');
+ sb.append(", invoiceDate=").append(invoiceDate);
+ sb.append(", targetDate=").append(targetDate);
+ sb.append(", currency=").append(currency);
+ sb.append(", balance=").append(balance);
+ sb.append(", amountPaid=").append(amountPaid);
+ sb.append(", amountCharged=").append(amountCharged);
+ sb.append(", amountCredited=").append(amountCredited);
+ 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 BusinessInvoiceModelDao that = (BusinessInvoiceModelDao) o;
+
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (amountCharged != null ? Rounder.round(amountCharged) != Rounder.round(that.amountCharged) : that.amountCharged != null) {
+ return false;
+ }
+ if (amountCredited != null ? Rounder.round(amountCredited) != Rounder.round(that.amountCredited) : that.amountCredited != null) {
+ return false;
+ }
+ if (amountPaid != null ? Rounder.round(amountPaid) != Rounder.round(that.amountPaid) : that.amountPaid != null) {
+ return false;
+ }
+ if (balance != null ? Rounder.round(balance) != Rounder.round(that.balance) : that.balance != null) {
+ return false;
+ }
+ if (createdDate != null ? createdDate.compareTo(that.createdDate) != 0 : that.createdDate != null) {
+ return false;
+ }
+ if (currency != that.currency) {
+ return false;
+ }
+ if (invoiceDate != null ? invoiceDate.compareTo(that.invoiceDate) != 0 : 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 (targetDate != null ? targetDate.compareTo(that.targetDate) != 0 : that.targetDate != null) {
+ return false;
+ }
+ if (updatedDate != null ? updatedDate.compareTo(that.updatedDate) != 0 : that.updatedDate != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = invoiceId != null ? invoiceId.hashCode() : 0;
+ result = 31 * result + (invoiceNumber != null ? invoiceNumber.hashCode() : 0);
+ result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
+ result = 31 * result + (updatedDate != null ? updatedDate.hashCode() : 0);
+ result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+ result = 31 * result + (accountKey != null ? accountKey.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 + (amountCredited != null ? amountCredited.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentFieldModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentFieldModelDao.java
new file mode 100644
index 0000000..d051bf0
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentFieldModelDao.java
@@ -0,0 +1,76 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessInvoicePaymentFieldModelDao extends BusinessFieldModelDao {
+
+ private final UUID paymentId;
+
+ public BusinessInvoicePaymentFieldModelDao(final UUID paymentId, final String name, final String value) {
+ super(paymentId, name, value);
+ this.paymentId = paymentId;
+ }
+
+ public UUID getPaymentId() {
+ return paymentId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessPaymentField");
+ sb.append("{paymentId='").append(paymentId).append('\'');
+ sb.append(", name='").append(getName()).append('\'');
+ sb.append(", value='").append(getValue()).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 BusinessInvoicePaymentFieldModelDao that = (BusinessInvoicePaymentFieldModelDao) o;
+
+ if (paymentId != null ? !paymentId.equals(that.paymentId) : that.paymentId != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+ if (getValue() != null ? !getValue().equals(that.getValue()) : that.getValue() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = paymentId != null ? paymentId.hashCode() : 0;
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentModelDao.java
new file mode 100644
index 0000000..e04d1d6
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentModelDao.java
@@ -0,0 +1,272 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+import com.ning.billing.util.entity.EntityBase;
+
+public class BusinessInvoicePaymentModelDao extends EntityBase {
+
+ private final UUID paymentId;
+ private final String extFirstPaymentRefId;
+ private final String extSecondPaymentRefId;
+ private final String accountKey;
+ private final UUID invoiceId;
+ private final DateTime effectiveDate;
+ private final BigDecimal amount;
+ private final Currency currency;
+ private final String paymentError;
+ private final String processingStatus;
+ private final BigDecimal requestedAmount;
+ private final String pluginName;
+ private final String paymentType;
+ private final String paymentMethod;
+ private final String cardType;
+ private final String cardCountry;
+ private final String invoicePaymentType;
+ private final UUID linkedInvoicePaymentId;
+
+ public BusinessInvoicePaymentModelDao(final String accountKey, final BigDecimal amount,
+ final String cardCountry, final String cardType, final DateTime createdDate,
+ final Currency currency, final DateTime effectiveDate, final UUID invoiceId,
+ final String paymentError, final UUID paymentId, final String paymentMethod,
+ final String paymentType, @Nullable final String pluginName, final String processingStatus,
+ final BigDecimal requestedAmount, final DateTime updatedDate, @Nullable final String invoicePaymentType,
+ @Nullable final UUID linkedInvoicePaymentId) {
+ super(paymentId, createdDate, updatedDate);
+ this.accountKey = accountKey;
+ this.amount = amount;
+ // TODO For backward compatibility
+ this.extFirstPaymentRefId = null;
+ this.extSecondPaymentRefId = null;
+ this.cardCountry = cardCountry;
+ this.cardType = cardType;
+ this.currency = currency;
+ this.effectiveDate = effectiveDate;
+ this.invoiceId = invoiceId;
+ this.paymentError = paymentError;
+ this.paymentId = paymentId;
+ this.paymentMethod = paymentMethod;
+ this.paymentType = paymentType;
+ this.pluginName = pluginName;
+ this.processingStatus = processingStatus;
+ this.requestedAmount = requestedAmount;
+ this.invoicePaymentType = invoicePaymentType;
+ this.linkedInvoicePaymentId = linkedInvoicePaymentId;
+ }
+
+ public String getExtFirstPaymentRefId() {
+ return extFirstPaymentRefId;
+ }
+
+ public String getExtSecondPaymentRefId() {
+ return extSecondPaymentRefId;
+ }
+
+ public UUID getPaymentId() {
+ return paymentId;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public String getCardCountry() {
+ return cardCountry;
+ }
+
+ public String getCardType() {
+ return cardType;
+ }
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
+ }
+
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ public String getPaymentError() {
+ return paymentError;
+ }
+
+ public String getPaymentMethod() {
+ return paymentMethod;
+ }
+
+ public String getPaymentType() {
+ return paymentType;
+ }
+
+ public String getPluginName() {
+ return pluginName;
+ }
+
+ public String getProcessingStatus() {
+ return processingStatus;
+ }
+
+ public BigDecimal getRequestedAmount() {
+ return requestedAmount;
+ }
+
+ public String getInvoicePaymentType() {
+ return invoicePaymentType;
+ }
+
+ public UUID getLinkedInvoicePaymentId() {
+ return linkedInvoicePaymentId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessInvoicePaymentModelDao");
+ sb.append("{accountKey='").append(accountKey).append('\'');
+ sb.append(", paymentId=").append(paymentId);
+ sb.append(", createdDate=").append(createdDate);
+ sb.append(", extFirstPaymentRefId=").append(extFirstPaymentRefId);
+ sb.append(", updatedDate=").append(updatedDate);
+ sb.append(", invoiceId=").append(invoiceId);
+ sb.append(", effectiveDate=").append(effectiveDate);
+ sb.append(", amount=").append(amount);
+ sb.append(", currency=").append(currency);
+ sb.append(", paymentError='").append(paymentError).append('\'');
+ sb.append(", processingStatus='").append(processingStatus).append('\'');
+ sb.append(", requestedAmount=").append(requestedAmount);
+ sb.append(", pluginName='").append(pluginName).append('\'');
+ sb.append(", paymentType='").append(paymentType).append('\'');
+ sb.append(", paymentMethod='").append(paymentMethod).append('\'');
+ sb.append(", cardType='").append(cardType).append('\'');
+ sb.append(", cardCountry='").append(cardCountry).append('\'');
+ sb.append(", invoicePaymentType='").append(invoicePaymentType).append('\'');
+ sb.append(", linkedInvoicePaymentId='").append(linkedInvoicePaymentId).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 BusinessInvoicePaymentModelDao that = (BusinessInvoicePaymentModelDao) o;
+
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (amount != null ? Rounder.round(amount) != Rounder.round(that.amount) : that.amount != null) {
+ return false;
+ }
+ if (extFirstPaymentRefId != null ? !extFirstPaymentRefId.equals(that.extFirstPaymentRefId) : that.extFirstPaymentRefId != null) {
+ return false;
+ }
+ if (cardCountry != null ? !cardCountry.equals(that.cardCountry) : that.cardCountry != null) {
+ return false;
+ }
+ if (cardType != null ? !cardType.equals(that.cardType) : that.cardType != null) {
+ return false;
+ }
+ if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
+ return false;
+ }
+ if (currency != that.currency) {
+ return false;
+ }
+ if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
+ return false;
+ }
+ if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+ return false;
+ }
+ if (paymentError != null ? !paymentError.equals(that.paymentError) : that.paymentError != null) {
+ return false;
+ }
+ if (paymentId != null ? !paymentId.equals(that.paymentId) : that.paymentId != null) {
+ return false;
+ }
+ if (paymentMethod != null ? !paymentMethod.equals(that.paymentMethod) : that.paymentMethod != null) {
+ return false;
+ }
+ if (paymentType != null ? !paymentType.equals(that.paymentType) : that.paymentType != null) {
+ return false;
+ }
+ if (pluginName != null ? !pluginName.equals(that.pluginName) : that.pluginName != null) {
+ return false;
+ }
+ if (processingStatus != null ? !processingStatus.equals(that.processingStatus) : that.processingStatus != null) {
+ return false;
+ }
+ if (requestedAmount != null ? Rounder.round(requestedAmount) != Rounder.round(that.requestedAmount) : that.requestedAmount != null) {
+ return false;
+ }
+ if (updatedDate != null ? !updatedDate.equals(that.updatedDate) : that.updatedDate != null) {
+ return false;
+ }
+ if (invoicePaymentType != null ? !invoicePaymentType.equals(that.invoicePaymentType) : that.invoicePaymentType != null) {
+ return false;
+ }
+ if (linkedInvoicePaymentId != null ? !linkedInvoicePaymentId.equals(that.linkedInvoicePaymentId) : that.linkedInvoicePaymentId != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = paymentId != null ? paymentId.hashCode() : 0;
+ result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
+ result = 31 * result + (extFirstPaymentRefId != null ? extFirstPaymentRefId.hashCode() : 0);
+ result = 31 * result + (updatedDate != null ? updatedDate.hashCode() : 0);
+ result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
+ result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
+ result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
+ result = 31 * result + (paymentError != null ? paymentError.hashCode() : 0);
+ result = 31 * result + (processingStatus != null ? processingStatus.hashCode() : 0);
+ result = 31 * result + (requestedAmount != null ? requestedAmount.hashCode() : 0);
+ result = 31 * result + (pluginName != null ? pluginName.hashCode() : 0);
+ result = 31 * result + (paymentType != null ? paymentType.hashCode() : 0);
+ result = 31 * result + (paymentMethod != null ? paymentMethod.hashCode() : 0);
+ result = 31 * result + (cardType != null ? cardType.hashCode() : 0);
+ result = 31 * result + (cardCountry != null ? cardCountry.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentTagModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentTagModelDao.java
new file mode 100644
index 0000000..92606cf
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoicePaymentTagModelDao.java
@@ -0,0 +1,71 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessInvoicePaymentTagModelDao extends BusinessTagModelDao {
+
+ private final UUID paymentId;
+
+ public BusinessInvoicePaymentTagModelDao(final UUID paymentId, final String name) {
+ super(name);
+ this.paymentId = paymentId;
+ }
+
+ public UUID getPaymentId() {
+ return paymentId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessPaymentTag");
+ sb.append("{paymentId='").append(paymentId).append('\'');
+ sb.append(", name='").append(getName()).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 BusinessInvoicePaymentTagModelDao that = (BusinessInvoicePaymentTagModelDao) o;
+
+ if (paymentId != null ? !paymentId.equals(that.paymentId) : that.paymentId != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = paymentId != null ? paymentId.hashCode() : 0;
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceTagModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceTagModelDao.java
new file mode 100644
index 0000000..2740d37
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessInvoiceTagModelDao.java
@@ -0,0 +1,71 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessInvoiceTagModelDao extends BusinessTagModelDao {
+
+ private final UUID invoiceId;
+
+ public BusinessInvoiceTagModelDao(final UUID invoiceId, final String name) {
+ super(name);
+ this.invoiceId = invoiceId;
+ }
+
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessInvoiceTagModelDao");
+ sb.append("{paymentId='").append(invoiceId).append('\'');
+ sb.append(", name='").append(getName()).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 BusinessInvoiceTagModelDao that = (BusinessInvoiceTagModelDao) o;
+
+ if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = invoiceId != null ? invoiceId.hashCode() : 0;
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessOverdueStatusModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessOverdueStatusModelDao.java
new file mode 100644
index 0000000..13540b1
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessOverdueStatusModelDao.java
@@ -0,0 +1,127 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.util.entity.EntityBase;
+
+public class BusinessOverdueStatusModelDao extends EntityBase {
+
+ private final String accountKey;
+ private final UUID bundleId;
+ private final String externalKey;
+ private final String status;
+ private final DateTime startDate;
+ private final DateTime endDate;
+
+ public BusinessOverdueStatusModelDao(final String accountKey, final UUID bundleId, @Nullable final DateTime endDate,
+ final String externalKey, final DateTime startDate, final String status) {
+ this.accountKey = accountKey;
+ this.bundleId = bundleId;
+ this.endDate = endDate;
+ this.externalKey = externalKey;
+ this.startDate = startDate;
+ this.status = status;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ public UUID getBundleId() {
+ return bundleId;
+ }
+
+ public DateTime getEndDate() {
+ return endDate;
+ }
+
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ public DateTime getStartDate() {
+ return startDate;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessOverdueStatusModelDao");
+ sb.append("{accountKey=").append(accountKey);
+ sb.append(", bundleId='").append(bundleId).append('\'');
+ sb.append(", endDate='").append(endDate).append('\'');
+ sb.append(", externalKey='").append(externalKey).append('\'');
+ sb.append(", status='").append(status).append('\'');
+ sb.append(", startDate=").append(startDate);
+ 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 BusinessOverdueStatusModelDao that = (BusinessOverdueStatusModelDao) o;
+
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+ return false;
+ }
+ if (endDate != null ? !endDate.equals(that.endDate) : that.endDate != null) {
+ return false;
+ }
+ if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (startDate != null ? !startDate.equals(that.startDate) : that.startDate != null) {
+ return false;
+ }
+ if (status != null ? !status.equals(that.status) : that.status != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = accountKey != null ? accountKey.hashCode() : 0;
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+ result = 31 * result + (externalKey != null ? externalKey.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);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscription.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscription.java
new file mode 100644
index 0000000..5bebb96
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscription.java
@@ -0,0 +1,384 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+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.catalog.api.Product;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.osgi.bundles.analytics.utils.Rounder;
+
+import static com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+
+/**
+ * Describe a subscription for Analytics purposes
+ */
+public class BusinessSubscription {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessSubscription.class);
+
+ private static final Currency USD = Currency.valueOf("USD");
+
+ private final String productName;
+ private final String productType;
+ private final ProductCategory productCategory;
+ private final String slug;
+ private final String phase;
+ private final String billingPeriod;
+ private final BigDecimal price;
+ private final String priceList;
+ private final BigDecimal mrr;
+ private final String currency;
+ private final DateTime startDate;
+ private final SubscriptionState state;
+
+ public BusinessSubscription(final String productName, final String productType, final ProductCategory productCategory,
+ final String slug, final String phase, final String billingPeriod, final BigDecimal price,
+ final String priceList, final BigDecimal mrr, final String currency, final DateTime startDate, final SubscriptionState state) {
+ this.productName = productName;
+ this.productType = productType;
+ this.productCategory = productCategory;
+ this.slug = slug;
+ this.phase = phase;
+ this.billingPeriod = billingPeriod;
+ this.price = price;
+ this.priceList = priceList;
+ this.mrr = mrr;
+ this.currency = currency;
+ this.startDate = startDate;
+ this.state = state;
+ }
+
+ /**
+ * For unit tests only.
+ * <p/>
+ * You can't really use this constructor in real life because the start date is likely not the one you want (you likely
+ * want the phase start date).
+ *
+ * @param subscription Subscription to use as a model
+ * @param currency ACCOUNT currency
+ * @param catalog Catalog to use
+ */
+ BusinessSubscription(final Subscription subscription, final Currency currency, final Catalog catalog) {
+ this(subscription.getCurrentPriceList() == null ? null : subscription.getCurrentPriceList().getName(),
+ subscription.getCurrentPlan().getName(), subscription.getCurrentPhase().getName(), currency,
+ subscription.getStartDate(), subscription.getState(), catalog);
+ }
+
+ public BusinessSubscription(final String priceList, final String currentPlan, final String currentPhase, final Currency currency,
+ final DateTime startDate, final SubscriptionState state, final Catalog catalog) {
+ Plan thePlan = null;
+ PlanPhase thePhase = null;
+ try {
+ thePlan = (currentPlan != null) ? catalog.findPlan(currentPlan, new DateTime(), startDate) : null;
+ thePhase = (currentPhase != null) ? catalog.findPhase(currentPhase, new DateTime(), startDate) : null;
+ } catch (CatalogApiException e) {
+ log.error("Failed to retrieve Plan from catalog for plan {}, phase {}", currentPlan, currentPhase);
+ }
+
+ this.priceList = priceList;
+
+ // Record plan information
+ if (currentPlan != null && thePlan != null && thePlan.getProduct() != null) {
+ final Product product = thePlan.getProduct();
+ productName = product.getName();
+ productCategory = product.getCategory();
+ // TODO - we should keep the product type
+ productType = product.getCatalogName();
+ } else {
+ productName = null;
+ productCategory = null;
+ productType = null;
+ }
+
+ // Record phase information
+ if (currentPhase != null && thePhase != null) {
+ slug = thePhase.getName();
+
+ if (thePhase.getPhaseType() != null) {
+ phase = thePhase.getPhaseType().toString();
+ } else {
+ phase = null;
+ }
+
+ if (thePhase.getBillingPeriod() != null) {
+ billingPeriod = thePhase.getBillingPeriod().toString();
+ } else {
+ billingPeriod = null;
+ }
+
+ if (thePhase.getRecurringPrice() != null) {
+ //TODO check if this is the right way to handle exception
+ BigDecimal tmpPrice;
+ try {
+ tmpPrice = thePhase.getRecurringPrice().getPrice(USD);
+ } catch (CatalogApiException e) {
+ tmpPrice = new BigDecimal(0);
+ }
+ price = tmpPrice;
+ mrr = getMrrFromBillingPeriod(thePhase.getBillingPeriod(), price);
+ } else {
+ price = BigDecimal.ZERO;
+ mrr = BigDecimal.ZERO;
+ }
+ } else {
+ slug = null;
+ phase = null;
+ billingPeriod = null;
+ price = BigDecimal.ZERO;
+ mrr = BigDecimal.ZERO;
+ }
+
+ if (currency != null) {
+ this.currency = currency.toString();
+ } else {
+ this.currency = null;
+ }
+
+ this.startDate = startDate;
+ this.state = state;
+ }
+
+ public BusinessSubscription(final String priceList, final Plan currentPlan, final PlanPhase currentPhase, final Currency currency,
+ final DateTime startDate, final SubscriptionState state) {
+ this.priceList = priceList;
+
+ // Record plan information
+ if (currentPlan != null && currentPlan.getProduct() != null) {
+ final Product product = currentPlan.getProduct();
+ productName = product.getName();
+ productCategory = product.getCategory();
+ // TODO - we should keep the product type
+ productType = product.getCatalogName();
+ } else {
+ productName = null;
+ productCategory = null;
+ productType = null;
+ }
+
+ // Record phase information
+ if (currentPhase != null) {
+ slug = currentPhase.getName();
+
+ if (currentPhase.getPhaseType() != null) {
+ phase = currentPhase.getPhaseType().toString();
+ } else {
+ phase = null;
+ }
+
+ if (currentPhase.getBillingPeriod() != null) {
+ billingPeriod = currentPhase.getBillingPeriod().toString();
+ } else {
+ billingPeriod = null;
+ }
+
+ if (currentPhase.getRecurringPrice() != null) {
+ //TODO check if this is the right way to handle exception
+ BigDecimal tmpPrice;
+ try {
+ tmpPrice = currentPhase.getRecurringPrice().getPrice(USD);
+ } catch (CatalogApiException e) {
+ tmpPrice = new BigDecimal(0);
+ }
+ price = tmpPrice;
+ mrr = getMrrFromBillingPeriod(currentPhase.getBillingPeriod(), price);
+ } else {
+ price = BigDecimal.ZERO;
+ mrr = BigDecimal.ZERO;
+ }
+ } else {
+ slug = null;
+ phase = null;
+ billingPeriod = null;
+ price = BigDecimal.ZERO;
+ mrr = BigDecimal.ZERO;
+ }
+
+ if (currency != null) {
+ this.currency = currency.toString();
+ } else {
+ this.currency = null;
+ }
+
+ this.startDate = startDate;
+ this.state = state;
+ }
+
+ public String getBillingPeriod() {
+ return billingPeriod;
+ }
+
+ public String getCurrency() {
+ return currency;
+ }
+
+ public BigDecimal getMrr() {
+ return mrr;
+ }
+
+ public double getRoundedMrr() {
+ return Rounder.round(mrr);
+ }
+
+ public String getPhase() {
+ return phase;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ public String getPriceList() {
+ return priceList;
+ }
+
+ public double getRoundedPrice() {
+ return Rounder.round(price);
+ }
+
+ public ProductCategory getProductCategory() {
+ return productCategory;
+ }
+
+ public String getProductName() {
+ return productName;
+ }
+
+ public String getProductType() {
+ return productType;
+ }
+
+ public String getSlug() {
+ return slug;
+ }
+
+ public DateTime getStartDate() {
+ return startDate;
+ }
+
+ public SubscriptionState getState() {
+ return state;
+ }
+
+ static BigDecimal getMrrFromBillingPeriod(final BillingPeriod period, final BigDecimal price) {
+ if (period == null || period.getNumberOfMonths() == 0) {
+ return BigDecimal.ZERO;
+ }
+
+ return price.divide(BigDecimal.valueOf(period.getNumberOfMonths()), Rounder.SCALE, RoundingMode.HALF_UP);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessSubscription");
+ sb.append("{billingPeriod='").append(billingPeriod).append('\'');
+ sb.append(", productName='").append(productName).append('\'');
+ sb.append(", productType='").append(productType).append('\'');
+ sb.append(", productCategory=").append(productCategory);
+ sb.append(", slug='").append(slug).append('\'');
+ sb.append(", phase='").append(phase).append('\'');
+ sb.append(", price=").append(price);
+ sb.append(", priceList=").append(priceList);
+ sb.append(", mrr=").append(mrr);
+ sb.append(", currency='").append(currency).append('\'');
+ sb.append(", startDate=").append(startDate);
+ sb.append(", state=").append(state);
+ 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 BusinessSubscription that = (BusinessSubscription) o;
+
+ if (billingPeriod != null ? !billingPeriod.equals(that.billingPeriod) : that.billingPeriod != null) {
+ return false;
+ }
+ if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
+ return false;
+ }
+ if (mrr != null ? !(Rounder.round(mrr) == Rounder.round(that.mrr)) : that.mrr != null) {
+ return false;
+ }
+ if (phase != null ? !phase.equals(that.phase) : that.phase != null) {
+ return false;
+ }
+ if (price != null ? !(Rounder.round(price) == Rounder.round(that.price)) : that.price != null) {
+ return false;
+ }
+ if (priceList != null ? !priceList.equals(that.priceList) : that.priceList != 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 (slug != null ? !slug.equals(that.slug) : that.slug != null) {
+ return false;
+ }
+ if (startDate != null ? !startDate.equals(that.startDate) : that.startDate != null) {
+ return false;
+ }
+ if (state != that.state) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int 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 + (price != null ? price.hashCode() : 0);
+ result = 31 * result + (priceList != null ? priceList.hashCode() : 0);
+ result = 31 * result + (mrr != null ? mrr.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
+ result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
+ result = 31 * result + (state != null ? state.hashCode() : 0);
+ result = 31 * result + (billingPeriod != null ? billingPeriod.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionEvent.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionEvent.java
new file mode 100644
index 0000000..5d4d4c5
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionEvent.java
@@ -0,0 +1,174 @@
+/*
+ * 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.model;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.catalog.api.ProductCategory;
+
+import static com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+
+/**
+ * Describe an event associated with a transition between two BusinessSubscription
+ */
+public class BusinessSubscriptionEvent {
+
+ private static final Logger log = LoggerFactory.getLogger(BusinessSubscriptionEvent.class);
+
+ private static final String MISC = "MISC";
+
+ public enum EventType {
+ MIGRATE,
+ ADD,
+ CANCEL,
+ RE_ADD,
+ TRANSFER,
+ CHANGE,
+ SYSTEM_CANCEL,
+ SYSTEM_CHANGE
+ }
+
+ private final EventType eventType;
+ private final ProductCategory category;
+
+ public static BusinessSubscriptionEvent valueOf(final String eventString) {
+ for (final EventType possibleEventType : EventType.values()) {
+ if (!eventString.startsWith(possibleEventType.toString().toUpperCase())) {
+ continue;
+ }
+
+ final String categoryString = eventString.substring(possibleEventType.toString().length() + 1, eventString.length());
+
+ if (categoryString.equals(MISC)) {
+ return new BusinessSubscriptionEvent(possibleEventType, null);
+ } else {
+ return new BusinessSubscriptionEvent(possibleEventType, ProductCategory.valueOf(categoryString));
+ }
+ }
+
+ throw new IllegalArgumentException("Unable to parse event string: " + eventString);
+ }
+
+ // Public for internal reasons
+ public BusinessSubscriptionEvent(final EventType eventType, final ProductCategory category) {
+ this.eventType = eventType;
+ this.category = category;
+ }
+
+ public ProductCategory getCategory() {
+ return category;
+ }
+
+ public EventType getEventType() {
+ return eventType;
+ }
+
+ public static BusinessSubscriptionEvent subscriptionMigrated(final String plan, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ return eventFromType(EventType.MIGRATE, plan, catalog, eventTime, subscriptionCreationDate);
+ }
+
+ public static BusinessSubscriptionEvent subscriptionCreated(final String plan, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ return eventFromType(EventType.ADD, plan, catalog, eventTime, subscriptionCreationDate);
+ }
+
+ public static BusinessSubscriptionEvent subscriptionCancelled(final String plan, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ return eventFromType(EventType.CANCEL, plan, catalog, eventTime, subscriptionCreationDate);
+ }
+
+ public static BusinessSubscriptionEvent subscriptionChanged(final String plan, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ return eventFromType(EventType.CHANGE, plan, catalog, eventTime, subscriptionCreationDate);
+ }
+
+ public static BusinessSubscriptionEvent subscriptionRecreated(final String plan, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ return eventFromType(EventType.RE_ADD, plan, catalog, eventTime, subscriptionCreationDate);
+ }
+
+ public static BusinessSubscriptionEvent subscriptionTransfered(final String plan, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ return eventFromType(EventType.TRANSFER, plan, catalog, eventTime, subscriptionCreationDate);
+ }
+
+ public static BusinessSubscriptionEvent subscriptionPhaseChanged(final String plan, final SubscriptionState state, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ if (state != null && state.equals(SubscriptionState.CANCELLED)) {
+ return eventFromType(EventType.SYSTEM_CANCEL, plan, catalog, eventTime, subscriptionCreationDate);
+ } else {
+ return eventFromType(EventType.SYSTEM_CHANGE, plan, catalog, eventTime, subscriptionCreationDate);
+ }
+ }
+
+ private static BusinessSubscriptionEvent eventFromType(final EventType eventType, final String plan, final Catalog catalog, final DateTime eventTime, final DateTime subscriptionCreationDate) {
+ Plan thePlan = null;
+ try {
+ thePlan = catalog.findPlan(plan, eventTime, subscriptionCreationDate);
+ } catch (CatalogApiException e) {
+ log.error(String.format("Failed to retrieve PLan from catalog for %s", plan));
+
+ }
+ final ProductCategory category = getTypeFromSubscription(thePlan);
+ return new BusinessSubscriptionEvent(eventType, category);
+ }
+
+ private static ProductCategory getTypeFromSubscription(final Plan plan) {
+
+ if (plan != null && plan.getProduct() != null) {
+ final Product product = plan.getProduct();
+ if (product.getCatalogName() != null && product.getCategory() != null) {
+ return product.getCategory();
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return eventType.toString() + "_" + (category == null ? MISC : category.toString().toUpperCase());
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final BusinessSubscriptionEvent that = (BusinessSubscriptionEvent) o;
+
+ if (category != that.category) {
+ return false;
+ }
+ if (eventType != null ? !eventType.equals(that.eventType) : that.eventType != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = eventType != null ? eventType.hashCode() : 0;
+ result = 31 * result + (category != null ? category.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionFieldModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionFieldModelDao.java
new file mode 100644
index 0000000..5ed5162
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionFieldModelDao.java
@@ -0,0 +1,99 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessSubscriptionTransitionFieldModelDao extends BusinessFieldModelDao {
+
+ private final String accountKey;
+ private final UUID bundleId;
+ private final String externalKey;
+
+ public BusinessSubscriptionTransitionFieldModelDao(final String accountKey, final UUID bundleId, final String externalKey,
+ final String name, final String value) {
+ super(bundleId, name, value);
+ this.accountKey = accountKey;
+ this.bundleId = bundleId;
+ this.externalKey = externalKey;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ public UUID getBundleId() {
+ return bundleId;
+ }
+
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessSubscriptionTransitionFieldModelDao");
+ sb.append("{accountKey='").append(accountKey).append('\'');
+ sb.append(", bundleId='").append(bundleId).append('\'');
+ sb.append(", externalKey='").append(externalKey).append('\'');
+ sb.append(", name='").append(getName()).append('\'');
+ sb.append(", value='").append(getValue()).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 BusinessSubscriptionTransitionFieldModelDao that = (BusinessSubscriptionTransitionFieldModelDao) o;
+
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+ return false;
+ }
+ if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+ if (getValue() != null ? !getValue().equals(that.getValue()) : that.getValue() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = accountKey != null ? accountKey.hashCode() : 0;
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+ result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionModelDao.java
new file mode 100644
index 0000000..8ca0eb8
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionModelDao.java
@@ -0,0 +1,200 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.util.entity.EntityBase;
+
+/**
+ * Describe a state change between two BusinessSubscription
+ */
+public class BusinessSubscriptionTransitionModelDao extends EntityBase {
+
+ private final long totalOrdering;
+ private final UUID bundleId;
+ private final String externalKey;
+ private final UUID accountId;
+ private final String accountKey;
+ private final UUID subscriptionId;
+ private final DateTime requestedTimestamp;
+ private final BusinessSubscriptionEvent event;
+ private final BusinessSubscription previousSubscription;
+ private final BusinessSubscription nextSubscription;
+
+ public BusinessSubscriptionTransitionModelDao(final Long totalOrdering, final UUID bundleId, final String externalKey,
+ final UUID accountId, final String accountKey, final UUID subscriptionId,
+ final DateTime requestedTimestamp, final BusinessSubscriptionEvent event,
+ final BusinessSubscription previousSubscription, final BusinessSubscription nextSubscription) {
+ if (totalOrdering == null) {
+ throw new IllegalArgumentException("A transition must have a total ordering");
+ }
+ if (bundleId == null) {
+ throw new IllegalArgumentException("A transition must have a bundle id");
+ }
+ if (externalKey == null) {
+ throw new IllegalArgumentException("A transition must have an external key");
+ }
+ if (accountId == null) {
+ throw new IllegalArgumentException("A transition must have an account key");
+ }
+ if (subscriptionId == null) {
+ throw new IllegalArgumentException("A transition must have a subscription id");
+ }
+ if (accountKey == null) {
+ throw new IllegalArgumentException("A transition must have an account key");
+ }
+ if (requestedTimestamp == null) {
+ throw new IllegalArgumentException("A transition must have a requested timestamp");
+ }
+ if (event == null) {
+ throw new IllegalArgumentException("No event specified");
+ }
+
+ this.totalOrdering = totalOrdering;
+ this.bundleId = bundleId;
+ this.externalKey = externalKey;
+ this.accountId = accountId;
+ this.accountKey = accountKey;
+ this.subscriptionId = subscriptionId;
+ this.requestedTimestamp = requestedTimestamp;
+ this.event = event;
+ this.previousSubscription = previousSubscription;
+ this.nextSubscription = nextSubscription;
+ }
+
+ public long getTotalOrdering() {
+ return totalOrdering;
+ }
+
+ public BusinessSubscriptionEvent getEvent() {
+ return event;
+ }
+
+ public UUID getBundleId() {
+ return bundleId;
+ }
+
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ public BusinessSubscription getNextSubscription() {
+ return nextSubscription;
+ }
+
+ public BusinessSubscription getPreviousSubscription() {
+ return previousSubscription;
+ }
+
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ public DateTime getRequestedTimestamp() {
+ return requestedTimestamp;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessSubscriptionTransitionModelDao");
+ sb.append("{accountId='").append(accountId).append('\'');
+ sb.append(", accountKey=").append(accountKey);
+ sb.append(", totalOrdering=").append(totalOrdering);
+ sb.append(", bundleId='").append(bundleId).append('\'');
+ sb.append(", externalKey='").append(externalKey).append('\'');
+ sb.append(", subscriptionId='").append(subscriptionId).append('\'');
+ sb.append(", requestedTimestamp=").append(requestedTimestamp);
+ sb.append(", event=").append(event);
+ sb.append(", previousSubscription=").append(previousSubscription);
+ sb.append(", nextSubscription=").append(nextSubscription);
+ 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 BusinessSubscriptionTransitionModelDao that = (BusinessSubscriptionTransitionModelDao) o;
+
+ return totalOrdering == that.totalOrdering && isDuplicateOf(that);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (totalOrdering ^ (totalOrdering >>> 32));
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+ result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
+ result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+ result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
+ result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
+ result = 31 * result + (requestedTimestamp != null ? requestedTimestamp.hashCode() : 0);
+ result = 31 * result + (event != null ? event.hashCode() : 0);
+ result = 31 * result + (previousSubscription != null ? previousSubscription.hashCode() : 0);
+ result = 31 * result + (nextSubscription != null ? nextSubscription.hashCode() : 0);
+ return result;
+ }
+
+ public boolean isDuplicateOf(final BusinessSubscriptionTransitionModelDao that) {
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (event != null ? !event.equals(that.event) : that.event != null) {
+ return false;
+ }
+ if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+ return false;
+ }
+ if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (nextSubscription != null ? !nextSubscription.equals(that.nextSubscription) : that.nextSubscription != null) {
+ return false;
+ }
+ if (previousSubscription != null ? !previousSubscription.equals(that.previousSubscription) : that.previousSubscription != null) {
+ return false;
+ }
+ if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null) {
+ return false;
+ }
+ if (requestedTimestamp != null ? !requestedTimestamp.equals(that.requestedTimestamp) : that.requestedTimestamp != null) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionTagModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionTagModelDao.java
new file mode 100644
index 0000000..2031b9f
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessSubscriptionTransitionTagModelDao.java
@@ -0,0 +1,93 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+public class BusinessSubscriptionTransitionTagModelDao extends BusinessTagModelDao {
+
+ private final String accountKey;
+ private final UUID bundleId;
+ private final String externalKey;
+
+ public BusinessSubscriptionTransitionTagModelDao(final String accountKey, final UUID bundleId, final String externalKey, final String name) {
+ super(name);
+ this.accountKey = accountKey;
+ this.bundleId = bundleId;
+ this.externalKey = externalKey;
+ }
+
+ public String getAccountKey() {
+ return accountKey;
+ }
+
+ public UUID getBundleId() {
+ return bundleId;
+ }
+
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessSubscriptionTransitionTagModelDao");
+ sb.append("{accountKey='").append(accountKey).append('\'');
+ sb.append(", bundleId='").append(bundleId).append('\'');
+ sb.append(", externalKey='").append(externalKey).append('\'');
+ sb.append(", name='").append(getName()).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 BusinessSubscriptionTransitionTagModelDao that = (BusinessSubscriptionTransitionTagModelDao) o;
+
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
+ if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+ return false;
+ }
+ if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = accountKey != null ? accountKey.hashCode() : 0;
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+ result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessTagModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessTagModelDao.java
new file mode 100644
index 0000000..9809b57
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/model/BusinessTagModelDao.java
@@ -0,0 +1,32 @@
+/*
+ * 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.model;
+
+import com.ning.billing.util.entity.EntityBase;
+
+public abstract class BusinessTagModelDao extends EntityBase {
+
+ private final String name;
+
+ public BusinessTagModelDao(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/PaymentMethodUtils.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/PaymentMethodUtils.java
new file mode 100644
index 0000000..23fb706
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/PaymentMethodUtils.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+import javax.annotation.Nullable;
+
+import com.ning.billing.payment.api.PaymentMethodPlugin;
+
+import com.google.common.annotations.VisibleForTesting;
+
+// TODO - make it generic
+public class PaymentMethodUtils {
+
+ @VisibleForTesting
+ static final String COUNTRY_KEY = "country";
+ @VisibleForTesting
+ static final String CARD_TYPE_KEY = "cardType";
+ @VisibleForTesting
+ static final String TYPE_KEY = "type";
+
+ private PaymentMethodUtils() {}
+
+ public static String getCardCountry(@Nullable final PaymentMethodPlugin pluginDetail) {
+ if (pluginDetail == null) {
+ return null;
+ }
+
+ return pluginDetail.getValueString(COUNTRY_KEY);
+ }
+
+ public static String getCardType(@Nullable final PaymentMethodPlugin pluginDetail) {
+ if (pluginDetail == null) {
+ return null;
+ }
+
+ return pluginDetail.getValueString(CARD_TYPE_KEY);
+ }
+
+ public static String getPaymentMethodType(@Nullable final PaymentMethodPlugin pluginDetail) {
+ if (pluginDetail == null) {
+ return null;
+ }
+
+ return pluginDetail.getValueString(TYPE_KEY);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/setup/AnalyticsModule.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/setup/AnalyticsModule.java
new file mode 100644
index 0000000..a2fa2c0
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/setup/AnalyticsModule.java
@@ -0,0 +1,106 @@
+/*
+ * 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.setup;
+
+import org.skife.config.ConfigSource;
+
+import com.ning.billing.analytics.api.AnalyticsService;
+import com.ning.billing.analytics.api.sanity.AnalyticsSanityApi;
+import com.ning.billing.analytics.api.user.AnalyticsUserApi;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsListener;
+import com.ning.billing.osgi.bundles.analytics.BusinessAccountDao;
+import com.ning.billing.osgi.bundles.analytics.BusinessSubscriptionTransitionDao;
+import com.ning.billing.osgi.bundles.analytics.BusinessTagDao;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultAnalyticsService;
+import com.ning.billing.osgi.bundles.analytics.api.sanity.DefaultAnalyticsSanityApi;
+import com.ning.billing.osgi.bundles.analytics.api.user.DefaultAnalyticsUserApi;
+import com.ning.billing.osgi.bundles.analytics.dao.AnalyticsDao;
+import com.ning.billing.osgi.bundles.analytics.dao.AnalyticsSanityDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceItemSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessOverdueStatusSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSqlProvider;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.DefaultAnalyticsDao;
+import com.ning.billing.osgi.bundles.analytics.dao.DefaultAnalyticsSanityDao;
+
+import com.google.inject.AbstractModule;
+
+public class AnalyticsModule extends AbstractModule {
+
+ protected final ConfigSource configSource;
+
+ public AnalyticsModule(final ConfigSource configSource) {
+ this.configSource = configSource;
+ }
+
+ @Override
+ protected void configure() {
+ installAnalyticsUserApi();
+ installAnalyticsSanityApi();
+
+ installAnalyticsDao();
+ installAnalyticsSqlDao();
+
+ bind(AnalyticsListener.class).asEagerSingleton();
+ bind(AnalyticsService.class).to(DefaultAnalyticsService.class).asEagerSingleton();
+ }
+
+ protected void installAnalyticsUserApi() {
+ bind(DefaultAnalyticsUserApi.class).asEagerSingleton();
+ bind(AnalyticsUserApi.class).to(DefaultAnalyticsUserApi.class).asEagerSingleton();
+ }
+
+ protected void installAnalyticsSanityApi() {
+ bind(AnalyticsSanityApi.class).to(DefaultAnalyticsSanityApi.class).asEagerSingleton();
+ }
+
+ protected void installAnalyticsDao() {
+ bind(AnalyticsDao.class).to(DefaultAnalyticsDao.class).asEagerSingleton();
+ bind(AnalyticsSanityDao.class).to(DefaultAnalyticsSanityDao.class).asEagerSingleton();
+ bind(BusinessSubscriptionTransitionDao.class).asEagerSingleton();
+ bind(BusinessAccountDao.class).asEagerSingleton();
+ bind(BusinessTagDao.class).asEagerSingleton();
+ }
+
+ protected void installAnalyticsSqlDao() {
+ bind(BusinessAccountSqlDao.class).toProvider(new BusinessSqlProvider<BusinessAccountSqlDao>(BusinessAccountSqlDao.class));
+ bind(BusinessAccountTagSqlDao.class).toProvider(new BusinessSqlProvider<BusinessAccountTagSqlDao>(BusinessAccountTagSqlDao.class));
+ bind(BusinessAccountFieldSqlDao.class).toProvider(new BusinessSqlProvider<BusinessAccountFieldSqlDao>(BusinessAccountFieldSqlDao.class));
+ bind(BusinessInvoiceFieldSqlDao.class).toProvider(new BusinessSqlProvider<BusinessInvoiceFieldSqlDao>(BusinessInvoiceFieldSqlDao.class));
+ bind(BusinessInvoiceItemSqlDao.class).toProvider(new BusinessSqlProvider<BusinessInvoiceItemSqlDao>(BusinessInvoiceItemSqlDao.class));
+ bind(BusinessInvoicePaymentFieldSqlDao.class).toProvider(new BusinessSqlProvider<BusinessInvoicePaymentFieldSqlDao>(BusinessInvoicePaymentFieldSqlDao.class));
+ bind(BusinessInvoicePaymentSqlDao.class).toProvider(new BusinessSqlProvider<BusinessInvoicePaymentSqlDao>(BusinessInvoicePaymentSqlDao.class));
+ bind(BusinessInvoicePaymentTagSqlDao.class).toProvider(new BusinessSqlProvider<BusinessInvoicePaymentTagSqlDao>(BusinessInvoicePaymentTagSqlDao.class));
+ bind(BusinessInvoiceSqlDao.class).toProvider(new BusinessSqlProvider<BusinessInvoiceSqlDao>(BusinessInvoiceSqlDao.class));
+ bind(BusinessInvoiceTagSqlDao.class).toProvider(new BusinessSqlProvider<BusinessInvoiceTagSqlDao>(BusinessInvoiceTagSqlDao.class));
+ bind(BusinessOverdueStatusSqlDao.class).toProvider(new BusinessSqlProvider<BusinessOverdueStatusSqlDao>(BusinessOverdueStatusSqlDao.class));
+ bind(BusinessSubscriptionTransitionFieldSqlDao.class).toProvider(new BusinessSqlProvider<BusinessSubscriptionTransitionFieldSqlDao>(BusinessSubscriptionTransitionFieldSqlDao.class));
+ bind(BusinessSubscriptionTransitionSqlDao.class).toProvider(new BusinessSqlProvider<BusinessSubscriptionTransitionSqlDao>(BusinessSubscriptionTransitionSqlDao.class));
+ bind(BusinessSubscriptionTransitionTagSqlDao.class).toProvider(new BusinessSqlProvider<BusinessSubscriptionTransitionTagSqlDao>(BusinessSubscriptionTransitionTagSqlDao.class));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/utils/Rounder.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/utils/Rounder.java
new file mode 100644
index 0000000..fc32b85
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/utils/Rounder.java
@@ -0,0 +1,36 @@
+/*
+ * 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.utils;
+
+import java.math.BigDecimal;
+
+public class Rounder {
+
+ public static final int SCALE = 4;
+
+ // Static only
+ private Rounder() {
+ }
+
+ public static double round(final BigDecimal decimal) {
+ if (decimal == null) {
+ return 0;
+ } else {
+ return decimal.setScale(SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.sql.stg
new file mode 100644
index 0000000..4040115
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/AnalyticsSanitySqlDao.sql.stg
@@ -0,0 +1,301 @@
+group AnalyticsSanitySqlDao;
+
+CHECK_TENANT(prefix) ::= "<prefix>tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT(prefix) ::= "AND <CHECK_TENANT(prefix)>"
+
+checkBstMatchesSubscriptionEvents() ::= <<
+select distinct
+ account_id
+from (
+ select
+ account_id
+ , sum(per_event_check) account_check_left
+ , count(*) account_check_right
+ from (
+ select
+ account_id
+ , account_key_check and app_id and date_type and slug per_event_check
+ from (
+ select
+ q.account_key
+ , q.account_id
+ , b_account_key = account_key account_key_check
+ , b_app_id = app_id app_id
+ , case
+ when b_event like 'CANCEL_%' then b_req_dt = req_dt
+ when b_event like 'SYSTEM_CANCEL_%' then b_req_dt = eff_dt
+ else b_req_dt = req_dt and b_eff_dt = eff_dt
+ end date_type
+ , coalesce(b_slug = slug, 1) slug
+ from (
+ select
+ bst.total_ordering record_id
+ , bst.account_key b_account_key
+ , bst.external_key b_app_id
+ , bst.event b_event
+ , bst.next_slug b_slug
+ , from_unixtime(bst.requested_timestamp / 1000) b_req_dt
+ , from_unixtime(bst.next_start_date / 1000) b_eff_dt
+ , a.external_key account_key
+ , a.id account_id
+ , b.external_key app_id
+ , s.id
+ , e.event_type
+ , e.user_type
+ , e.phase_name slug
+ , e.effective_date eff_dt
+ , e.requested_date req_dt
+ , from_unixtime(coalesce(bst.next_start_date, bst.requested_timestamp) / 1000) b_dt
+ from subscription_events e
+ join subscriptions s on e.subscription_id = s.id
+ join bundles b on s.bundle_id = b.id
+ join accounts a on b.account_id = a.id
+ join bst on bst.total_ordering = e.record_id
+ where
+ e.is_active = 1
+ and e.user_type != 'MIGRATE_BILLING'
+ <AND_CHECK_TENANT("e.")>
+ <AND_CHECK_TENANT("s.")>
+ <AND_CHECK_TENANT("b.")>
+ <AND_CHECK_TENANT("a.")>
+ <AND_CHECK_TENANT("bst.")>
+ order by e.record_id asc
+ ) q
+ ) p
+ ) r group by (account_id)
+) s
+where account_check_left != account_check_right
+;
+>>
+
+checkBiiMatchesInvoiceItems() ::= <<
+select distinct
+ account_id
+from (
+ select
+ id
+ , account_id
+ , start_date_check and end_date_check and amount_check and currency_check and linked_item_id_check and slug_check per_item_check
+ from (
+ select
+ ii.id
+ , ii.account_id
+ , ii.start_date = bii.start_date start_date_check
+ , coalesce(ii.end_date, bii.end_date) = bii.end_date end_date_check
+ , ii.amount = bii.amount amount_check
+ , ii.currency = bii.currency currency_check
+ , coalesce(ii.linked_item_id = bii.linked_item_id, 1) linked_item_id_check
+ , ii.phase_name = bii.slug slug_check
+ from invoice_items ii
+ join bii on ii.id = bii.item_id
+ where <CHECK_TENANT("ii.")>
+ <AND_CHECK_TENANT("bii.")>
+ ) p
+) q where !per_item_check
+;
+>>
+
+checkBipMatchesInvoicePayments() ::= <<
+select distinct
+ account_id
+from (
+ select
+ payment_id
+ , account_id
+ , amount_check and currency_check and payment_type_check and linked_invoice_payment_id_check and invoice_id_check total_check
+ from (
+ select
+ bip.payment_id
+ , a.id account_id
+ , bip.amount = ip.amount amount_check
+ , bip.currency = ip.currency currency_check
+ , bip.invoice_payment_type = ip.type payment_type_check
+ , bip.linked_invoice_payment_id = ip.linked_invoice_payment_id linked_invoice_payment_id_check
+ , bip.invoice_id = ip.invoice_id invoice_id_check
+ from bip
+ join invoice_payments ip on bip.payment_id = ip.id
+ join accounts a on a.record_id = ip.account_record_id
+ where <CHECK_TENANT("bip.")>
+ <AND_CHECK_TENANT("ip.")>
+ <AND_CHECK_TENANT("a.")>
+ ) p
+) q where !total_check
+;
+>>
+
+checkBinAmountPaidMatchesInvoicePayments() ::= <<
+select distinct
+ account_id
+from (
+ select
+ bin.invoice_id
+ , bin.account_id
+ , sum(ip.amount) = amount_paid amount_paid_check
+ from bin
+ join invoice_payments ip on bin.invoice_id = ip.invoice_id
+ where <CHECK_TENANT("bin.")>
+ <AND_CHECK_TENANT("ip.")>
+ group by ip.invoice_id, bin.account_id
+) p where !amount_paid_check
+;
+>>
+
+checkBinAmountChargedMatchesInvoicePayments() ::= <<
+select distinct
+ account_id
+from (
+ select
+ bin.invoice_id
+ , bin.account_id
+ , sum(ip.amount) = amount_charged amount_charged_check
+ from bin
+ join invoice_payments ip on bin.invoice_id = ip.invoice_id
+ where <CHECK_TENANT("bin.")>
+ <AND_CHECK_TENANT("ip.")>
+ group by ip.invoice_id, bin.account_id
+) p where !amount_charged_check
+;
+>>
+
+checkBinBiiBalanceConsistency() ::= <<
+select distinct
+ account_id
+from (
+ select
+ invoice_id
+ , account_id
+ , balance = amount_charged + total_adj_amount + total_cba - amount_paid balance_check
+ from (
+ select
+ bin.invoice_id
+ , bin.account_id
+ , bin.amount_paid
+ , bin.amount_charged
+ , bin.amount_credited
+ , bin.balance
+ , coalesce(total_adj_amount, 0) total_adj_amount
+ , coalesce(total_cba, 0) total_cba
+ from bin
+ left join (
+ select
+ bii.invoice_id
+ , sum(amount) total_adj_amount
+ from bii
+ join bin on bin.invoice_id = bii.invoice_id
+ where bii.item_type in ('CREDIT_ADJ', 'REFUND_ADJ', 'ITEM_ADJ')
+ <AND_CHECK_TENANT("bii.")>
+ <AND_CHECK_TENANT("bin.")>
+ group by (bii.invoice_id)
+ ) p on bin.invoice_id = p.invoice_id
+ left join (
+ select
+ q.invoice_id
+ , total_cba
+ from (
+ select
+ bii.invoice_id
+ , sum(amount) total_cba
+ from bii
+ join bin on bin.invoice_id = bii.invoice_id
+ where bii.item_type in ('CBA_ADJ')
+ <AND_CHECK_TENANT("bii.")>
+ <AND_CHECK_TENANT("bin.")>
+ group by (bii.invoice_id)
+ ) q
+ ) r on r.invoice_id = bin.invoice_id
+ where <CHECK_TENANT("bin.")>
+ ) s
+) t where !balance_check
+;
+>>
+
+checkBinBiiAmountCreditedConsistency() ::= <<
+select distinct
+ account_id
+from (
+ select
+ bii.invoice_id
+ , bin.account_id
+ , sum(amount) = bin.amount_credited credit_check
+ from bii
+ join bin on bin.invoice_id = bii.invoice_id
+ where bii.item_type in ('CREDIT_ADJ')
+ <AND_CHECK_TENANT("bii.")>
+ <AND_CHECK_TENANT("bin.")>
+ group by bii.invoice_id, bin.account_id
+) p where !credit_check
+;
+>>
+
+checkBacBinBiiConsistency() ::= <<
+select distinct
+ account_id
+from (
+ select
+ account_id
+ , total_invoice_balance_check and total_account_balance_check bac_check
+ from (
+ select
+ account_id
+ , total_invoice_balance_on_account = total_invoice_balance total_invoice_balance_check
+ , total_account_balance = total_invoice_balance_on_account - account_cba total_account_balance_check
+ from (
+ select
+ bac.account_id
+ , bac.total_invoice_balance total_invoice_balance_on_account
+ , sum(bin.balance) total_invoice_balance
+ , bac.balance total_account_balance
+ , coalesce(account_cba, 0) account_cba
+ from bac
+ -- some might not have cba items
+ left join (
+ select
+ bin.account_id
+ , sum(bii.amount) account_cba
+ from bac
+ join bin on bin.account_id = bac.account_id
+ join bii on bii.invoice_id = bin.invoice_id
+ where bii.item_type = 'CBA_ADJ'
+ <AND_CHECK_TENANT("bac.")>
+ <AND_CHECK_TENANT("bin.")>
+ <AND_CHECK_TENANT("bii.")>
+ group by (bin.account_id)
+ ) p on bac.account_id = p.account_id
+ left join bin on bin.account_id = bac.account_id
+ where <CHECK_TENANT("bac.")>
+ <AND_CHECK_TENANT("bin.")>
+ group by bac.account_id, account_cba
+ ) q
+ ) r
+) s where !bac_check
+;
+>>
+
+checkBacTagsMatchesTags() ::= <<
+select distinct
+ account_id
+from (
+ select
+ account_id
+ , b_tag_name = tag_name tag_name_check
+ from (
+ select
+ bt.account_id account_id
+ , bt.name b_tag_name
+ , case
+ when t.tag_definition_id = '00000000-0000-0000-0000-000000000001' then 'AUTO_PAY_OFF'
+ when t.tag_definition_id = '00000000-0000-0000-0000-000000000002' then 'AUTO_INVOICING_OFF'
+ when t.tag_definition_id = '00000000-0000-0000-0000-000000000003' then 'OVERDUE_ENFORCEMENT_OFF'
+ when t.tag_definition_id = '00000000-0000-0000-0000-000000000003' then 'WRITTEN_OFF'
+ else tdef.name
+ end tag_name
+ from bac_tags bt
+ join tags t on t.object_id = bt.account_id
+ left join tag_definitions tdef on t.tag_definition_id = tdef.id
+ where t.object_type = 'account'
+ <AND_CHECK_TENANT("bt.")>
+ <AND_CHECK_TENANT("t.")>
+ <AND_CHECK_TENANT("tdef.")>
+ ) p
+) q where ! tag_name_check;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.sql.stg
new file mode 100644
index 0000000..3715ed9
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountFieldSqlDao.sql.stg
@@ -0,0 +1,42 @@
+group BusinessAccountField;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getFieldsForAccountByKey(account_key) ::=<<
+select
+ account_id
+, account_key
+, name
+, value
+from bac_fields
+where account_key = :account_key
+<AND_CHECK_TENANT()>
+;
+>>
+
+addField(account_id, account_key, name, value) ::=<<
+insert into bac_fields (
+ account_id
+, account_key
+, name
+, value
+, account_record_id
+, tenant_record_id
+) values (
+ :account_id
+, :account_key
+, :name
+, :value
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeField(account_id, name) ::= <<
+delete from bac_fields where account_id = :account_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bac_fields where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.sql.stg
new file mode 100644
index 0000000..819a5c9
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountSqlDao.sql.stg
@@ -0,0 +1,123 @@
+group BusinessAccount;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getAccountsCreatedOverTime() ::= <<
+ select
+ date(from_unixtime(created_date / 1000)) day
+ -- TODO: use account_record_id, once populated
+ , count(record_id) count
+ from bac
+ where <CHECK_TENANT()>
+ group by 1
+ order by 1
+ ;
+>>
+
+getAccount(account_id) ::= <<
+ select
+ account_id
+ , account_key
+ , created_date
+ , updated_date
+ , balance
+ , name
+ , last_invoice_date
+ , total_invoice_balance
+ , last_payment_status
+ , payment_method
+ , credit_card_type
+ , billing_address_country
+ , currency
+ , tenant_record_id
+ from bac
+ where account_id=:account_id
+ <AND_CHECK_TENANT()>
+ limit 1
+ ;
+>>
+
+getAccountByKey(account_key) ::= <<
+ select
+ account_id
+ , account_key
+ , created_date
+ , updated_date
+ , balance
+ , name
+ , last_invoice_date
+ , total_invoice_balance
+ , last_payment_status
+ , payment_method
+ , credit_card_type
+ , billing_address_country
+ , currency
+ , tenant_record_id
+ from bac
+ where account_key=:account_key
+ <AND_CHECK_TENANT()>
+ limit 1
+ ;
+>>
+
+createAccount() ::= <<
+ insert into bac(
+ account_id
+ , account_key
+ , created_date
+ , updated_date
+ , balance
+ , name
+ , last_invoice_date
+ , total_invoice_balance
+ , last_payment_status
+ , payment_method
+ , credit_card_type
+ , billing_address_country
+ , currency
+ , account_record_id
+ , tenant_record_id
+ ) values (
+ :account_id
+ , :account_key
+ , :created_date
+ , :updated_date
+ , :balance
+ , :name
+ , :last_invoice_date
+ , :total_invoice_balance
+ , :last_payment_status
+ , :payment_method
+ , :credit_card_type
+ , :billing_address_country
+ , :currency
+ , :accountRecordId
+ , :tenantRecordId
+ );
+>>
+
+saveAccount() ::= <<
+ update bac set
+ updated_date=:updated_date
+ , balance=:balance
+ , name=:name
+ , last_invoice_date=:last_invoice_date
+ , total_invoice_balance=:total_invoice_balance
+ , last_payment_status=:last_payment_status
+ , payment_method=:payment_method
+ , credit_card_type=:credit_card_type
+ , billing_address_country=:billing_address_country
+ , currency=:currency
+ where account_id=:account_id
+ <AND_CHECK_TENANT()>
+ ;
+>>
+
+deleteAccount(account_id) ::= <<
+delete from bac where account_id = :account_id <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bac where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.sql.stg
new file mode 100644
index 0000000..5c4d142
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessAccountTagSqlDao.sql.stg
@@ -0,0 +1,39 @@
+group BusinessAccountTag;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getTagsForAccountByKey(account_key) ::=<<
+select
+ account_id
+, account_key
+, name
+from bac_tags
+where account_key = :account_key
+<AND_CHECK_TENANT()>
+;
+>>
+
+addTag(account_id, account_key, name) ::=<<
+insert into bac_tags (
+ account_id
+, account_key
+, name
+, account_record_id
+, tenant_record_id
+) values (
+ :account_id
+, :account_key
+, :name
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeTag(account_id, name) ::= <<
+delete from bac_tags where account_id = :account_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bac_tags where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.sql.stg
new file mode 100644
index 0000000..63e1ce0
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceFieldSqlDao.sql.stg
@@ -0,0 +1,39 @@
+group BusinessInvoiceField;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getFieldsForInvoice(invoice_id) ::=<<
+select
+ invoice_id
+, name
+, value
+from bin_fields
+where invoice_id = :invoice_id
+<AND_CHECK_TENANT()>
+;
+>>
+
+addField(invoice_id, name, value) ::=<<
+insert into bin_fields (
+ invoice_id
+, name
+, value
+, account_record_id
+, tenant_record_id
+) values (
+ :invoice_id
+, :name
+, :value
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeField(invoice_id, name, value) ::= <<
+delete from bin_fields where invoice_id = :invoice_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bin_tags where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.sql.stg
new file mode 100644
index 0000000..c15d21c
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceItemSqlDao.sql.stg
@@ -0,0 +1,141 @@
+group BusinessInvoiceItem;
+
+CHECK_TENANT(prefix) ::= "<prefix>tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT(prefix) ::= "AND <CHECK_TENANT(prefix)>"
+
+getInvoiceItem(item_id) ::= <<
+select
+ item_id
+, created_date
+, updated_date
+, invoice_id
+, item_type
+, external_key
+, product_name
+, product_type
+, product_category
+, slug
+, phase
+, billing_period
+, start_date
+, end_date
+, amount
+, currency
+, linked_item_id
+, tenant_record_id
+from bii
+where item_id = :item_id
+<AND_CHECK_TENANT()>
+limit 1
+;
+>>
+
+getInvoiceItemsForInvoice(invoice_id) ::= <<
+select
+ item_id
+, created_date
+, updated_date
+, invoice_id
+, item_type
+, external_key
+, product_name
+, product_type
+, product_category
+, slug
+, phase
+, billing_period
+, start_date
+, end_date
+, amount
+, currency
+, linked_item_id
+, tenant_record_id
+from bii
+where invoice_id = :invoice_id
+<AND_CHECK_TENANT()>
+order by created_date asc
+;
+>>
+
+getInvoiceItemsForBundleByKey(external_key) ::= <<
+select
+ item_id
+, created_date
+, updated_date
+, invoice_id
+, item_type
+, external_key
+, product_name
+, product_type
+, product_category
+, slug
+, phase
+, billing_period
+, start_date
+, end_date
+, amount
+, currency
+, linked_item_id
+, tenant_record_id
+from bii
+where external_key = :external_key
+<AND_CHECK_TENANT()>
+order by created_date asc
+;
+>>
+
+createInvoiceItem() ::= <<
+insert into bii (
+ item_id
+, created_date
+, updated_date
+, invoice_id
+, item_type
+, external_key
+, product_name
+, product_type
+, product_category
+, slug
+, phase
+, billing_period
+, start_date
+, end_date
+, amount
+, currency
+, linked_item_id
+, account_record_id
+, tenant_record_id
+) values (
+ :item_id
+, :created_date
+, :updated_date
+, :invoice_id
+, :item_type
+, :external_key
+, :product_name
+, :product_type
+, :product_category
+, :slug
+, :phase
+, :billing_period
+, :start_date
+, :end_date
+, :amount
+, :currency
+, :linked_item_id
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+deleteInvoiceItem(item_id) ::= <<
+delete from bii where item_id = :item_id <AND_CHECK_TENANT()>;
+>>
+
+deleteInvoiceItemsForAccount(account_id) ::= <<
+delete from bii where bii.invoice_id in (select invoice_id from bin where bin.account_id = :account_id <AND_CHECK_TENANT("bin.")> for update) <AND_CHECK_TENANT("bii.")>;
+>>
+
+test() ::= <<
+select 1 from bii where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.sql.stg
new file mode 100644
index 0000000..9bee903
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentFieldSqlDao.sql.stg
@@ -0,0 +1,39 @@
+group BusinessInvoicePaymentField;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getFieldsForInvoicePayment(payment_id) ::=<<
+select
+ payment_id
+, name
+, value
+from bip_fields
+where payment_id = :payment_id
+<AND_CHECK_TENANT()>
+;
+>>
+
+addField(payment_id, name, value) ::=<<
+insert into bip_fields (
+ payment_id
+, name
+, value
+, account_record_id
+, tenant_record_id
+) values (
+ :payment_id
+, :name
+, :value
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeField(payment_id, name) ::= <<
+delete from bip_fields where payment_id = :payment_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bip_fields where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.sql.stg
new file mode 100644
index 0000000..e358c09
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentSqlDao.sql.stg
@@ -0,0 +1,122 @@
+group BusinessInvoicePayment;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getInvoicePayment(payment_id) ::= <<
+select
+ payment_id
+, created_date
+, updated_date
+, ext_first_payment_ref_id
+, ext_second_payment_ref_id
+, account_key
+, invoice_id
+, effective_date
+, amount
+, currency
+, payment_error
+, processing_status
+, requested_amount
+, plugin_name
+, payment_type
+, payment_method
+, card_type
+, card_country
+, invoice_payment_type
+, linked_invoice_payment_id
+, tenant_record_id
+from bip
+where payment_id = :payment_id
+<AND_CHECK_TENANT()>
+limit 1
+;
+>>
+
+getInvoicePaymentsForAccountByKey(account_key) ::= <<
+select
+ payment_id
+, created_date
+, updated_date
+, ext_first_payment_ref_id
+, ext_second_payment_ref_id
+, account_key
+, invoice_id
+, effective_date
+, amount
+, currency
+, payment_error
+, processing_status
+, requested_amount
+, plugin_name
+, payment_type
+, payment_method
+, card_type
+, card_country
+, invoice_payment_type
+, linked_invoice_payment_id
+, tenant_record_id
+from bip
+where account_key = :account_key
+<AND_CHECK_TENANT()>
+order by created_date asc
+;
+>>
+
+createInvoicePayment() ::= <<
+insert into bip (
+ payment_id
+, created_date
+, updated_date
+, ext_first_payment_ref_id
+, ext_second_payment_ref_id
+, account_key
+, invoice_id
+, effective_date
+, amount
+, currency
+, payment_error
+, processing_status
+, requested_amount
+, plugin_name
+, payment_type
+, payment_method
+, card_type
+, card_country
+, invoice_payment_type
+, linked_invoice_payment_id
+, account_record_id
+, tenant_record_id
+) values (
+ :payment_id
+, :created_date
+, :updated_date
+, :ext_first_payment_ref_id
+, :ext_second_payment_ref_id
+, :account_key
+, :invoice_id
+, :effective_date
+, :amount
+, :currency
+, :payment_error
+, :processing_status
+, :requested_amount
+, :plugin_name
+, :payment_type
+, :payment_method
+, :card_type
+, :card_country
+, :invoice_payment_type
+, :linked_invoice_payment_id
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+deleteInvoicePayment(payment_id) ::= <<
+delete from bip where payment_id = :payment_id <AND_CHECK_TENANT()>
+>>
+
+test() ::= <<
+select 1 from bip where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.sql.stg
new file mode 100644
index 0000000..541a809
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoicePaymentTagSqlDao.sql.stg
@@ -0,0 +1,37 @@
+group BusinessInvoicePaymentTag;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getTagsForInvoicePayment(payment_id) ::=<<
+select
+ payment_id
+, name
+, tenant_record_id
+from bip_tags
+where payment_id = :payment_id
+<AND_CHECK_TENANT()>
+;
+>>
+
+addTag(payment_id, name) ::=<<
+insert into bip_tags (
+ payment_id
+, name
+, account_record_id
+, tenant_record_id
+) values (
+ :payment_id
+, :name
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeTag(payment_id, name) ::= <<
+delete from bip_tags where payment_id = :payment_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bip_tags where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.sql.stg
new file mode 100644
index 0000000..2d19030
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceSqlDao.sql.stg
@@ -0,0 +1,138 @@
+group BusinessInvoice;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getInvoice(invoice_id) ::= <<
+select
+ invoice_id
+, invoice_number
+, created_date
+, updated_date
+, account_id
+, account_key
+, invoice_date
+, target_date
+, currency
+, balance
+, amount_paid
+, amount_charged
+, amount_credited
+, tenant_record_id
+from bin
+where invoice_id = :invoice_id
+<AND_CHECK_TENANT()>
+limit 1
+;
+>>
+
+getInvoicesForAccount(account_id) ::= <<
+select
+ invoice_id
+, invoice_number
+, created_date
+, updated_date
+, account_id
+, account_key
+, invoice_date
+, target_date
+, currency
+, balance
+, amount_paid
+, amount_charged
+, amount_credited
+, tenant_record_id
+from bin
+where account_id = :account_id
+<AND_CHECK_TENANT()>
+order by created_date asc
+;
+>>
+
+getInvoicesForAccountByKey(account_key) ::= <<
+select
+ invoice_id
+, invoice_number
+, created_date
+, updated_date
+, account_id
+, account_key
+, invoice_date
+, target_date
+, currency
+, balance
+, amount_paid
+, amount_charged
+, amount_credited
+, tenant_record_id
+from bin
+where account_key = :account_key
+<AND_CHECK_TENANT()>
+order by created_date asc
+;
+>>
+
+createInvoice() ::= <<
+insert into bin (
+ invoice_id
+, invoice_number
+, created_date
+, updated_date
+, account_id
+, account_key
+, invoice_date
+, target_date
+, currency
+, balance
+, amount_paid
+, amount_charged
+, amount_credited
+, account_record_id
+, tenant_record_id
+) values (
+ :invoice_id
+, :invoice_number
+, :created_date
+, :updated_date
+, :account_id
+, :account_key
+, :invoice_date
+, :target_date
+, :currency
+, :balance
+, :amount_paid
+, :amount_charged
+, :amount_credited
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+updateInvoice() ::= <<
+update bin set
+ updated_date = :updated_date
+, invoice_number = :invoice_number
+, account_key = :account_key
+, invoice_date = :invoice_date
+, target_date = :target_date
+, currency = :currency
+, balance = :balance
+, amount_paid = :amount_paid
+, amount_charged = :amount_charged
+, amount_credited = :amount_credited
+where invoice_id = :invoice_id
+<AND_CHECK_TENANT()>
+;
+>>
+
+deleteInvoice(invoice_id) ::= <<
+delete from bin where invoice_id = :invoice_id <AND_CHECK_TENANT()>;
+>>
+
+deleteInvoicesForAccount(account_id) ::= <<
+delete from bin where account_id = :account_id <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bin where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.sql.stg
new file mode 100644
index 0000000..b2f5c0b
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceTagSqlDao.sql.stg
@@ -0,0 +1,37 @@
+group BusinessInvoiceTag;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getTagsForInvoice(invoice_id) ::=<<
+select
+ invoice_id
+, name
+, tenant_record_id
+from bin_tags
+where invoice_id = :invoice_id
+<AND_CHECK_TENANT()>
+;
+>>
+
+addTag(invoice_id, name) ::=<<
+insert into bin_tags (
+ invoice_id
+, name
+, account_record_id
+, tenant_record_id
+) values (
+ :invoice_id
+, :name
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeTag(invoice_id, name) ::= <<
+delete from bin_tags where invoice_id = :invoice_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bin_tags where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.sql.stg
new file mode 100644
index 0000000..59eb814
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessOverdueStatusSqlDao.sql.stg
@@ -0,0 +1,50 @@
+group BusinessOverdueStatus;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getOverdueStatusesForBundleByKey(external_key) ::= <<
+select
+ bundle_id
+, external_key
+, account_key
+, status
+, start_date
+, end_date
+, tenant_record_id
+from bos
+where external_key = :external_key
+<AND_CHECK_TENANT()>
+order by start_date asc
+;
+>>
+
+createOverdueStatus() ::= <<
+insert into bos (
+ bundle_id
+, external_key
+, account_key
+, status
+, start_date
+, end_date
+, account_record_id
+, tenant_record_id
+) values (
+ :bundle_id
+, :external_key
+, :account_key
+, :status
+, :start_date
+, :end_date
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+deleteOverdueStatusesForBundle(bundle_id) ::= <<
+delete from bos where bundle_id = :bundle_id <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bos where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.sql.stg
new file mode 100644
index 0000000..3528475
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionFieldSqlDao.sql.stg
@@ -0,0 +1,46 @@
+group BusinessSubscriptionTransitionField;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getFieldsForBusinessSubscriptionTransitionByKey(external_key) ::=<<
+select
+ bundle_id
+, external_key
+, account_key
+, name
+, value
+, tenant_record_id
+from bst_fields
+where external_key = :external_key
+<AND_CHECK_TENANT()>
+;
+>>
+
+addField(bundle_id, external_key, name, value) ::=<<
+insert into bst_fields (
+ bundle_id
+, external_key
+, account_key
+, name
+, value
+, account_record_id
+, tenant_record_id
+) values (
+ :bundle_id
+, :external_key
+, :account_key
+, :name
+, :value
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeField(bundle_id, name) ::= <<
+delete from bst_fields where bundle_id = :bundle_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bst_fields where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg
new file mode 100644
index 0000000..d88006e
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionSqlDao.sql.stg
@@ -0,0 +1,229 @@
+group BusinessSubscriptionTransition;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getSubscriptionsCreatedOverTime(product_type, slug) ::= <<
+ select
+ date(from_unixtime(requested_timestamp / 1000)) day
+ , count(record_id) count
+ from bst
+ where event in ('ADD_ADD_ON', 'ADD_BASE', 'ADD_STANDALONE')
+ and next_product_type = :product_type
+ and next_slug = :slug
+ <AND_CHECK_TENANT()>
+ group by 1
+ order by 1
+ ;
+>>
+
+getTransitionsByKey(external_key) ::= <<
+ select
+ total_ordering
+ , bundle_id
+ , external_key
+ , account_id
+ , account_key
+ , subscription_id
+ , requested_timestamp
+ , event
+ , prev_product_name
+ , prev_product_type
+ , prev_product_category
+ , prev_slug
+ , prev_phase
+ , prev_billing_period
+ , prev_price
+ , prev_price_list
+ , prev_mrr
+ , prev_currency
+ , prev_start_date
+ , prev_state
+ , next_product_name
+ , next_product_type
+ , next_product_category
+ , next_slug
+ , next_phase
+ , next_billing_period
+ , next_price
+ , next_price_list
+ , next_mrr
+ , next_currency
+ , next_start_date
+ , next_state
+ , tenant_record_id
+ from bst
+ where external_key=:external_key
+ <AND_CHECK_TENANT()>
+ order by requested_timestamp asc
+ ;
+>>
+
+getTransitionForSubscription(subscription_id) ::= <<
+ select
+ total_ordering
+ , bundle_id
+ , external_key
+ , account_id
+ , account_key
+ , subscription_id
+ , requested_timestamp
+ , event
+ , prev_product_name
+ , prev_product_type
+ , prev_product_category
+ , prev_slug
+ , prev_phase
+ , prev_billing_period
+ , prev_price
+ , prev_price_list
+ , prev_mrr
+ , prev_currency
+ , prev_start_date
+ , prev_state
+ , next_product_name
+ , next_product_type
+ , next_product_category
+ , next_slug
+ , next_phase
+ , next_billing_period
+ , next_price
+ , next_price_list
+ , next_mrr
+ , next_currency
+ , next_start_date
+ , next_state
+ , tenant_record_id
+ from bst
+ where subscription_id = :subscription_id
+ <AND_CHECK_TENANT()>
+ order by requested_timestamp asc
+ ;
+>>
+
+getTransitionsForAccount(account_id) ::= <<
+ select
+ total_ordering
+ , bundle_id
+ , external_key
+ , account_id
+ , account_key
+ , subscription_id
+ , requested_timestamp
+ , event
+ , prev_product_name
+ , prev_product_type
+ , prev_product_category
+ , prev_slug
+ , prev_phase
+ , prev_billing_period
+ , prev_price
+ , prev_price_list
+ , prev_mrr
+ , prev_currency
+ , prev_start_date
+ , prev_state
+ , next_product_name
+ , next_product_type
+ , next_product_category
+ , next_slug
+ , next_phase
+ , next_billing_period
+ , next_price
+ , next_price_list
+ , next_mrr
+ , next_currency
+ , next_start_date
+ , next_state
+ , tenant_record_id
+ from bst
+ where account_key = :account_key
+ <AND_CHECK_TENANT()>
+ order by requested_timestamp asc
+ ;
+>>
+
+createTransition() ::= <<
+ insert into bst(
+ total_ordering
+ , bundle_id
+ , external_key
+ , account_id
+ , account_key
+ , subscription_id
+ , requested_timestamp
+ , event
+ , prev_product_name
+ , prev_product_type
+ , prev_product_category
+ , prev_slug
+ , prev_phase
+ , prev_billing_period
+ , prev_price
+ , prev_price_list
+ , prev_mrr
+ , prev_currency
+ , prev_start_date
+ , prev_state
+ , next_product_name
+ , next_product_type
+ , next_product_category
+ , next_slug
+ , next_phase
+ , next_billing_period
+ , next_price
+ , next_price_list
+ , next_mrr
+ , next_currency
+ , next_start_date
+ , next_state
+ , account_record_id
+ , tenant_record_id
+ ) values (
+ :total_ordering
+ , :bundle_id
+ , :external_key
+ , :account_id
+ , :account_key
+ , :subscription_id
+ , :requested_timestamp
+ , :event
+ , :prev_product_name
+ , :prev_product_type
+ , :prev_product_category
+ , :prev_slug
+ , :prev_phase
+ , :prev_billing_period
+ , :prev_price
+ , :prev_price_list
+ , :prev_mrr
+ , :prev_currency
+ , :prev_start_date
+ , :prev_state
+ , :next_product_name
+ , :next_product_type
+ , :next_product_category
+ , :next_slug
+ , :next_phase
+ , :next_billing_period
+ , :next_price
+ , :next_price_list
+ , :next_mrr
+ , :next_currency
+ , :next_start_date
+ , :next_state
+ , :accountRecordId
+ , :tenantRecordId
+ );
+>>
+
+deleteTransitionsForBundle(bundle_id) ::= <<
+ delete from bst
+ where bundle_id=:bundle_id
+ <AND_CHECK_TENANT()>
+ ;
+>>
+
+test() ::= <<
+select 1 from bst where <CHECK_TENANT()> limit 1;
+>>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.sql.stg b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.sql.stg
new file mode 100644
index 0000000..bd89b0d
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/dao/BusinessSubscriptionTransitionTagSqlDao.sql.stg
@@ -0,0 +1,43 @@
+group BusinessSubscriptionTransitionTag;
+
+CHECK_TENANT() ::= "tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT() ::= "AND <CHECK_TENANT()>"
+
+getTagsForBusinessSubscriptionTransitionByKey(external_key) ::=<<
+select
+ bundle_id
+, external_key
+, account_key
+, name
+, tenant_record_id
+from bst_tags
+where external_key = :external_key
+<AND_CHECK_TENANT()>
+;
+>>
+
+addTag(bundle_id, external_key, name) ::=<<
+insert into bst_tags (
+ bundle_id
+, external_key
+, account_key
+, name
+, account_record_id
+, tenant_record_id
+) values (
+ :bundle_id
+, :external_key
+, :account_key
+, :name
+, :accountRecordId
+, :tenantRecordId
+);
+>>
+
+removeTag(bundle_id, name) ::= <<
+delete from bst_tags where bundle_id = :bundle_id and name = :name <AND_CHECK_TENANT()>;
+>>
+
+test() ::= <<
+select 1 from bst_tags where <CHECK_TENANT()> limit 1;
+>>
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
new file mode 100644
index 0000000..7c93a84
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/resources/com/ning/billing/osgi/bundles/analytics/ddl.sql
@@ -0,0 +1,259 @@
+/*! SET storage_engine=INNODB */;
+
+drop table if exists bst;
+create table bst (
+ record_id int(11) unsigned not null auto_increment
+, total_ordering bigint default 0
+, bundle_id char(36) not null
+, account_id char(36) not null
+, external_key varchar(50) not null comment 'Bundle external key'
+, account_key varchar(50) not null comment 'Account external key'
+, subscription_id char(36) not null
+, requested_timestamp bigint not null
+, event varchar(50) not null
+, prev_product_name varchar(50) default null
+, prev_product_type varchar(50) default null
+, prev_product_category varchar(50) default null
+, prev_slug varchar(50) default null
+, prev_phase varchar(50) default null
+, prev_billing_period varchar(50) default null
+, prev_price numeric(10, 4) default 0
+, prev_price_list varchar(50) default null
+, prev_mrr numeric(10, 4) default 0
+, prev_currency varchar(50) default null
+, prev_start_date bigint default null
+, prev_state varchar(50) default null
+, next_product_name varchar(50) default null
+, next_product_type varchar(50) default null
+, next_product_category varchar(50) default null
+, next_slug varchar(50) default null
+, next_phase varchar(50) default null
+, next_billing_period varchar(50) default null
+, next_price numeric(10, 4) default 0
+, next_price_list varchar(50) default null
+, next_mrr numeric(10, 4) default 0
+, next_currency varchar(50) default null
+, next_start_date bigint default null
+, next_state varchar(50) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bst_key_index on bst (external_key, requested_timestamp asc);
+create index bst_tenant_account_record_id on bst(tenant_record_id, account_record_id);
+
+drop table if exists bac;
+create table bac (
+ record_id int(11) unsigned not null auto_increment
+, account_id char(36) not null
+, account_key varchar(50) not null
+, name varchar(100) not null
+, created_date bigint not null
+, updated_date bigint not null
+, balance numeric(10, 4) default 0
+, last_invoice_date date default null
+, total_invoice_balance numeric(10, 4) default 0
+, last_payment_status varchar(255) default null
+, payment_method varchar(50) default null
+, credit_card_type varchar(50) default null
+, billing_address_country varchar(50) default null
+, currency char(50) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create unique index bac_key_index on bac (account_key);
+create index bac_tenant_account_record_id on bac(tenant_record_id, account_record_id);
+
+drop table if exists bin;
+create table bin (
+ record_id int(11) unsigned not null auto_increment
+, invoice_id char(36) not null
+, invoice_number bigint default null
+, created_date bigint not null
+, updated_date bigint not null
+, account_id char(36) not null
+, account_key varchar(50) not null
+, invoice_date date not null
+, target_date date not null
+, currency char(50) not null
+, balance numeric(10, 4) default 0 comment 'amount_charged - amount_paid - amount_credited'
+, amount_paid numeric(10, 4) default 0 comment 'Sums of the successful payments made for this invoice minus the refunds associated with this invoice'
+, amount_charged numeric(10, 4) default 0 comment 'Sums of the invoice items amount'
+, amount_credited numeric(10, 4) default 0 comment 'Sums of the credit items'
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create unique index bin_key_index on bin (invoice_id);
+create index bin_tenant_account_record_id on bin(tenant_record_id, account_record_id);
+
+drop table if exists bii;
+create table bii (
+ record_id int(11) unsigned not null auto_increment
+, item_id char(36) not null
+, created_date bigint not null
+, updated_date bigint not null
+, invoice_id char(36) not null
+, item_type char(50) not null comment 'e.g. FIXED or RECURRING'
+, external_key varchar(50) default null comment 'Bundle external key (could be null for certain items)'
+, product_name varchar(50) default null
+, product_type varchar(50) default null
+, product_category varchar(50) default null
+, slug varchar(50) default null
+, phase varchar(50) default null
+, billing_period varchar(50) default null
+, start_date date default null
+, end_date date default null
+, amount numeric(10, 4) default 0
+, currency char(50) default null
+, linked_item_id char(36) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create unique index bii_key_index on bii (item_id);
+create index bii_tenant_account_record_id on bii(tenant_record_id, account_record_id);
+
+drop table if exists bip;
+create table bip (
+ record_id int(11) unsigned not null auto_increment
+, payment_id char(36) not null
+, created_date bigint not null
+, updated_date bigint not null
+, ext_first_payment_ref_id varchar(255) default null
+, ext_second_payment_ref_id varchar(255) default null
+, account_key varchar(50) not null comment 'Account external key'
+, invoice_id char(36) not null
+, effective_date bigint default null
+, amount numeric(10, 4) default 0
+, currency char(50) default null
+, payment_error varchar(255) default null
+, processing_status varchar(50) default null
+, requested_amount numeric(10, 4) default 0
+, plugin_name varchar(50) default null
+, payment_type varchar(50) default null
+, payment_method varchar(50) default null
+, card_type varchar(50) default null
+, card_country varchar(50) default null
+, invoice_payment_type varchar(50) default null
+, linked_invoice_payment_id char(36) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create unique index bip_key_index on bip (payment_id);
+create index bip_tenant_account_record_id on bip(tenant_record_id, account_record_id);
+
+drop table if exists bos;
+create table bos (
+ record_id int(11) unsigned not null auto_increment
+, bundle_id char(36) not null
+, external_key varchar(50) not null comment 'Bundle external key'
+, account_key varchar(50) not null comment 'Account external key'
+, status varchar(50) not null
+, start_date bigint default null
+, end_date bigint default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bos_tenant_account_record_id on bos(tenant_record_id, account_record_id);
+
+drop table if exists bac_tags;
+create table bac_tags (
+ record_id int(11) unsigned not null auto_increment
+, account_id char(36) not null
+, account_key varchar(50) not null comment 'Account external key'
+, name varchar(50) not null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bac_tags_tenant_account_record_id on bac_tags(tenant_record_id, account_record_id);
+
+drop table if exists bac_fields;
+create table bac_fields (
+ record_id int(11) unsigned not null auto_increment
+, account_id char(36) not null
+, account_key varchar(50) not null comment 'Account external key'
+, name varchar(50) not null
+, value varchar(255) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bac_fields_tenant_account_record_id on bac_fields(tenant_record_id, account_record_id);
+
+drop table if exists bst_tags;
+create table bst_tags (
+ record_id int(11) unsigned not null auto_increment
+, bundle_id char(36) not null
+, external_key varchar(50) not null comment 'Bundle external key'
+, account_key varchar(50) not null comment 'Account external key'
+, name varchar(50) not null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bst_tags_tenant_account_record_id on bst_tags(tenant_record_id, account_record_id);
+
+drop table if exists bst_fields;
+create table bst_fields (
+ record_id int(11) unsigned not null auto_increment
+, bundle_id char(36) not null
+, external_key varchar(50) not null comment 'Bundle external key'
+, account_key varchar(50) not null comment 'Account external key'
+, name varchar(50) not null
+, value varchar(255) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bst_fields_tenant_account_record_id on bst_fields(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
+, invoice_id char(36) not null
+, name varchar(50) not null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bin_tags_tenant_account_record_id on bin_tags(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
+, invoice_id char(36) not null
+, name varchar(50) not null
+, value varchar(255) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bin_fields_tenant_account_record_id on bin_fields(tenant_record_id, account_record_id);
+
+drop table if exists bip_tags;
+create table bip_tags (
+ record_id int(11) unsigned not null auto_increment
+, payment_id char(36) not null
+, name varchar(50) not null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bip_tags_tenant_account_record_id on bip_tags(tenant_record_id, account_record_id);
+
+drop table if exists bip_fields;
+create table bip_fields (
+ record_id int(11) unsigned not null auto_increment
+, payment_id char(36) not null
+, name varchar(50) not null
+, value varchar(255) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+);
+create index bip_fields_tenant_account_record_id on bip_fields(tenant_record_id, account_record_id);
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
new file mode 100644
index 0000000..e096376
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java
@@ -0,0 +1,139 @@
+/*
+ * 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;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+
+import com.ning.billing.GuicyKillbillTestSuiteNoDB;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.analytics.api.user.AnalyticsUserApi;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultAnalyticsService;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceItemSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessOverdueStatusSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.glue.TestAnalyticsModuleNoDB;
+import com.ning.billing.payment.dao.PaymentDao;
+import com.ning.billing.util.glue.RealImplementation;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
+import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
+import com.ning.billing.util.svcsapi.bus.InternalBus;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+public abstract class AnalyticsTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
+
+ @Inject
+ @RealImplementation
+ protected AccountUserApi accountApi;
+ @Inject
+ protected AccountInternalApi accountInternalApi;
+ @Inject
+ protected AnalyticsUserApi analyticsUserApi;
+ @Inject
+ protected CatalogService catalogService;
+ @Inject
+ @RealImplementation
+ protected EntitlementUserApi entitlementApi;
+ @Inject
+ protected EntitlementInternalApi entitlementInternalApi;
+ @Inject
+ protected InvoiceUserApi invoiceApi;
+ @Inject
+ protected InvoiceDao realInvoiceDao;
+ @Inject
+ protected InvoiceInternalApi invoiceInternalApi;
+ @Inject
+ protected PaymentDao paymentDao;
+ @Inject
+ protected DefaultAnalyticsService service;
+ @Inject
+ protected InternalBus bus;
+ @Inject
+ protected BusinessAccountDao accountDao;
+ @Inject
+ protected BusinessAccountSqlDao accountSqlDao;
+ @Inject
+ protected BusinessAccountFieldSqlDao accountFieldSqlDao;
+ @Inject
+ protected BusinessAccountTagSqlDao accountTagSqlDao;
+ @Inject
+ protected BusinessInvoiceFieldSqlDao invoiceFieldSqlDao;
+ @Inject
+ protected BusinessInvoiceItemSqlDao invoiceItemSqlDao;
+ @Inject
+ protected BusinessInvoicePaymentFieldSqlDao invoicePaymentFieldSqlDao;
+ @Inject
+ protected BusinessInvoicePaymentSqlDao invoicePaymentSqlDao;
+ @Inject
+ protected BusinessInvoicePaymentTagSqlDao invoicePaymentTagSqlDao;
+ @Inject
+ protected BusinessInvoiceDao invoiceDao;
+ @Inject
+ protected BusinessInvoiceSqlDao invoiceSqlDao;
+ @Inject
+ protected BusinessInvoiceTagSqlDao invoiceTagSqlDao;
+ @Inject
+ protected BusinessOverdueStatusDao overdueStatusDao;
+ @Inject
+ protected BusinessOverdueStatusSqlDao overdueStatusSqlDao;
+ @Inject
+ protected BusinessSubscriptionTransitionFieldSqlDao subscriptionTransitionFieldSqlDao;
+ @Inject
+ protected BusinessSubscriptionTransitionTagSqlDao subscriptionTransitionTagSqlDao;
+ @Inject
+ protected BusinessSubscriptionTransitionDao subscriptionTransitionDao;
+ @Inject
+ protected BusinessSubscriptionTransitionSqlDao subscriptionTransitionSqlDao;
+ @Inject
+ protected BusinessTagDao tagDao;
+
+ @BeforeClass(groups = "fast")
+ protected void beforeClass() throws Exception {
+ final Injector injector = Guice.createInjector(new TestAnalyticsModuleNoDB(configSource));
+ injector.injectMembers(this);
+ }
+
+ @BeforeMethod(groups = "fast")
+ public void beforeMethod() throws Exception {
+ bus.start();
+ }
+
+ @AfterMethod(groups = "fast")
+ public void afterMethod() throws Exception {
+ bus.stop();
+ }
+}
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
new file mode 100644
index 0000000..ae239d4
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteWithEmbeddedDB.java
@@ -0,0 +1,153 @@
+/*
+ * 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;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+
+import com.ning.billing.GuicyKillbillTestSuiteWithEmbeddedDB;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.analytics.api.AnalyticsService;
+import com.ning.billing.analytics.api.user.AnalyticsUserApi;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.osgi.bundles.analytics.api.DefaultAnalyticsService;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceItemSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessOverdueStatusSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.glue.TestAnalyticsModuleWithEmbeddedDB;
+import com.ning.billing.payment.dao.PaymentDao;
+import com.ning.billing.util.glue.RealImplementation;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
+import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
+import com.ning.billing.util.svcsapi.bus.InternalBus;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+public abstract class AnalyticsTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteWithEmbeddedDB {
+
+ @Inject
+ @RealImplementation
+ protected AccountUserApi accountApi;
+ @Inject
+ protected AccountInternalApi accountInternalApi;
+ @Inject
+ protected AnalyticsUserApi analyticsUserApi;
+ @Inject
+ protected AnalyticsService analyticsService;
+ @Inject
+ protected CatalogService catalogService;
+ @Inject
+ @RealImplementation
+ protected EntitlementUserApi entitlementApi;
+ @Inject
+ protected EntitlementInternalApi entitlementInternalApi;
+ @Inject
+ protected InvoiceUserApi invoiceApi;
+ @Inject
+ protected InvoiceDao realInvoiceDao;
+ @Inject
+ protected InvoiceInternalApi invoiceInternalApi;
+ @Inject
+ protected PaymentDao paymentDao;
+ @Inject
+ protected DefaultAnalyticsService service;
+ @Inject
+ protected InternalBus bus;
+ @Inject
+ protected BusinessAccountDao accountDao;
+ @Inject
+ protected BusinessAccountSqlDao accountSqlDao;
+ @Inject
+ protected BusinessAccountFieldSqlDao accountFieldSqlDao;
+ @Inject
+ protected BusinessAccountTagSqlDao accountTagSqlDao;
+ @Inject
+ protected BusinessInvoiceFieldSqlDao invoiceFieldSqlDao;
+ @Inject
+ protected BusinessInvoiceItemSqlDao invoiceItemSqlDao;
+ @Inject
+ protected BusinessInvoicePaymentFieldSqlDao invoicePaymentFieldSqlDao;
+ @Inject
+ protected BusinessInvoicePaymentSqlDao invoicePaymentSqlDao;
+ @Inject
+ protected BusinessInvoicePaymentTagSqlDao invoicePaymentTagSqlDao;
+ @Inject
+ protected BusinessInvoiceDao invoiceDao;
+ @Inject
+ protected BusinessInvoiceSqlDao invoiceSqlDao;
+ @Inject
+ protected BusinessInvoiceTagSqlDao invoiceTagSqlDao;
+ @Inject
+ protected BusinessOverdueStatusDao overdueStatusDao;
+ @Inject
+ protected BusinessOverdueStatusSqlDao overdueStatusSqlDao;
+ @Inject
+ protected BusinessSubscriptionTransitionFieldSqlDao subscriptionTransitionFieldSqlDao;
+ @Inject
+ protected BusinessSubscriptionTransitionTagSqlDao subscriptionTransitionTagSqlDao;
+ @Inject
+ protected BusinessSubscriptionTransitionDao subscriptionTransitionDao;
+ @Inject
+ protected BusinessSubscriptionTransitionSqlDao subscriptionTransitionSqlDao;
+ @Inject
+ protected BusinessTagDao tagDao;
+
+ @BeforeClass(groups = "slow")
+ protected void beforeClass() throws Exception {
+ final Injector injector = Guice.createInjector(new TestAnalyticsModuleWithEmbeddedDB(configSource));
+ injector.injectMembers(this);
+ }
+
+ @BeforeMethod(groups = "slow")
+ public void beforeMethod() throws Exception {
+ super.beforeMethod();
+ bus.start();
+ restartAnalyticsService();
+ }
+
+ @AfterMethod(groups = "slow")
+ public void afterMethod() throws Exception {
+ bus.stop();
+ stopAnalyticsService();
+ }
+
+ private void restartAnalyticsService() throws Exception {
+ ((DefaultAnalyticsService) analyticsService).registerForNotifications();
+ }
+
+ private void stopAnalyticsService() throws Exception {
+ ((DefaultAnalyticsService) analyticsService).unregisterForNotifications();
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestAnalyticsService.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestAnalyticsService.java
new file mode 100644
index 0000000..2810f3e
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestAnalyticsService.java
@@ -0,0 +1,231 @@
+/*
+ * 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 java.util.UUID;
+import java.util.concurrent.Callable;
+
+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.account.api.Account;
+import com.ning.billing.account.api.user.DefaultAccountCreationEvent;
+import com.ning.billing.account.dao.AccountModelDao;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.MockPriceList;
+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.DefaultEffectiveSubscriptionEvent;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
+import com.ning.billing.entitlement.events.EntitlementEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.user.DefaultInvoiceCreationEvent;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
+import com.ning.billing.mock.MockAccountBuilder;
+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.payment.api.DefaultPaymentInfoEvent;
+import com.ning.billing.payment.api.PaymentMethod;
+import com.ning.billing.payment.api.PaymentStatus;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.events.AccountCreationInternalEvent;
+import com.ning.billing.util.events.EffectiveSubscriptionInternalEvent;
+import com.ning.billing.util.events.InvoiceCreationInternalEvent;
+import com.ning.billing.util.events.PaymentInfoInternalEvent;
+
+import com.google.common.collect.ImmutableList;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.testng.Assert.fail;
+
+public class TestAnalyticsService extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ final Product product = new MockProduct("platinum", "subscription", ProductCategory.BASE);
+ final Plan plan = new MockPlan("platinum-monthly", product);
+ final PlanPhase phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
+
+ private static final Long TOTAL_ORDERING = 11L;
+ private final String ACCOUNT_KEY = UUID.randomUUID().toString();
+ private final String BUNDLE_KEY = UUID.randomUUID().toString();
+ private static final Currency ACCOUNT_CURRENCY = Currency.EUR;
+ private static final BigDecimal INVOICE_AMOUNT = BigDecimal.valueOf(1243.11);
+ private final UUID bundleId = UUID.randomUUID();
+ private final UUID subscriptionId = UUID.randomUUID();
+
+ private EffectiveSubscriptionInternalEvent transition;
+
+ private AccountCreationInternalEvent accountCreationNotification;
+ private InvoiceCreationInternalEvent invoiceCreationNotification;
+ private PaymentInfoInternalEvent paymentInfoNotification;
+
+ @BeforeMethod(groups = "slow")
+ public void beforeMethod() throws Exception {
+ super.beforeMethod();
+ Mockito.when(catalogService.getFullCatalog()).thenReturn(new MockCatalog());
+
+ final PaymentMethod paymentMethod = Mockito.mock(PaymentMethod.class);
+ final UUID paymentMethodId = UUID.randomUUID();
+ Mockito.when(paymentMethod.getId()).thenReturn(paymentMethodId);
+ final Account account = new MockAccountBuilder(UUID.randomUUID())
+ .externalKey(ACCOUNT_KEY)
+ .currency(ACCOUNT_CURRENCY)
+ .paymentMethodId(paymentMethodId)
+ .build();
+ Mockito.when(accountInternalApi.getAccountById(Mockito.eq(account.getId()), Mockito.<InternalCallContext>any())).thenReturn(account);
+
+ try {
+ // Create events for the bus and expected results
+ createSubscriptionTransitionEvent(account);
+ createAccountCreationEvent(account);
+ createInvoiceAndPaymentCreationEvents(account);
+ } catch (Throwable t) {
+ fail("Initializing accounts failed.", t);
+ }
+ }
+
+ private void createSubscriptionTransitionEvent(final Account account) throws EntitlementUserApiException {
+ final DateTime effectiveTransitionTime = clock.getUTCNow();
+ final DateTime requestedTransitionTime = clock.getUTCNow();
+ final PriceList priceList = new MockPriceList().setName("something");
+
+ final SubscriptionBundle bundle = Mockito.mock(SubscriptionBundle.class);
+ Mockito.when(bundle.getId()).thenReturn(bundleId);
+ Mockito.when(bundle.getAccountId()).thenReturn(account.getId());
+ Mockito.when(bundle.getExternalKey()).thenReturn(BUNDLE_KEY);
+ Mockito.when(entitlementInternalApi.getBundleFromId(Mockito.eq(bundleId), Mockito.<InternalCallContext>any())).thenReturn(bundle);
+
+ final Subscription subscription = Mockito.mock(Subscription.class);
+ Mockito.when(subscription.getId()).thenReturn(subscriptionId);
+ Mockito.when(subscription.getBundleId()).thenReturn(bundleId);
+ Mockito.when(entitlementInternalApi.getSubscriptionFromId(Mockito.eq(subscriptionId), Mockito.<InternalCallContext>any())).thenReturn(subscription);
+ Mockito.when(entitlementInternalApi.getSubscriptionsForBundle(Mockito.eq(bundleId), Mockito.<InternalCallContext>any())).thenReturn(ImmutableList.<Subscription>of(subscription));
+
+ final EffectiveSubscriptionInternalEvent event = Mockito.mock(EffectiveSubscriptionInternalEvent.class);
+ Mockito.when(event.getEffectiveTransitionTime()).thenReturn(effectiveTransitionTime);
+ Mockito.when(event.getRequestedTransitionTime()).thenReturn(requestedTransitionTime);
+ Mockito.when(event.getTransitionType()).thenReturn(SubscriptionTransitionType.CREATE);
+ Mockito.when(entitlementInternalApi.getAllTransitions(Mockito.eq(subscription), Mockito.<InternalCallContext>any())).thenReturn(ImmutableList.<EffectiveSubscriptionInternalEvent>of(event));
+
+ // Create a subscription transition event
+ transition = new DefaultEffectiveSubscriptionEvent(new SubscriptionTransitionData(
+ UUID.randomUUID(),
+ subscriptionId,
+ bundleId,
+ EntitlementEvent.EventType.API_USER,
+ ApiEventType.CREATE,
+ requestedTransitionTime,
+ effectiveTransitionTime,
+ null,
+ null,
+ null,
+ null,
+ Subscription.SubscriptionState.ACTIVE,
+ plan,
+ phase,
+ priceList,
+ TOTAL_ORDERING,
+ null,
+ true), null, null, 1L, 1L);
+ }
+
+ private void createAccountCreationEvent(final Account account) {
+ accountCreationNotification = new DefaultAccountCreationEvent(new AccountModelDao(account.getId(), account), null, 1L, 1L);
+ }
+
+ private void createInvoiceAndPaymentCreationEvents(final Account account) {
+ final DefaultInvoice invoice = new DefaultInvoice(account.getId(), clock.getUTCToday(), clock.getUTCToday(), ACCOUNT_CURRENCY);
+ final FixedPriceInvoiceItem invoiceItem = new FixedPriceInvoiceItem(invoice.getId(), account.getId(), bundleId, subscriptionId, "somePlan", "somePhase", clock.getUTCToday(),
+ INVOICE_AMOUNT, ACCOUNT_CURRENCY);
+ invoice.addInvoiceItem(invoiceItem);
+ Mockito.when(invoiceInternalApi.getInvoicesByAccountId(Mockito.eq(account.getId()), Mockito.<InternalCallContext>any())).thenReturn(ImmutableList.<Invoice>of(invoice));
+
+ // It doesn't really matter what the events contain - the listener will go back to the db
+ invoiceCreationNotification = new DefaultInvoiceCreationEvent(invoice.getId(), account.getId(),
+ INVOICE_AMOUNT, ACCOUNT_CURRENCY, null, 1L, 1L);
+
+ paymentInfoNotification = new DefaultPaymentInfoEvent(account.getId(), invoice.getId(), null, INVOICE_AMOUNT, -1,
+ PaymentStatus.UNKNOWN, null, clock.getUTCNow(), 1L, 1L);
+ }
+
+ @Test(groups = "slow")
+ public void testRegisterForNotifications() throws Exception {
+ // Make sure the service has been instantiated
+ Assert.assertEquals(service.getName(), "analytics-service");
+
+ Assert.assertNull(accountSqlDao.getAccountByKey(ACCOUNT_KEY, internalCallContext));
+
+ // Send events and wait for the async part...
+ bus.post(accountCreationNotification, internalCallContext);
+ waitALittle(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return (accountSqlDao.getAccountByKey(ACCOUNT_KEY, internalCallContext) != null);
+ }
+ });
+
+ // Test subscriptions integration - this is just to exercise the code. It's hard to test the actual subscriptions
+ // as we would need to mock a bunch of APIs (see integration tests in Beatrix instead)
+ bus.post(transition, internalCallContext);
+ waitALittle(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return (subscriptionTransitionSqlDao.getTransitionsForAccount(ACCOUNT_KEY, internalCallContext).size() == 1);
+ }
+ });
+
+ // Test invoice integration - the account creation notification has triggered a BAC update
+ bus.post(invoiceCreationNotification, internalCallContext);
+ waitALittle(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ // Test invoice integration - the account creation notification has triggered a BAC update
+ return (accountSqlDao.getAccountByKey(ACCOUNT_KEY, internalCallContext).getTotalInvoiceBalance().compareTo(INVOICE_AMOUNT) == 0);
+ }
+ });
+
+ // Test payment integration - the fields have already been populated, just make sure the code is exercised
+ // It's hard to test the actual payments fields though in bac, since we should mock the plugin
+ bus.post(paymentInfoNotification, internalCallContext);
+ }
+
+ private void waitALittle(final Callable<Boolean> callable) {
+ try {
+ await().atMost(5, SECONDS).until(callable);
+ } catch (Exception e) {
+ Assert.fail("Exception in TestAnalyticsService", e);
+ }
+ }
+}
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
new file mode 100644
index 0000000..c7cb17d
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/user/TestDefaultAnalyticsUserApi.java
@@ -0,0 +1,94 @@
+/*
+ * 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.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.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscription;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionEvent;
+import com.ning.billing.osgi.bundles.analytics.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);
+ }
+}
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
new file mode 100644
index 0000000..07aa037
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestAnalyticsDao.java
@@ -0,0 +1,269 @@
+/*
+ * 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 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.model.BusinessAccountModelDao;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscription;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionEvent;
+import com.ning.billing.osgi.bundles.analytics.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);
+
+ 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));
+
+ // 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());
+
+ // ACCOUNT not found
+ Assert.assertNull(accountSqlDao.getAccountByKey("Doesn't exist", internalCallContext));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountFieldSqlDao.java
new file mode 100644
index 0000000..c664b30
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountFieldSqlDao.java
@@ -0,0 +1,90 @@
+/*
+ * 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.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountFieldModelDao;
+
+public class TestBusinessAccountFieldSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final UUID accountId = UUID.randomUUID();
+ final String accountKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 30);
+ final String value = UUID.randomUUID().toString();
+
+ // Verify initial state
+ Assert.assertEquals(accountFieldSqlDao.getFieldsForAccountByKey(accountKey, internalCallContext).size(), 0);
+ Assert.assertEquals(accountFieldSqlDao.removeField(accountId.toString(), name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(accountFieldSqlDao.addField(accountId.toString(), accountKey, name, value, internalCallContext), 1);
+ final List<BusinessAccountFieldModelDao> fieldsForAccount = accountFieldSqlDao.getFieldsForAccountByKey(accountKey, internalCallContext);
+ Assert.assertEquals(fieldsForAccount.size(), 1);
+
+ // Retrieve it
+ final BusinessAccountFieldModelDao accountField = fieldsForAccount.get(0);
+ Assert.assertEquals(accountField.getAccountId(), accountId);
+ Assert.assertEquals(accountField.getAccountKey(), accountKey);
+ Assert.assertEquals(accountField.getName(), name);
+ Assert.assertEquals(accountField.getValue(), value);
+
+ // Delete it
+ Assert.assertEquals(accountFieldSqlDao.removeField(accountId.toString(), name, internalCallContext), 1);
+ Assert.assertEquals(accountFieldSqlDao.getFieldsForAccountByKey(accountKey, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final UUID accountId1 = UUID.randomUUID();
+ final String accountKey1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 30);
+ final UUID accountId2 = UUID.randomUUID();
+ final String accountKey2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 30);
+
+ // Add a field to both accounts
+ Assert.assertEquals(accountFieldSqlDao.addField(accountId1.toString(), accountKey1, name1, UUID.randomUUID().toString(), internalCallContext), 1);
+ Assert.assertEquals(accountFieldSqlDao.addField(accountId2.toString(), accountKey2, name2, UUID.randomUUID().toString(), internalCallContext), 1);
+
+ Assert.assertEquals(accountFieldSqlDao.getFieldsForAccountByKey(accountKey1, internalCallContext).size(), 1);
+ Assert.assertEquals(accountFieldSqlDao.getFieldsForAccountByKey(accountKey2, internalCallContext).size(), 1);
+
+ // Remove the field for the first account
+ Assert.assertEquals(accountFieldSqlDao.removeField(accountId1.toString(), name1, internalCallContext), 1);
+
+ Assert.assertEquals(accountFieldSqlDao.getFieldsForAccountByKey(accountKey1, internalCallContext).size(), 0);
+ Assert.assertEquals(accountFieldSqlDao.getFieldsForAccountByKey(accountKey2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ accountFieldSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountTagSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountTagSqlDao.java
new file mode 100644
index 0000000..597adcc
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessAccountTagSqlDao.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;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessAccountTagModelDao;
+
+public class TestBusinessAccountTagSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final UUID accountId = UUID.randomUUID();
+ final String accountKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 20);
+
+ // Verify initial state
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey, internalCallContext).size(), 0);
+ Assert.assertEquals(accountTagSqlDao.removeTag(accountId.toString(), name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(accountTagSqlDao.addTag(accountId.toString(), accountKey, name, internalCallContext), 1);
+ final List<BusinessAccountTagModelDao> tagsForAccount = accountTagSqlDao.getTagsForAccountByKey(accountKey, internalCallContext);
+ Assert.assertEquals(tagsForAccount.size(), 1);
+
+ // Retrieve it
+ final BusinessAccountTagModelDao accountTag = tagsForAccount.get(0);
+ Assert.assertEquals(accountTag.getAccountId(), accountId);
+ Assert.assertEquals(accountTag.getAccountKey(), accountKey);
+ Assert.assertEquals(accountTag.getName(), name);
+
+ // Delete it
+ Assert.assertEquals(accountTagSqlDao.removeTag(accountId.toString(), name, internalCallContext), 1);
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final UUID accountId1 = UUID.randomUUID();
+ final String accountKey1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 20);
+ final UUID accountId2 = UUID.randomUUID();
+ final String accountKey2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 20);
+
+ // Add a tag to both accounts
+ Assert.assertEquals(accountTagSqlDao.addTag(accountId1.toString(), accountKey1, name1, internalCallContext), 1);
+ Assert.assertEquals(accountTagSqlDao.addTag(accountId2.toString(), accountKey2, name2, internalCallContext), 1);
+
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey1, internalCallContext).size(), 1);
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey2, internalCallContext).size(), 1);
+
+ // Remove the tag for the first account
+ Assert.assertEquals(accountTagSqlDao.removeTag(accountId1.toString(), name1, internalCallContext), 1);
+
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey1, internalCallContext).size(), 0);
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ accountTagSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceFieldSqlDao.java
new file mode 100644
index 0000000..234a7c9
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceFieldSqlDao.java
@@ -0,0 +1,86 @@
+/*
+ * 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.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceFieldModelDao;
+
+public class TestBusinessInvoiceFieldSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final String invoiceId = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 30);
+ final String value = UUID.randomUUID().toString();
+
+ // Verify initial state
+ Assert.assertEquals(invoiceFieldSqlDao.getFieldsForInvoice(invoiceId, internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceFieldSqlDao.removeField(invoiceId, name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(invoiceFieldSqlDao.addField(invoiceId, name, value, internalCallContext), 1);
+ final List<BusinessInvoiceFieldModelDao> fieldsForInvoice = invoiceFieldSqlDao.getFieldsForInvoice(invoiceId, internalCallContext);
+ Assert.assertEquals(fieldsForInvoice.size(), 1);
+
+ // Retrieve it
+ final BusinessInvoiceFieldModelDao invoiceField = fieldsForInvoice.get(0);
+ Assert.assertEquals(invoiceField.getInvoiceId().toString(), invoiceId);
+ Assert.assertEquals(invoiceField.getName(), name);
+ Assert.assertEquals(invoiceField.getValue(), value);
+
+ // Delete it
+ Assert.assertEquals(invoiceFieldSqlDao.removeField(invoiceId, name, internalCallContext), 1);
+ Assert.assertEquals(invoiceFieldSqlDao.getFieldsForInvoice(invoiceId, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final String invoiceId1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 30);
+ final String invoiceId2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 30);
+
+ // Add a field to both invoices
+ Assert.assertEquals(invoiceFieldSqlDao.addField(invoiceId1, name1, UUID.randomUUID().toString(), internalCallContext), 1);
+ Assert.assertEquals(invoiceFieldSqlDao.addField(invoiceId2, name2, UUID.randomUUID().toString(), internalCallContext), 1);
+
+ Assert.assertEquals(invoiceFieldSqlDao.getFieldsForInvoice(invoiceId1, internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceFieldSqlDao.getFieldsForInvoice(invoiceId2, internalCallContext).size(), 1);
+
+ // Remove the field for the first invoice
+ Assert.assertEquals(invoiceFieldSqlDao.removeField(invoiceId1, name1, internalCallContext), 1);
+
+ Assert.assertEquals(invoiceFieldSqlDao.getFieldsForInvoice(invoiceId1, internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceFieldSqlDao.getFieldsForInvoice(invoiceId2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ invoiceFieldSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceItemSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceItemSqlDao.java
new file mode 100644
index 0000000..d6997fb
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceItemSqlDao.java
@@ -0,0 +1,117 @@
+/*
+ * 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 java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+
+public class TestBusinessInvoiceItemSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final UUID invoiceId = UUID.randomUUID();
+ final String externalKey = UUID.randomUUID().toString();
+ final BusinessInvoiceItemModelDao invoiceItem = createInvoiceItem(invoiceId, externalKey);
+
+ // Verify initial state
+ Assert.assertNull(invoiceItemSqlDao.getInvoiceItem(invoiceItem.getItemId().toString(), internalCallContext));
+ Assert.assertEquals(invoiceItemSqlDao.deleteInvoiceItem(invoiceItem.getItemId().toString(), internalCallContext), 0);
+
+ // Add the invoice item
+ Assert.assertEquals(invoiceItemSqlDao.createInvoiceItem(invoiceItem, internalCallContext), 1);
+
+ // Retrieve it
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItem(invoiceItem.getItemId().toString(), internalCallContext), invoiceItem);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForBundleByKey(invoiceItem.getExternalKey(), internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForBundleByKey(invoiceItem.getExternalKey(), internalCallContext).get(0), invoiceItem);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceItem.getInvoiceId().toString(), internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceItem.getInvoiceId().toString(), internalCallContext).get(0), invoiceItem);
+
+ // Delete it
+ Assert.assertEquals(invoiceItemSqlDao.deleteInvoiceItem(invoiceItem.getItemId().toString(), internalCallContext), 1);
+ Assert.assertNull(invoiceItemSqlDao.getInvoiceItem(invoiceItem.getItemId().toString(), internalCallContext));
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForBundleByKey(invoiceItem.getExternalKey(), internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceItem.getInvoiceId().toString(), internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final UUID invoiceId1 = UUID.randomUUID();
+ final String externalKey1 = UUID.randomUUID().toString();
+ final BusinessInvoiceItemModelDao invoiceItem1 = createInvoiceItem(invoiceId1, externalKey1);
+ final UUID invoiceId2 = UUID.randomUUID();
+ final String externalKey2 = UUID.randomUUID().toString();
+ final BusinessInvoiceItemModelDao invoiceItem2 = createInvoiceItem(invoiceId2, externalKey2);
+
+ // Create both invoice items
+ Assert.assertEquals(invoiceItemSqlDao.createInvoiceItem(invoiceItem1, internalCallContext), 1);
+ Assert.assertEquals(invoiceItemSqlDao.createInvoiceItem(invoiceItem2, internalCallContext), 1);
+
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForBundleByKey(externalKey1, internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForBundleByKey(externalKey2, internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceId1.toString(), internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceId2.toString(), internalCallContext).size(), 1);
+
+ // Remove the first invoice item
+ Assert.assertEquals(invoiceItemSqlDao.deleteInvoiceItem(invoiceItem1.getItemId().toString(), internalCallContext), 1);
+
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForBundleByKey(externalKey1, internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForBundleByKey(externalKey2, internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceId1.toString(), internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceItemSqlDao.getInvoiceItemsForInvoice(invoiceId2.toString(), internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ invoiceItemSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+
+ private BusinessInvoiceItemModelDao createInvoiceItem(final UUID invoiceId, final String externalKey) {
+ final BigDecimal amount = BigDecimal.TEN;
+ final String billingPeriod = UUID.randomUUID().toString().substring(0, 20);
+ final DateTime createdDate = clock.getUTCNow();
+ final Currency currency = Currency.AUD;
+ final LocalDate endDate = clock.getUTCToday();
+ final UUID itemId = UUID.randomUUID();
+ final UUID linkedItemId = UUID.randomUUID();
+ final String itemType = UUID.randomUUID().toString().substring(0, 20);
+ final String phase = UUID.randomUUID().toString().substring(0, 20);
+ final String productCategory = UUID.randomUUID().toString().substring(0, 20);
+ final String productName = UUID.randomUUID().toString().substring(0, 20);
+ final String productType = UUID.randomUUID().toString().substring(0, 20);
+ final String slug = UUID.randomUUID().toString();
+ final LocalDate startDate = clock.getUTCToday();
+ final DateTime updatedDate = clock.getUTCNow();
+
+ return new BusinessInvoiceItemModelDao(amount, billingPeriod, createdDate, currency, endDate, externalKey, invoiceId, itemId,
+ linkedItemId, itemType, phase, productCategory, productName, productType, slug, startDate, updatedDate);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentFieldSqlDao.java
new file mode 100644
index 0000000..0c4b38d
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentFieldSqlDao.java
@@ -0,0 +1,86 @@
+/*
+ * 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.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentFieldModelDao;
+
+public class TestBusinessInvoicePaymentFieldSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final String paymentId = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 30);
+ final String value = UUID.randomUUID().toString();
+
+ // Verify initial state
+ Assert.assertEquals(invoicePaymentFieldSqlDao.getFieldsForInvoicePayment(paymentId, internalCallContext).size(), 0);
+ Assert.assertEquals(invoicePaymentFieldSqlDao.removeField(paymentId, name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(invoicePaymentFieldSqlDao.addField(paymentId, name, value, internalCallContext), 1);
+ final List<BusinessInvoicePaymentFieldModelDao> fieldsForInvoicePayment = invoicePaymentFieldSqlDao.getFieldsForInvoicePayment(paymentId, internalCallContext);
+ Assert.assertEquals(fieldsForInvoicePayment.size(), 1);
+
+ // Retrieve it
+ final BusinessInvoicePaymentFieldModelDao invoicePaymentField = fieldsForInvoicePayment.get(0);
+ Assert.assertEquals(invoicePaymentField.getPaymentId().toString(), paymentId);
+ Assert.assertEquals(invoicePaymentField.getName(), name);
+ Assert.assertEquals(invoicePaymentField.getValue(), value);
+
+ // Delete it
+ Assert.assertEquals(invoicePaymentFieldSqlDao.removeField(paymentId, name, internalCallContext), 1);
+ Assert.assertEquals(invoicePaymentFieldSqlDao.getFieldsForInvoicePayment(paymentId, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final String paymentId1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 30);
+ final String paymentId2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 30);
+
+ // Add a field to both invoice payments
+ Assert.assertEquals(invoicePaymentFieldSqlDao.addField(paymentId1, name1, UUID.randomUUID().toString(), internalCallContext), 1);
+ Assert.assertEquals(invoicePaymentFieldSqlDao.addField(paymentId2, name2, UUID.randomUUID().toString(), internalCallContext), 1);
+
+ Assert.assertEquals(invoicePaymentFieldSqlDao.getFieldsForInvoicePayment(paymentId1, internalCallContext).size(), 1);
+ Assert.assertEquals(invoicePaymentFieldSqlDao.getFieldsForInvoicePayment(paymentId2, internalCallContext).size(), 1);
+
+ // Remove the field for the first invoice payment
+ Assert.assertEquals(invoicePaymentFieldSqlDao.removeField(paymentId1, name1, internalCallContext), 1);
+
+ Assert.assertEquals(invoicePaymentFieldSqlDao.getFieldsForInvoicePayment(paymentId1, internalCallContext).size(), 0);
+ Assert.assertEquals(invoicePaymentFieldSqlDao.getFieldsForInvoicePayment(paymentId2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ invoicePaymentFieldSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentSqlDao.java
new file mode 100644
index 0000000..c8445c4
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentSqlDao.java
@@ -0,0 +1,118 @@
+/*
+ * 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 java.util.UUID;
+
+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.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentModelDao;
+
+public class TestBusinessInvoicePaymentSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final BusinessInvoicePaymentModelDao invoicePayment = createInvoicePayment(accountKey);
+
+ // Verify initial state
+ Assert.assertNull(invoicePaymentSqlDao.getInvoicePayment(invoicePayment.getPaymentId().toString(), internalCallContext));
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment.getAccountKey(), internalCallContext).size(), 0);
+
+ // Add the invoice payment
+ Assert.assertEquals(invoicePaymentSqlDao.createInvoicePayment(invoicePayment, internalCallContext), 1);
+
+ // Retrieve it
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePayment(invoicePayment.getPaymentId().toString(), internalCallContext), invoicePayment);
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment.getAccountKey(), internalCallContext).size(), 1);
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment.getAccountKey(), internalCallContext).get(0), invoicePayment);
+
+ // Delete it
+ Assert.assertEquals(invoicePaymentSqlDao.deleteInvoicePayment(invoicePayment.getPaymentId().toString(), internalCallContext), 1);
+ Assert.assertNull(invoicePaymentSqlDao.getInvoicePayment(invoicePayment.getPaymentId().toString(), internalCallContext));
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment.getAccountKey(), internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final String accountKey1 = UUID.randomUUID().toString();
+ final BusinessInvoicePaymentModelDao invoicePayment1 = createInvoicePayment(accountKey1);
+ final String accountKey2 = UUID.randomUUID().toString();
+ final BusinessInvoicePaymentModelDao invoicePayment2 = createInvoicePayment(accountKey2);
+
+ // Create both invoice payments
+ Assert.assertEquals(invoicePaymentSqlDao.createInvoicePayment(invoicePayment1, internalCallContext), 1);
+ Assert.assertEquals(invoicePaymentSqlDao.createInvoicePayment(invoicePayment2, internalCallContext), 1);
+
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePayment(invoicePayment1.getPaymentId().toString(), internalCallContext), invoicePayment1);
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePayment(invoicePayment2.getPaymentId().toString(), internalCallContext), invoicePayment2);
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment1.getAccountKey(), internalCallContext).size(), 1);
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment2.getAccountKey(), internalCallContext).size(), 1);
+
+ // Remove the first invoice payment
+ Assert.assertEquals(invoicePaymentSqlDao.deleteInvoicePayment(invoicePayment1.getPaymentId().toString(), internalCallContext), 1);
+
+ Assert.assertNull(invoicePaymentSqlDao.getInvoicePayment(invoicePayment1.getPaymentId().toString(), internalCallContext));
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePayment(invoicePayment2.getPaymentId().toString(), internalCallContext), invoicePayment2);
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment1.getAccountKey(), internalCallContext).size(), 0);
+ Assert.assertEquals(invoicePaymentSqlDao.getInvoicePaymentsForAccountByKey(invoicePayment2.getAccountKey(), internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ invoicePaymentSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+
+ private BusinessInvoicePaymentModelDao createInvoicePayment(final String accountKey) {
+ final BigDecimal amount = BigDecimal.ONE;
+ final String cardCountry = UUID.randomUUID().toString().substring(0, 20);
+ final String cardType = UUID.randomUUID().toString().substring(0, 20);
+ final DateTime createdDate = new DateTime(DateTimeZone.UTC);
+ final Currency currency = Currency.BRL;
+ final DateTime effectiveDate = new DateTime(DateTimeZone.UTC);
+ final UUID invoiceId = UUID.randomUUID();
+ final String paymentError = UUID.randomUUID().toString();
+ final UUID paymentId = UUID.randomUUID();
+ final String paymentMethod = UUID.randomUUID().toString().substring(0, 20);
+ final String paymentType = UUID.randomUUID().toString().substring(0, 20);
+ final String pluginName = UUID.randomUUID().toString().substring(0, 20);
+ final String processingStatus = UUID.randomUUID().toString();
+ final BigDecimal requestedAmount = BigDecimal.ZERO;
+ final DateTime updatedDate = new DateTime(DateTimeZone.UTC);
+ final String invoicePaymentType = UUID.randomUUID().toString().substring(0, 10);
+ final UUID linkedInvoicePaymentId = UUID.randomUUID();
+
+ return new BusinessInvoicePaymentModelDao(accountKey, amount,
+ cardCountry, cardType, createdDate,
+ currency, effectiveDate, invoiceId,
+ paymentError, paymentId, paymentMethod,
+ paymentType, pluginName, processingStatus,
+ requestedAmount, updatedDate, invoicePaymentType,
+ linkedInvoicePaymentId);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentTagSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentTagSqlDao.java
new file mode 100644
index 0000000..6ef7ab5
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoicePaymentTagSqlDao.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.dao;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoicePaymentTagModelDao;
+
+public class TestBusinessInvoicePaymentTagSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final String paymentId = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 20);
+
+ // Verify initial state
+ Assert.assertEquals(invoicePaymentTagSqlDao.getTagsForInvoicePayment(paymentId, internalCallContext).size(), 0);
+ Assert.assertEquals(invoicePaymentTagSqlDao.removeTag(paymentId, name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(invoicePaymentTagSqlDao.addTag(paymentId, name, internalCallContext), 1);
+ final List<BusinessInvoicePaymentTagModelDao> tagsForInvoicePayment = invoicePaymentTagSqlDao.getTagsForInvoicePayment(paymentId, internalCallContext);
+ Assert.assertEquals(tagsForInvoicePayment.size(), 1);
+
+ // Retrieve it
+ final BusinessInvoicePaymentTagModelDao invoicePaymentTag = tagsForInvoicePayment.get(0);
+ Assert.assertEquals(invoicePaymentTag.getPaymentId().toString(), paymentId);
+ Assert.assertEquals(invoicePaymentTag.getName(), name);
+
+ // Delete it
+ Assert.assertEquals(invoicePaymentTagSqlDao.removeTag(paymentId, name, internalCallContext), 1);
+ Assert.assertEquals(invoicePaymentTagSqlDao.getTagsForInvoicePayment(paymentId, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final String paymentId1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 20);
+ final String paymentId2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 20);
+
+ // Add a tag to both invoice payments
+ Assert.assertEquals(invoicePaymentTagSqlDao.addTag(paymentId1, name1, internalCallContext), 1);
+ Assert.assertEquals(invoicePaymentTagSqlDao.addTag(paymentId2, name2, internalCallContext), 1);
+
+ Assert.assertEquals(invoicePaymentTagSqlDao.getTagsForInvoicePayment(paymentId1, internalCallContext).size(), 1);
+ Assert.assertEquals(invoicePaymentTagSqlDao.getTagsForInvoicePayment(paymentId2, internalCallContext).size(), 1);
+
+ // Remove the tag for the first invoice payment
+ Assert.assertEquals(invoicePaymentTagSqlDao.removeTag(paymentId1, name1, internalCallContext), 1);
+
+ Assert.assertEquals(invoicePaymentTagSqlDao.getTagsForInvoicePayment(paymentId1, internalCallContext).size(), 0);
+ Assert.assertEquals(invoicePaymentTagSqlDao.getTagsForInvoicePayment(paymentId2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ invoicePaymentTagSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceSqlDao.java
new file mode 100644
index 0000000..61a7b44
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceSqlDao.java
@@ -0,0 +1,107 @@
+/*
+ * 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 java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceModelDao;
+
+public class TestBusinessInvoiceSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final UUID invoiceId = UUID.randomUUID();
+ final UUID accountId = UUID.randomUUID();
+ final String accountKey = UUID.randomUUID().toString();
+ final BusinessInvoiceModelDao invoice = createInvoice(accountId, invoiceId, accountKey);
+
+ // Verify initial state
+ Assert.assertNull(invoiceSqlDao.getInvoice(invoice.getInvoiceId().toString(), internalCallContext));
+ Assert.assertEquals(invoiceSqlDao.deleteInvoice(invoice.getInvoiceId().toString(), internalCallContext), 0);
+
+ // Add the invoice
+ Assert.assertEquals(invoiceSqlDao.createInvoice(invoice, internalCallContext), 1);
+
+ // Retrieve it
+ Assert.assertEquals(invoiceSqlDao.getInvoice(invoice.getInvoiceId().toString(), internalCallContext), invoice);
+ Assert.assertEquals(invoiceSqlDao.getInvoicesForAccount(invoice.getAccountId().toString(), internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceSqlDao.getInvoicesForAccount(invoice.getAccountId().toString(), internalCallContext).get(0), invoice);
+
+ // Delete it
+ Assert.assertEquals(invoiceSqlDao.deleteInvoice(invoice.getInvoiceId().toString(), internalCallContext), 1);
+ Assert.assertNull(invoiceSqlDao.getInvoice(invoice.getInvoiceId().toString(), internalCallContext));
+ Assert.assertEquals(invoiceSqlDao.getInvoicesForAccount(invoice.getAccountId().toString(), internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final UUID invoiceId1 = UUID.randomUUID();
+ final UUID accountId1 = UUID.randomUUID();
+ final String accountKey1 = UUID.randomUUID().toString();
+ final BusinessInvoiceModelDao invoice1 = createInvoice(invoiceId1, accountId1, accountKey1);
+ final UUID invoiceId2 = UUID.randomUUID();
+ final UUID accountId2 = UUID.randomUUID();
+ final String accountKey2 = UUID.randomUUID().toString();
+ final BusinessInvoiceModelDao invoice2 = createInvoice(invoiceId2, accountId2, accountKey2);
+
+ // Create both invoices
+ Assert.assertEquals(invoiceSqlDao.createInvoice(invoice1, internalCallContext), 1);
+ Assert.assertEquals(invoiceSqlDao.createInvoice(invoice2, internalCallContext), 1);
+
+ Assert.assertEquals(invoiceSqlDao.getInvoicesForAccount(accountId1.toString(), internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceSqlDao.getInvoicesForAccount(accountId2.toString(), internalCallContext).size(), 1);
+
+ // Remove the first invoice
+ Assert.assertEquals(invoiceSqlDao.deleteInvoice(invoice1.getInvoiceId().toString(), internalCallContext), 1);
+
+ Assert.assertEquals(invoiceSqlDao.getInvoicesForAccount(accountId1.toString(), internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceSqlDao.getInvoicesForAccount(accountId2.toString(), internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ invoiceSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+
+ private BusinessInvoiceModelDao createInvoice(final UUID invoiceId, final UUID accountId, final String accountKey) {
+ final BigDecimal amountCharged = BigDecimal.ZERO;
+ final BigDecimal amountCredited = BigDecimal.ONE;
+ final BigDecimal amountPaid = BigDecimal.TEN;
+ final BigDecimal balance = BigDecimal.valueOf(123L);
+ final DateTime createdDate = clock.getUTCNow();
+ final Currency currency = Currency.MXN;
+ final LocalDate invoiceDate = clock.getUTCToday();
+ final LocalDate targetDate = clock.getUTCToday();
+ final DateTime updatedDate = clock.getUTCNow();
+
+ return new BusinessInvoiceModelDao(accountId, accountKey, amountCharged, amountCredited, amountPaid, balance,
+ createdDate, currency, invoiceDate, invoiceId, 12, targetDate, updatedDate);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceTagSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceTagSqlDao.java
new file mode 100644
index 0000000..06118ba
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceTagSqlDao.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.dao;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceTagModelDao;
+
+public class TestBusinessInvoiceTagSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final String invoiceId = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 20);
+
+ // Verify initial state
+ Assert.assertEquals(invoiceTagSqlDao.getTagsForInvoice(invoiceId, internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceTagSqlDao.removeTag(invoiceId, name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(invoiceTagSqlDao.addTag(invoiceId, name, internalCallContext), 1);
+ final List<BusinessInvoiceTagModelDao> tagsForInvoice = invoiceTagSqlDao.getTagsForInvoice(invoiceId, internalCallContext);
+ Assert.assertEquals(tagsForInvoice.size(), 1);
+
+ // Retrieve it
+ final BusinessInvoiceTagModelDao invoiceTag = tagsForInvoice.get(0);
+ Assert.assertEquals(invoiceTag.getInvoiceId().toString(), invoiceId);
+ Assert.assertEquals(invoiceTag.getName(), name);
+
+ // Delete it
+ Assert.assertEquals(invoiceTagSqlDao.removeTag(invoiceId, name, internalCallContext), 1);
+ Assert.assertEquals(invoiceTagSqlDao.getTagsForInvoice(invoiceId, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final String invoiceId1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 20);
+ final String invoiceId2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 20);
+
+ // Add a tag to both invoices
+ Assert.assertEquals(invoiceTagSqlDao.addTag(invoiceId1, name1, internalCallContext), 1);
+ Assert.assertEquals(invoiceTagSqlDao.addTag(invoiceId2, name2, internalCallContext), 1);
+
+ Assert.assertEquals(invoiceTagSqlDao.getTagsForInvoice(invoiceId1, internalCallContext).size(), 1);
+ Assert.assertEquals(invoiceTagSqlDao.getTagsForInvoice(invoiceId2, internalCallContext).size(), 1);
+
+ // Remove the tag for the first invoice
+ Assert.assertEquals(invoiceTagSqlDao.removeTag(invoiceId1, name1, internalCallContext), 1);
+
+ Assert.assertEquals(invoiceTagSqlDao.getTagsForInvoice(invoiceId1, internalCallContext).size(), 0);
+ Assert.assertEquals(invoiceTagSqlDao.getTagsForInvoice(invoiceId2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ invoiceTagSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessOverdueStatusSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessOverdueStatusSqlDao.java
new file mode 100644
index 0000000..880fc49
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessOverdueStatusSqlDao.java
@@ -0,0 +1,75 @@
+/*
+ * 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.util.UUID;
+
+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.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessOverdueStatusModelDao;
+
+public class TestBusinessOverdueStatusSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCreate() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId = UUID.randomUUID();
+ final String externalKey = UUID.randomUUID().toString();
+ final BusinessOverdueStatusModelDao firstOverdueStatus = createOverdueStatus(accountKey, bundleId, externalKey);
+
+ // Verify initial state
+ Assert.assertEquals(overdueStatusSqlDao.getOverdueStatusesForBundleByKey(externalKey, internalCallContext).size(), 0);
+
+ // Add the overdue status
+ Assert.assertEquals(overdueStatusSqlDao.createOverdueStatus(firstOverdueStatus, internalCallContext), 1);
+
+ // Retrieve it
+ Assert.assertEquals(overdueStatusSqlDao.getOverdueStatusesForBundleByKey(externalKey, internalCallContext).size(), 1);
+ Assert.assertEquals(overdueStatusSqlDao.getOverdueStatusesForBundleByKey(externalKey, internalCallContext).get(0), firstOverdueStatus);
+
+ // Add a second one
+ final BusinessOverdueStatusModelDao secondOverdueStatus = createOverdueStatus(accountKey, bundleId, externalKey);
+ Assert.assertEquals(overdueStatusSqlDao.createOverdueStatus(secondOverdueStatus, internalCallContext), 1);
+
+ // Retrieve both
+ Assert.assertEquals(overdueStatusSqlDao.getOverdueStatusesForBundleByKey(externalKey, internalCallContext).size(), 2);
+ Assert.assertEquals(overdueStatusSqlDao.getOverdueStatusesForBundleByKey(externalKey, internalCallContext).get(0), firstOverdueStatus);
+ Assert.assertEquals(overdueStatusSqlDao.getOverdueStatusesForBundleByKey(externalKey, internalCallContext).get(1), secondOverdueStatus);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ overdueStatusSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+
+ private BusinessOverdueStatusModelDao createOverdueStatus(final String accountKey, final UUID bundleId, final String externalKey) {
+ final DateTime endDate = new DateTime(DateTimeZone.UTC);
+ final DateTime startDate = new DateTime(DateTimeZone.UTC);
+ final String status = UUID.randomUUID().toString();
+
+ return new BusinessOverdueStatusModelDao(accountKey, bundleId, endDate, externalKey, startDate, status);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionFieldSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionFieldSqlDao.java
new file mode 100644
index 0000000..c6e0618
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionFieldSqlDao.java
@@ -0,0 +1,92 @@
+/*
+ * 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.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionFieldModelDao;
+
+public class TestBusinessSubscriptionTransitionFieldSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId = UUID.randomUUID();
+ final String externalKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 30);
+ final String value = UUID.randomUUID().toString();
+
+ // Verify initial state
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.getFieldsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext).size(), 0);
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.removeField(bundleId.toString(), name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.addField(accountKey, bundleId.toString(), externalKey, name, value, internalCallContext), 1);
+ final List<BusinessSubscriptionTransitionFieldModelDao> fieldsForBusinessSubscriptionTransition = subscriptionTransitionFieldSqlDao.getFieldsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext);
+ Assert.assertEquals(fieldsForBusinessSubscriptionTransition.size(), 1);
+
+ // Retrieve it
+ final BusinessSubscriptionTransitionFieldModelDao subscriptionTransitionField = fieldsForBusinessSubscriptionTransition.get(0);
+ Assert.assertEquals(subscriptionTransitionField.getBundleId(), bundleId);
+ Assert.assertEquals(subscriptionTransitionField.getExternalKey(), externalKey);
+ Assert.assertEquals(subscriptionTransitionField.getName(), name);
+ Assert.assertEquals(subscriptionTransitionField.getValue(), value);
+
+ // Delete it
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.removeField(bundleId.toString(), name, internalCallContext), 1);
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.getFieldsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId1 = UUID.randomUUID();
+ final String externalKey1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 30);
+ final UUID bundleId2 = UUID.randomUUID();
+ final String externalKey2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 30);
+
+ // Add a field to both transitions
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.addField(accountKey, bundleId1.toString(), externalKey1, name1, UUID.randomUUID().toString(), internalCallContext), 1);
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.addField(accountKey, bundleId2.toString(), externalKey2, name2, UUID.randomUUID().toString(), internalCallContext), 1);
+
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.getFieldsForBusinessSubscriptionTransitionByKey(externalKey1, internalCallContext).size(), 1);
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.getFieldsForBusinessSubscriptionTransitionByKey(externalKey2, internalCallContext).size(), 1);
+
+ // Remove the field for the first transition
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.removeField(bundleId1.toString(), name1, internalCallContext), 1);
+
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.getFieldsForBusinessSubscriptionTransitionByKey(externalKey1, internalCallContext).size(), 0);
+ Assert.assertEquals(subscriptionTransitionFieldSqlDao.getFieldsForBusinessSubscriptionTransitionByKey(externalKey2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ subscriptionTransitionFieldSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionTagSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionTagSqlDao.java
new file mode 100644
index 0000000..9681b10
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessSubscriptionTransitionTagSqlDao.java
@@ -0,0 +1,90 @@
+/*
+ * 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.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteWithEmbeddedDB;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionTagModelDao;
+
+public class TestBusinessSubscriptionTransitionTagSqlDao extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testCRUD() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId = UUID.randomUUID();
+ final String externalKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString().substring(0, 20);
+
+ // Verify initial state
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext).size(), 0);
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.removeTag(bundleId.toString(), name, internalCallContext), 0);
+
+ // Add an entry
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.addTag(accountKey, bundleId.toString(), externalKey, name, internalCallContext), 1);
+ final List<BusinessSubscriptionTransitionTagModelDao> tagsForBusinessSubscriptionTransition = subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext);
+ Assert.assertEquals(tagsForBusinessSubscriptionTransition.size(), 1);
+
+ // Retrieve it
+ final BusinessSubscriptionTransitionTagModelDao subscriptionTransitionTag = tagsForBusinessSubscriptionTransition.get(0);
+ Assert.assertEquals(subscriptionTransitionTag.getBundleId(), bundleId);
+ Assert.assertEquals(subscriptionTransitionTag.getExternalKey(), externalKey);
+ Assert.assertEquals(subscriptionTransitionTag.getName(), name);
+
+ // Delete it
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.removeTag(bundleId.toString(), name, internalCallContext), 1);
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testSegmentation() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId1 = UUID.randomUUID();
+ final String externalKey1 = UUID.randomUUID().toString();
+ final String name1 = UUID.randomUUID().toString().substring(0, 20);
+ final UUID bundleId2 = UUID.randomUUID();
+ final String externalKey2 = UUID.randomUUID().toString();
+ final String name2 = UUID.randomUUID().toString().substring(0, 20);
+
+ // Add a tag to both transitions
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.addTag(accountKey, bundleId1.toString(), externalKey1, name1, internalCallContext), 1);
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.addTag(accountKey, bundleId2.toString(), externalKey2, name2, internalCallContext), 1);
+
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey1, internalCallContext).size(), 1);
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey2, internalCallContext).size(), 1);
+
+ // Remove the tag for the first transition
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.removeTag(bundleId1.toString(), name1, internalCallContext), 1);
+
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey1, internalCallContext).size(), 0);
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey2, internalCallContext).size(), 1);
+ }
+
+ @Test(groups = "slow")
+ public void testHealthCheck() throws Exception {
+ // HealthCheck test to make sure MySQL is setup properly
+ try {
+ subscriptionTransitionTagSqlDao.test(internalCallContext);
+ } catch (Throwable t) {
+ Assert.fail(t.toString());
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModule.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModule.java
new file mode 100644
index 0000000..e15543a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModule.java
@@ -0,0 +1,68 @@
+/*
+ * 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.glue;
+
+import org.mockito.Mockito;
+import org.skife.config.ConfigSource;
+
+import com.ning.billing.catalog.MockCatalogModule;
+import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.mock.glue.MockAccountModule;
+import com.ning.billing.mock.glue.MockEntitlementModule;
+import com.ning.billing.mock.glue.MockGlobalLockerModule;
+import com.ning.billing.mock.glue.MockInvoiceModule;
+import com.ning.billing.mock.glue.MockJunctionModule;
+import com.ning.billing.mock.glue.MockOverdueModule;
+import com.ning.billing.mock.glue.MockPaymentModule;
+import com.ning.billing.osgi.bundles.analytics.setup.AnalyticsModule;
+import com.ning.billing.payment.dao.PaymentDao;
+import com.ning.billing.util.glue.AuditModule;
+import com.ning.billing.util.glue.CacheModule;
+import com.ning.billing.util.glue.CallContextModule;
+import com.ning.billing.util.glue.CustomFieldModule;
+import com.ning.billing.util.glue.NotificationQueueModule;
+import com.ning.billing.util.glue.TagStoreModule;
+
+public class TestAnalyticsModule extends AnalyticsModule {
+
+ public TestAnalyticsModule(final ConfigSource configSource) {
+ super(configSource);
+ }
+
+ @Override
+ protected void configure() {
+ super.configure();
+
+ install(new AuditModule());
+ install(new CacheModule(configSource));
+ install(new CallContextModule());
+ install(new CustomFieldModule());
+ install(new MockAccountModule());
+ install(new MockCatalogModule());
+ install(new MockEntitlementModule());
+ install(new MockInvoiceModule());
+ install(new MockJunctionModule());
+ install(new MockOverdueModule());
+ install(new MockPaymentModule());
+ install(new MockGlobalLockerModule());
+ install(new NotificationQueueModule(configSource));
+ install(new TagStoreModule());
+
+ bind(InvoiceDao.class).toInstance(Mockito.mock(InvoiceDao.class));
+ bind(PaymentDao.class).toInstance(Mockito.mock(PaymentDao.class));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleNoDB.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleNoDB.java
new file mode 100644
index 0000000..12757fd
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleNoDB.java
@@ -0,0 +1,74 @@
+/*
+ * 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.glue;
+
+import org.mockito.Mockito;
+import org.skife.config.ConfigSource;
+
+import com.ning.billing.GuicyKillbillTestNoDBModule;
+import com.ning.billing.mock.glue.MockNonEntityDaoModule;
+import com.ning.billing.osgi.bundles.analytics.MockBusinessSubscriptionTransitionSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessAccountTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceItemSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoicePaymentTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessInvoiceTagSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessOverdueStatusSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionFieldSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionTagSqlDao;
+import com.ning.billing.util.bus.InMemoryBusModule;
+
+public class TestAnalyticsModuleNoDB extends TestAnalyticsModule {
+
+ public TestAnalyticsModuleNoDB(final ConfigSource configSource) {
+ super(configSource);
+ }
+
+ @Override
+ protected void installAnalyticsSqlDao() {
+ bind(BusinessSubscriptionTransitionSqlDao.class).to(MockBusinessSubscriptionTransitionSqlDao.class).asEagerSingleton();
+
+ bind(BusinessAccountSqlDao.class).toInstance(Mockito.mock(BusinessAccountSqlDao.class));
+ bind(BusinessAccountTagSqlDao.class).toInstance(Mockito.mock(BusinessAccountTagSqlDao.class));
+ bind(BusinessAccountFieldSqlDao.class).toInstance(Mockito.mock(BusinessAccountFieldSqlDao.class));
+ bind(BusinessInvoiceFieldSqlDao.class).toInstance(Mockito.mock(BusinessInvoiceFieldSqlDao.class));
+ bind(BusinessInvoiceItemSqlDao.class).toInstance(Mockito.mock(BusinessInvoiceItemSqlDao.class));
+ bind(BusinessInvoicePaymentFieldSqlDao.class).toInstance(Mockito.mock(BusinessInvoicePaymentFieldSqlDao.class));
+ bind(BusinessInvoicePaymentSqlDao.class).toInstance(Mockito.mock(BusinessInvoicePaymentSqlDao.class));
+ bind(BusinessInvoicePaymentTagSqlDao.class).toInstance(Mockito.mock(BusinessInvoicePaymentTagSqlDao.class));
+ bind(BusinessInvoiceSqlDao.class).toInstance(Mockito.mock(BusinessInvoiceSqlDao.class));
+ bind(BusinessInvoiceTagSqlDao.class).toInstance(Mockito.mock(BusinessInvoiceTagSqlDao.class));
+ bind(BusinessOverdueStatusSqlDao.class).toInstance(Mockito.mock(BusinessOverdueStatusSqlDao.class));
+ bind(BusinessSubscriptionTransitionFieldSqlDao.class).toInstance(Mockito.mock(BusinessSubscriptionTransitionFieldSqlDao.class));
+ bind(BusinessSubscriptionTransitionTagSqlDao.class).toInstance(Mockito.mock(BusinessSubscriptionTransitionTagSqlDao.class));
+ }
+
+ @Override
+ public void configure() {
+ super.configure();
+
+ install(new GuicyKillbillTestNoDBModule());
+ install(new MockNonEntityDaoModule());
+ install(new InMemoryBusModule(configSource));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleWithEmbeddedDB.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleWithEmbeddedDB.java
new file mode 100644
index 0000000..23b0dc1
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/glue/TestAnalyticsModuleWithEmbeddedDB.java
@@ -0,0 +1,39 @@
+/*
+ * 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.glue;
+
+import org.skife.config.ConfigSource;
+
+import com.ning.billing.GuicyKillbillTestWithEmbeddedDBModule;
+import com.ning.billing.util.glue.BusModule;
+import com.ning.billing.util.glue.NonEntityDaoModule;
+
+public class TestAnalyticsModuleWithEmbeddedDB extends TestAnalyticsModule {
+
+ public TestAnalyticsModuleWithEmbeddedDB(final ConfigSource configSource) {
+ super(configSource);
+ }
+
+ @Override
+ public void configure() {
+ super.configure();
+
+ install(new GuicyKillbillTestWithEmbeddedDBModule());
+ install(new NonEntityDaoModule());
+ install(new BusModule(configSource));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockBusinessSubscriptionTransitionSqlDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockBusinessSubscriptionTransitionSqlDao.java
new file mode 100644
index 0000000..f9ee7bc
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockBusinessSubscriptionTransitionSqlDao.java
@@ -0,0 +1,127 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionIsolationLevel;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.testng.Assert;
+
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionBinder;
+import com.ning.billing.osgi.bundles.analytics.dao.BusinessSubscriptionTransitionSqlDao;
+import com.ning.billing.osgi.bundles.analytics.dao.TimeSeriesTuple;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+
+import com.google.common.collect.ImmutableList;
+
+public class MockBusinessSubscriptionTransitionSqlDao implements BusinessSubscriptionTransitionSqlDao {
+
+ private final Map<String, List<BusinessSubscriptionTransitionModelDao>> content = new HashMap<String, List<BusinessSubscriptionTransitionModelDao>>();
+ private final Map<String, String> keyForBundleId = new HashMap<String, String>();
+
+ @Override
+ public List<TimeSeriesTuple> getSubscriptionsCreatedOverTime(@Bind("product_type") final String productType,
+ @Bind("slug") final String slug,
+ @InternalTenantContextBinder final InternalTenantContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<BusinessSubscriptionTransitionModelDao> getTransitionsByKey(@Bind("event_key") final String key,
+ @InternalTenantContextBinder final InternalTenantContext context) {
+ return content.get(key);
+ }
+
+ @Override
+ public List<BusinessSubscriptionTransitionModelDao> getTransitionForSubscription(@Bind("subscription_id") final String subscriptionId,
+ @InternalTenantContextBinder final InternalTenantContext context) {
+ return ImmutableList.<BusinessSubscriptionTransitionModelDao>of();
+ }
+
+ @Override
+ public List<BusinessSubscriptionTransitionModelDao> getTransitionsForAccount(@Bind("account_id") final String accountId, @InternalTenantContextBinder final InternalTenantContext context) {
+ return ImmutableList.<BusinessSubscriptionTransitionModelDao>of();
+ }
+
+ @Override
+ public int createTransition(@BusinessSubscriptionTransitionBinder final BusinessSubscriptionTransitionModelDao transition,
+ @InternalTenantContextBinder final InternalCallContext context) {
+ if (content.get(transition.getExternalKey()) == null) {
+ content.put(transition.getExternalKey(), new ArrayList<BusinessSubscriptionTransitionModelDao>());
+ }
+ content.get(transition.getExternalKey()).add(transition);
+ keyForBundleId.put(transition.getBundleId().toString(), transition.getExternalKey());
+ return 1;
+ }
+
+ @Override
+ public void deleteTransitionsForBundle(@Bind("bundle_id") final String bundleId,
+ @InternalTenantContextBinder final InternalCallContext context) {
+ content.put(keyForBundleId.get(bundleId), new ArrayList<BusinessSubscriptionTransitionModelDao>());
+ }
+
+ @Override
+ public void test(@InternalTenantContextBinder final InternalTenantContext context) {
+ }
+
+ @Override
+ public void begin() {
+ }
+
+ @Override
+ public void commit() {
+ }
+
+ @Override
+ public void rollback() {
+ }
+
+ @Override
+ public void checkpoint(final String name) {
+ }
+
+ @Override
+ public void release(final String name) {
+ }
+
+ @Override
+ public void rollback(final String name) {
+ }
+
+ @Override
+ public <ReturnType> ReturnType inTransaction(final Transaction<ReturnType, BusinessSubscriptionTransitionSqlDao> func) {
+ try {
+ return func.inTransaction(this, null);
+ } catch (Exception e) {
+ Assert.fail(e.toString());
+ return null;
+ }
+ }
+
+ @Override
+ public <ReturnType> ReturnType inTransaction(final TransactionIsolationLevel isolation, final Transaction<ReturnType, BusinessSubscriptionTransitionSqlDao> func) {
+ return inTransaction(func);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockDuration.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockDuration.java
new file mode 100644
index 0000000..d98fd8a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockDuration.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+import org.joda.time.DateTime;
+import org.joda.time.Period;
+
+import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.TimeUnit;
+
+public class MockDuration {
+
+ public static Duration UNLIMITED() {
+ return new Duration() {
+ @Override
+ public TimeUnit getUnit() {
+ return TimeUnit.UNLIMITED;
+ }
+
+ @Override
+ public int getNumber() {
+ return 1;
+ }
+
+ @Override
+ public DateTime addToDateTime(final DateTime dateTime) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Period toJodaPeriod() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockPhase.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockPhase.java
new file mode 100644
index 0000000..cfd5d45
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockPhase.java
@@ -0,0 +1,124 @@
+/*
+ * 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;
+
+import java.math.BigDecimal;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.InternationalPrice;
+import com.ning.billing.catalog.api.Limit;
+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.Price;
+
+public class MockPhase implements PlanPhase {
+
+ private final PhaseType cohort;
+ private final Plan plan;
+ private final Duration duration;
+ private final double price;
+
+ public MockPhase(final PhaseType cohort, final Plan plan, final Duration duration, final double price) {
+ this.cohort = cohort;
+ this.plan = plan;
+ this.duration = duration;
+ this.price = price;
+ }
+
+ @Override
+ public InternationalPrice getRecurringPrice() {
+ return new InternationalPrice() {
+ @Override
+ public Price[] getPrices() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public BigDecimal getPrice(final Currency currency) {
+ return BigDecimal.valueOf(price);
+ }
+
+ @Override
+ public boolean isZero() {
+ return price == 0.0;
+ }
+
+ };
+ }
+
+ @Override
+ public InternationalPrice getFixedPrice() {
+ return new InternationalPrice() {
+ @Override
+ public Price[] getPrices() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public BigDecimal getPrice(final Currency currency) {
+ return BigDecimal.valueOf(price);
+ }
+
+ @Override
+ public boolean isZero() {
+ return price == 0.0;
+ }
+ };
+ }
+
+ @Override
+ public BillingPeriod getBillingPeriod() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ if (plan == null) {
+ return null;
+ } else {
+ return plan.getName() + "-" + cohort;
+ }
+ }
+
+ @Override
+ public Plan getPlan() {
+ return plan;
+ }
+
+ @Override
+ public Duration getDuration() {
+ return duration;
+ }
+
+ @Override
+ public PhaseType getPhaseType() {
+ return cohort;
+ }
+
+ @Override
+ public Limit[] getLimits() {
+ return new Limit[0];
+ }
+
+ @Override
+ public boolean compliesWithLimits(String unit, double value) {
+ return false;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockProduct.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockProduct.java
new file mode 100644
index 0000000..7999311
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/MockProduct.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+import com.ning.billing.catalog.api.Limit;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class MockProduct implements Product {
+
+ private final String name;
+ private final String type;
+ private final ProductCategory category;
+
+ public MockProduct(final String name, final String type, final ProductCategory category) {
+ this.name = name;
+ this.type = type;
+ this.category = category;
+ }
+
+ @Override
+ public String getCatalogName() {
+ return type;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ProductCategory getCategory() {
+ return category;
+ }
+
+ @Override
+ public Product[] getAvailable() {
+ return null;
+ }
+
+ @Override
+ public Product[] getIncluded() {
+ return null;
+ }
+
+ @Override
+ public boolean isRetired() {
+ return false;
+ }
+
+ @Override
+ public Limit[] getLimits() {
+ return new Limit[0];
+ }
+
+ @Override
+ public boolean compliesWithLimits(String unit, double value) {
+ return false;
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccount.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccount.java
new file mode 100644
index 0000000..1e99805
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccount.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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessAccount extends AnalyticsTestSuiteNoDB {
+
+ private BusinessAccountModelDao account;
+
+ @BeforeMethod(groups = "fast")
+ public void beforeMethod() throws Exception {
+ super.beforeMethod();
+ account = new BusinessAccountModelDao(UUID.randomUUID(), "pierre", UUID.randomUUID().toString(), BigDecimal.ONE, clock.getUTCToday(),
+ BigDecimal.TEN, "ERROR_NOT_ENOUGH_FUNDS", "CreditCard", "Visa", "", UUID.randomUUID().toString(),
+ clock.getUTCNow(), clock.getUTCNow());
+ }
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ Assert.assertSame(account, account);
+ Assert.assertEquals(account, account);
+ Assert.assertTrue(account.equals(account));
+
+ final BusinessAccountModelDao otherAccount = new BusinessAccountModelDao(UUID.randomUUID(), "pierre cardin", UUID.randomUUID().toString(),
+ BigDecimal.ONE, clock.getUTCToday(),
+ BigDecimal.TEN, "ERROR_NOT_ENOUGH_FUNDS", "CreditCard", "Visa",
+ "", UUID.randomUUID().toString(), clock.getUTCNow(), clock.getUTCNow());
+ Assert.assertFalse(account.equals(otherAccount));
+ }
+
+ @Test(groups = "fast")
+ public void testDefaultBigDecimalValues() throws Exception {
+ final Account account = Mockito.mock(Account.class);
+ final BusinessAccountModelDao bac = new BusinessAccountModelDao(account);
+ Assert.assertEquals(bac.getBalance(), BigDecimal.ZERO);
+ Assert.assertEquals(bac.getTotalInvoiceBalance(), BigDecimal.ZERO);
+
+ bac.setBalance(BigDecimal.ONE);
+ bac.setTotalInvoiceBalance(BigDecimal.TEN);
+ Assert.assertEquals(bac.getBalance(), BigDecimal.ONE);
+ Assert.assertEquals(bac.getTotalInvoiceBalance(), BigDecimal.TEN);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountField.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountField.java
new file mode 100644
index 0000000..5fd381a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountField.java
@@ -0,0 +1,52 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessAccountField extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final UUID accountId = UUID.randomUUID();
+ final String accountKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString();
+ final String value = UUID.randomUUID().toString();
+ final BusinessAccountFieldModelDao accountField = new BusinessAccountFieldModelDao(accountId,
+ accountKey,
+ name,
+ value);
+ Assert.assertSame(accountField, accountField);
+ Assert.assertEquals(accountField, accountField);
+ Assert.assertTrue(accountField.equals(accountField));
+ Assert.assertEquals(accountField.getAccountId(), accountId);
+ Assert.assertEquals(accountField.getAccountKey(), accountKey);
+ Assert.assertEquals(accountField.getName(), name);
+ Assert.assertEquals(accountField.getValue(), value);
+
+ final BusinessAccountFieldModelDao otherAccountField = new BusinessAccountFieldModelDao(UUID.randomUUID(),
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString());
+ Assert.assertFalse(accountField.equals(otherAccountField));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountTag.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountTag.java
new file mode 100644
index 0000000..2691132
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessAccountTag.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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessAccountTag extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final UUID accountId = UUID.randomUUID();
+ final String accountKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString();
+ final BusinessAccountTagModelDao accountTag = new BusinessAccountTagModelDao(accountId, accountKey, name);
+ Assert.assertSame(accountTag, accountTag);
+ Assert.assertEquals(accountTag, accountTag);
+ Assert.assertTrue(accountTag.equals(accountTag));
+ Assert.assertEquals(accountTag.getAccountId(), accountId);
+ Assert.assertEquals(accountTag.getAccountKey(), accountKey);
+ Assert.assertEquals(accountTag.getName(), name);
+
+ final BusinessAccountTagModelDao otherAccountTag = new BusinessAccountTagModelDao(UUID.randomUUID(), UUID.randomUUID().toString(), UUID.randomUUID().toString());
+ Assert.assertFalse(accountTag.equals(otherAccountTag));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoice.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoice.java
new file mode 100644
index 0000000..c2cb8c7
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoice.java
@@ -0,0 +1,70 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoice extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final UUID accountId = UUID.randomUUID();
+ final String accountKey = UUID.randomUUID().toString();
+ final BigDecimal amountCharged = BigDecimal.ZERO;
+ final BigDecimal amountCredited = BigDecimal.ONE;
+ final BigDecimal amountPaid = BigDecimal.TEN;
+ final BigDecimal balance = BigDecimal.valueOf(123L);
+ final DateTime createdDate = clock.getUTCNow();
+ final Currency currency = Currency.MXN;
+ final LocalDate invoiceDate = clock.getUTCToday();
+ final UUID invoiceId = UUID.randomUUID();
+ final Integer invoiceNumber = 15;
+ final LocalDate targetDate = clock.getUTCToday();
+ final DateTime updatedDate = clock.getUTCNow();
+ final BusinessInvoiceModelDao invoice = new BusinessInvoiceModelDao(accountId, accountKey, amountCharged, amountCredited, amountPaid, balance,
+ createdDate, currency, invoiceDate, invoiceId, invoiceNumber, targetDate, updatedDate);
+ Assert.assertSame(invoice, invoice);
+ Assert.assertEquals(invoice, invoice);
+ Assert.assertTrue(invoice.equals(invoice));
+ Assert.assertEquals(invoice.getAccountId(), accountId);
+ Assert.assertEquals(invoice.getAccountKey(), accountKey);
+ Assert.assertEquals(invoice.getAmountCharged(), amountCharged);
+ Assert.assertEquals(invoice.getAmountCredited(), amountCredited);
+ Assert.assertEquals(invoice.getAmountPaid(), amountPaid);
+ Assert.assertEquals(invoice.getBalance(), balance);
+ Assert.assertEquals(invoice.getCreatedDate(), createdDate);
+ Assert.assertEquals(invoice.getCurrency(), currency);
+ Assert.assertEquals(invoice.getInvoiceDate(), invoiceDate);
+ Assert.assertEquals(invoice.getInvoiceId(), invoiceId);
+ Assert.assertEquals(invoice.getInvoiceNumber(), invoiceNumber);
+ Assert.assertEquals(invoice.getTargetDate(), targetDate);
+ Assert.assertEquals(invoice.getUpdatedDate(), updatedDate);
+
+ final BusinessInvoiceModelDao otherInvoice = new BusinessInvoiceModelDao(null, null, null, null, null, null, createdDate, null,
+ null, invoiceId, 0, null, null);
+ Assert.assertFalse(invoice.equals(otherInvoice));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceField.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceField.java
new file mode 100644
index 0000000..6287f82
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceField.java
@@ -0,0 +1,48 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoiceField extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final UUID invoiceId = UUID.randomUUID();
+ final String name = UUID.randomUUID().toString();
+ final String value = UUID.randomUUID().toString();
+ final BusinessInvoiceFieldModelDao invoiceField = new BusinessInvoiceFieldModelDao(invoiceId,
+ name,
+ value);
+ Assert.assertSame(invoiceField, invoiceField);
+ Assert.assertEquals(invoiceField, invoiceField);
+ Assert.assertTrue(invoiceField.equals(invoiceField));
+ Assert.assertEquals(invoiceField.getInvoiceId(), invoiceId);
+ Assert.assertEquals(invoiceField.getName(), name);
+ Assert.assertEquals(invoiceField.getValue(), value);
+
+ final BusinessInvoiceFieldModelDao otherInvoiceField = new BusinessInvoiceFieldModelDao(UUID.randomUUID(),
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString());
+ Assert.assertFalse(invoiceField.equals(otherInvoiceField));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceItem.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceItem.java
new file mode 100644
index 0000000..5c7663e
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceItem.java
@@ -0,0 +1,80 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoiceItem extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final BigDecimal amount = BigDecimal.TEN;
+ final String billingPeriod = UUID.randomUUID().toString();
+ final DateTime createdDate = clock.getUTCNow();
+ final Currency currency = Currency.AUD;
+ final LocalDate endDate = clock.getUTCToday();
+ final String externalKey = UUID.randomUUID().toString();
+ final UUID invoiceId = UUID.randomUUID();
+ final UUID itemId = UUID.randomUUID();
+ final UUID linkedItemId = UUID.randomUUID();
+ final String itemType = UUID.randomUUID().toString();
+ final String phase = UUID.randomUUID().toString();
+ final String productCategory = UUID.randomUUID().toString();
+ final String productName = UUID.randomUUID().toString();
+ final String productType = UUID.randomUUID().toString();
+ final String slug = UUID.randomUUID().toString();
+ final LocalDate startDate = clock.getUTCToday();
+ final DateTime updatedDate = clock.getUTCNow();
+ final BusinessInvoiceItemModelDao invoiceItem = new BusinessInvoiceItemModelDao(amount, billingPeriod, createdDate, currency,
+ endDate, externalKey, invoiceId, itemId, linkedItemId,
+ itemType, phase, productCategory, productName, productType,
+ slug, startDate, updatedDate);
+ Assert.assertSame(invoiceItem, invoiceItem);
+ Assert.assertEquals(invoiceItem, invoiceItem);
+ Assert.assertTrue(invoiceItem.equals(invoiceItem));
+ Assert.assertEquals(invoiceItem.getAmount(), amount);
+ Assert.assertEquals(invoiceItem.getBillingPeriod(), billingPeriod);
+ Assert.assertEquals(invoiceItem.getCreatedDate(), createdDate);
+ Assert.assertEquals(invoiceItem.getCurrency(), currency);
+ Assert.assertEquals(invoiceItem.getEndDate(), endDate);
+ Assert.assertEquals(invoiceItem.getExternalKey(), externalKey);
+ Assert.assertEquals(invoiceItem.getInvoiceId(), invoiceId);
+ Assert.assertEquals(invoiceItem.getItemId(), itemId);
+ Assert.assertEquals(invoiceItem.getItemType(), itemType);
+ Assert.assertEquals(invoiceItem.getLinkedItemId(), linkedItemId);
+ Assert.assertEquals(invoiceItem.getPhase(), phase);
+ Assert.assertEquals(invoiceItem.getProductCategory(), productCategory);
+ Assert.assertEquals(invoiceItem.getProductName(), productName);
+ Assert.assertEquals(invoiceItem.getProductType(), productType);
+ Assert.assertEquals(invoiceItem.getSlug(), slug);
+ Assert.assertEquals(invoiceItem.getStartDate(), startDate);
+ Assert.assertEquals(invoiceItem.getUpdatedDate(), updatedDate);
+
+ final BusinessInvoiceItemModelDao otherInvoiceItem = new BusinessInvoiceItemModelDao(null, null, createdDate, null, null, null, null, itemId,
+ linkedItemId, null, null, null, null, null, null, null, null);
+ Assert.assertFalse(invoiceItem.equals(otherInvoiceItem));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePayment.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePayment.java
new file mode 100644
index 0000000..b609d54
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePayment.java
@@ -0,0 +1,86 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+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.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoicePayment extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final BigDecimal amount = BigDecimal.ONE;
+ final String cardCountry = UUID.randomUUID().toString();
+ final String cardType = UUID.randomUUID().toString();
+ final DateTime createdDate = new DateTime(DateTimeZone.UTC);
+ final Currency currency = Currency.BRL;
+ final DateTime effectiveDate = new DateTime(DateTimeZone.UTC);
+ final UUID invoiceId = UUID.randomUUID();
+ final String paymentError = UUID.randomUUID().toString();
+ final UUID paymentId = UUID.randomUUID();
+ final String paymentMethod = UUID.randomUUID().toString();
+ final String paymentType = UUID.randomUUID().toString();
+ final String pluginName = UUID.randomUUID().toString();
+ final String processingStatus = UUID.randomUUID().toString();
+ final BigDecimal requestedAmount = BigDecimal.ZERO;
+ final DateTime updatedDate = new DateTime(DateTimeZone.UTC);
+ final String invoicePaymentType = UUID.randomUUID().toString();
+ final UUID linkedInvoicePaymentId = UUID.randomUUID();
+ final BusinessInvoicePaymentModelDao invoicePayment = new BusinessInvoicePaymentModelDao(accountKey, amount,
+ cardCountry, cardType, createdDate,
+ currency, effectiveDate, invoiceId,
+ paymentError, paymentId, paymentMethod,
+ paymentType, pluginName, processingStatus,
+ requestedAmount, updatedDate, invoicePaymentType,
+ linkedInvoicePaymentId);
+ Assert.assertSame(invoicePayment, invoicePayment);
+ Assert.assertEquals(invoicePayment, invoicePayment);
+ Assert.assertTrue(invoicePayment.equals(invoicePayment));
+ Assert.assertEquals(invoicePayment.getAccountKey(), accountKey);
+ Assert.assertEquals(invoicePayment.getAmount(), amount);
+ Assert.assertEquals(invoicePayment.getCardCountry(), cardCountry);
+ Assert.assertEquals(invoicePayment.getCardType(), cardType);
+ Assert.assertEquals(invoicePayment.getCreatedDate(), createdDate);
+ Assert.assertEquals(invoicePayment.getCurrency(), currency);
+ Assert.assertEquals(invoicePayment.getEffectiveDate(), effectiveDate);
+ Assert.assertEquals(invoicePayment.getInvoiceId(), invoiceId);
+ Assert.assertEquals(invoicePayment.getPaymentError(), paymentError);
+ Assert.assertEquals(invoicePayment.getPaymentId(), paymentId);
+ Assert.assertEquals(invoicePayment.getPaymentMethod(), paymentMethod);
+ Assert.assertEquals(invoicePayment.getPaymentType(), paymentType);
+ Assert.assertEquals(invoicePayment.getPluginName(), pluginName);
+ Assert.assertEquals(invoicePayment.getProcessingStatus(), processingStatus);
+ Assert.assertEquals(invoicePayment.getRequestedAmount(), requestedAmount);
+ Assert.assertEquals(invoicePayment.getUpdatedDate(), updatedDate);
+ Assert.assertEquals(invoicePayment.getInvoicePaymentType(), invoicePaymentType);
+ Assert.assertEquals(invoicePayment.getLinkedInvoicePaymentId(), linkedInvoicePaymentId);
+
+ final BusinessInvoicePaymentModelDao otherInvoicePayment = new BusinessInvoicePaymentModelDao(null, null, null, null, createdDate,
+ null, null, null, null, paymentId, null,
+ null, null, null, null, null, null, null);
+ Assert.assertFalse(invoicePayment.equals(otherInvoicePayment));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentField.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentField.java
new file mode 100644
index 0000000..5db7895
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentField.java
@@ -0,0 +1,48 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoicePaymentField extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final UUID paymentId = UUID.randomUUID();
+ final String name = UUID.randomUUID().toString();
+ final String value = UUID.randomUUID().toString();
+ final BusinessInvoicePaymentFieldModelDao invoiceField = new BusinessInvoicePaymentFieldModelDao(paymentId,
+ name,
+ value);
+ Assert.assertSame(invoiceField, invoiceField);
+ Assert.assertEquals(invoiceField, invoiceField);
+ Assert.assertTrue(invoiceField.equals(invoiceField));
+ Assert.assertEquals(invoiceField.getPaymentId(), paymentId);
+ Assert.assertEquals(invoiceField.getName(), name);
+ Assert.assertEquals(invoiceField.getValue(), value);
+
+ final BusinessInvoicePaymentFieldModelDao otherInvoicePaymentField = new BusinessInvoicePaymentFieldModelDao(UUID.randomUUID(),
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString());
+ Assert.assertFalse(invoiceField.equals(otherInvoicePaymentField));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentTag.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentTag.java
new file mode 100644
index 0000000..9336ffe
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoicePaymentTag.java
@@ -0,0 +1,43 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoicePaymentTag extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final UUID paymentId = UUID.randomUUID();
+ final String name = UUID.randomUUID().toString();
+ final BusinessInvoicePaymentTagModelDao invoicePaymentTag = new BusinessInvoicePaymentTagModelDao(paymentId, name);
+ Assert.assertSame(invoicePaymentTag, invoicePaymentTag);
+ Assert.assertEquals(invoicePaymentTag, invoicePaymentTag);
+ Assert.assertTrue(invoicePaymentTag.equals(invoicePaymentTag));
+ Assert.assertEquals(invoicePaymentTag.getPaymentId(), paymentId);
+ Assert.assertEquals(invoicePaymentTag.getName(), name);
+
+ final BusinessInvoicePaymentTagModelDao otherInvoicePaymentTag = new BusinessInvoicePaymentTagModelDao(UUID.randomUUID(),
+ UUID.randomUUID().toString());
+ Assert.assertFalse(invoicePaymentTag.equals(otherInvoicePaymentTag));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceTag.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceTag.java
new file mode 100644
index 0000000..91fc4d3
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessInvoiceTag.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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessInvoiceTag extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final UUID invoiceId = UUID.randomUUID();
+ final String name = UUID.randomUUID().toString();
+ final BusinessInvoiceTagModelDao invoiceTag = new BusinessInvoiceTagModelDao(invoiceId, name);
+ Assert.assertSame(invoiceTag, invoiceTag);
+ Assert.assertEquals(invoiceTag, invoiceTag);
+ Assert.assertTrue(invoiceTag.equals(invoiceTag));
+ Assert.assertEquals(invoiceTag.getInvoiceId(), invoiceId);
+ Assert.assertEquals(invoiceTag.getName(), name);
+
+ final BusinessInvoiceTagModelDao otherInvoiceTag = new BusinessInvoiceTagModelDao(UUID.randomUUID(), UUID.randomUUID().toString());
+ Assert.assertFalse(invoiceTag.equals(otherInvoiceTag));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessOverdueStatus.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessOverdueStatus.java
new file mode 100644
index 0000000..c813681
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessOverdueStatus.java
@@ -0,0 +1,57 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+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 TestBusinessOverdueStatus extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId = UUID.randomUUID();
+ final DateTime endDate = new DateTime(DateTimeZone.UTC);
+ final String externalKey = UUID.randomUUID().toString();
+ final DateTime startDate = new DateTime(DateTimeZone.UTC);
+ final String status = UUID.randomUUID().toString();
+ final BusinessOverdueStatusModelDao overdueStatus = new BusinessOverdueStatusModelDao(accountKey, bundleId, endDate, externalKey, startDate, status);
+ Assert.assertSame(overdueStatus, overdueStatus);
+ Assert.assertEquals(overdueStatus, overdueStatus);
+ Assert.assertTrue(overdueStatus.equals(overdueStatus));
+ Assert.assertEquals(overdueStatus.getAccountKey(), accountKey);
+ Assert.assertEquals(overdueStatus.getBundleId(), bundleId);
+ Assert.assertEquals(overdueStatus.getEndDate(), endDate);
+ Assert.assertEquals(overdueStatus.getExternalKey(), externalKey);
+ Assert.assertEquals(overdueStatus.getStartDate(), startDate);
+ Assert.assertEquals(overdueStatus.getStatus(), status);
+
+ final BusinessOverdueStatusModelDao otherOverdueStatus = new BusinessOverdueStatusModelDao(UUID.randomUUID().toString(),
+ UUID.randomUUID(),
+ new DateTime(DateTimeZone.UTC),
+ UUID.randomUUID().toString(),
+ new DateTime(DateTimeZone.UTC),
+ UUID.randomUUID().toString());
+ Assert.assertFalse(overdueStatus.equals(otherOverdueStatus));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscription.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscription.java
new file mode 100644
index 0000000..869b3d4
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscription.java
@@ -0,0 +1,172 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+
+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.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.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 static com.ning.billing.catalog.api.Currency.USD;
+
+public class TestBusinessSubscription extends AnalyticsTestSuiteNoDB {
+
+ final Object[][] catalogMapping = {
+ {BillingPeriod.NO_BILLING_PERIOD, 369.9500, 0.0000},
+ {BillingPeriod.NO_BILLING_PERIOD, 429.9500, 0.0000},
+ {BillingPeriod.NO_BILLING_PERIOD, 999.9500, 0.0000},
+ {BillingPeriod.NO_BILLING_PERIOD, 2300.0000, 0.0000},
+ {BillingPeriod.MONTHLY, 2.9500, 2.9500},
+ {BillingPeriod.MONTHLY, 3.9500, 3.9500},
+ {BillingPeriod.MONTHLY, 6.9500, 6.9500},
+ {BillingPeriod.MONTHLY, 7.0000, 7.0000},
+ {BillingPeriod.MONTHLY, 7.9500, 7.9500},
+ {BillingPeriod.MONTHLY, 9.0000, 9.0000},
+ {BillingPeriod.MONTHLY, 9.9500, 9.9500},
+ {BillingPeriod.MONTHLY, 11.9500, 11.9500},
+ {BillingPeriod.MONTHLY, 12.4500, 12.4500},
+ {BillingPeriod.MONTHLY, 12.9500, 12.9500},
+ {BillingPeriod.MONTHLY, 14.9500, 14.9500},
+ {BillingPeriod.MONTHLY, 15.0000, 15.0000},
+ {BillingPeriod.MONTHLY, 16.9500, 16.9500},
+ {BillingPeriod.MONTHLY, 19.0000, 19.0000},
+ {BillingPeriod.MONTHLY, 19.9500, 19.9500},
+ {BillingPeriod.MONTHLY, 24.9500, 24.9500},
+ {BillingPeriod.MONTHLY, 29.0000, 29.0000},
+ {BillingPeriod.MONTHLY, 29.9500, 29.9500},
+ {BillingPeriod.MONTHLY, 31.0000, 31.0000},
+ {BillingPeriod.MONTHLY, 34.9500, 34.9500},
+ {BillingPeriod.MONTHLY, 39.0000, 39.0000},
+ {BillingPeriod.MONTHLY, 39.9500, 39.9500},
+ {BillingPeriod.MONTHLY, 49.0000, 49.0000},
+ {BillingPeriod.MONTHLY, 49.9500, 49.9500},
+ {BillingPeriod.MONTHLY, 59.9500, 59.9500},
+ {BillingPeriod.MONTHLY, 79.0000, 79.0000},
+ {BillingPeriod.MONTHLY, 99.0000, 99.0000},
+ {BillingPeriod.MONTHLY, 139.0000, 139.0000},
+ {BillingPeriod.MONTHLY, 209.0000, 209.0000},
+ {BillingPeriod.MONTHLY, 229.0000, 229.0000},
+ {BillingPeriod.MONTHLY, 274.5000, 274.5000},
+ {BillingPeriod.MONTHLY, 549.0000, 549.0000},
+ {BillingPeriod.ANNUAL, 18.2900, 1.5242},
+ {BillingPeriod.ANNUAL, 19.9500, 1.6625},
+ {BillingPeriod.ANNUAL, 29.9500, 2.4958},
+ {BillingPeriod.ANNUAL, 49.0000, 4.0833},
+ {BillingPeriod.ANNUAL, 59.0000, 4.9167},
+ {BillingPeriod.ANNUAL, 149.9500, 12.4958},
+ {BillingPeriod.ANNUAL, 159.9500, 13.3292},
+ {BillingPeriod.ANNUAL, 169.9500, 14.1625},
+ {BillingPeriod.ANNUAL, 183.2900, 15.2742},
+ {BillingPeriod.ANNUAL, 199.9500, 16.6625},
+ {BillingPeriod.ANNUAL, 219.9500, 18.3292},
+ {BillingPeriod.ANNUAL, 239.9000, 19.9917},
+ {BillingPeriod.ANNUAL, 249.9500, 20.8292},
+ {BillingPeriod.ANNUAL, 319.0000, 26.5833},
+ {BillingPeriod.ANNUAL, 349.9500, 29.1625},
+ {BillingPeriod.ANNUAL, 399.0000, 33.2500},
+ {BillingPeriod.ANNUAL, 399.9500, 33.3292},
+ {BillingPeriod.ANNUAL, 458.2900, 38.1908},
+ {BillingPeriod.ANNUAL, 499.9500, 41.6625},
+ {BillingPeriod.ANNUAL, 549.9500, 45.8292},
+ {BillingPeriod.ANNUAL, 599.9000, 49.9917},
+ {BillingPeriod.ANNUAL, 599.9500, 49.9958},
+ {BillingPeriod.ANNUAL, 624.9500, 52.0792},
+ {BillingPeriod.ANNUAL, 799.0000, 66.5833},
+ {BillingPeriod.ANNUAL, 999.0000, 83.2500},
+ {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;
+ for (final Object[] object : catalogMapping) {
+ final BillingPeriod billingPeriod = (BillingPeriod) object[0];
+ final double price = (Double) object[1];
+ final double expectedMrr = (Double) object[2];
+
+ final BigDecimal computedMrr = BusinessSubscription.getMrrFromBillingPeriod(billingPeriod, BigDecimal.valueOf(price));
+ Assert.assertEquals(computedMrr.doubleValue(), expectedMrr, "Invalid mrr for product #" + i);
+ i++;
+ }
+ }
+
+ @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());
+ }
+
+ @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)));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionEvent.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionEvent.java
new file mode 100644
index 0000000..1dbf626
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionEvent.java
@@ -0,0 +1,124 @@
+/*
+ * 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.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;
+
+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;
+
+ event = BusinessSubscriptionEvent.valueOf("ADD_ADD_ON");
+ Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.ADD);
+ Assert.assertEquals(event.getCategory(), ProductCategory.ADD_ON);
+
+ event = BusinessSubscriptionEvent.valueOf("CANCEL_BASE");
+ Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.CANCEL);
+ Assert.assertEquals(event.getCategory(), ProductCategory.BASE);
+
+ event = BusinessSubscriptionEvent.valueOf("SYSTEM_CANCEL_ADD_ON");
+ Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.SYSTEM_CANCEL);
+ Assert.assertEquals(event.getCategory(), ProductCategory.ADD_ON);
+ }
+
+ @Test(groups = "fast")
+ public void testFromSubscription() throws Exception {
+ BusinessSubscriptionEvent event;
+
+ final DateTime now = new DateTime();
+
+ event = BusinessSubscriptionEvent.subscriptionCreated(subscription.getCurrentPlan().getName(), catalog, now, now);
+ Assert.assertEquals(event.getEventType(), BusinessSubscriptionEvent.EventType.ADD);
+ Assert.assertEquals(event.getCategory(), product.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/model/TestBusinessSubscriptionTransition.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransition.java
new file mode 100644
index 0000000..9bc0d4a
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransition.java
@@ -0,0 +1,161 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+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 static com.ning.billing.catalog.api.Currency.USD;
+
+public class TestBusinessSubscriptionTransition extends AnalyticsTestSuiteNoDB {
+
+ private BusinessSubscription prevSubscription;
+ private BusinessSubscription nextSubscription;
+ private BusinessSubscriptionEvent event;
+ private DateTime requestedTimestamp;
+ private Long totalOrdering;
+ private UUID bundleId;
+ private String externalKey;
+ private UUID accountId;
+ private String accountKey;
+ private UUID subscriptionId;
+ private BusinessSubscriptionTransitionModelDao transition;
+
+ private final Catalog catalog = Mockito.mock(Catalog.class);
+
+ @Override
+ @BeforeMethod(groups = "fast")
+ public void beforeMethod() throws Exception {
+ super.beforeMethod();
+ final Product product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
+ final Plan plan = new MockPlan("platinum-monthly", product);
+ final PlanPhase phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
+ final Subscription prevISubscription = new MockSubscription(Subscription.SubscriptionState.ACTIVE, plan, phase);
+ final Subscription nextISubscription = new MockSubscription(Subscription.SubscriptionState.CANCELLED, plan, phase);
+
+ Mockito.when(catalog.findPlan(Mockito.anyString(), 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);
+
+ final DateTime now = new DateTime();
+
+ prevSubscription = new BusinessSubscription(prevISubscription, USD, catalog);
+ nextSubscription = new BusinessSubscription(nextISubscription, USD, catalog);
+ event = BusinessSubscriptionEvent.subscriptionCancelled(prevISubscription.getCurrentPlan().getName(), catalog, now, now);
+ requestedTimestamp = new DateTime(DateTimeZone.UTC);
+ totalOrdering = 12L;
+ bundleId = UUID.randomUUID();
+ externalKey = "1234";
+ accountId = UUID.randomUUID();
+ accountKey = "pierre-1234";
+ subscriptionId = UUID.randomUUID();
+ transition = new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, requestedTimestamp, event, prevSubscription, nextSubscription);
+ }
+
+ @Test(groups = "fast")
+ public void testConstructor() throws Exception {
+ Assert.assertEquals(transition.getEvent(), event);
+ Assert.assertEquals(transition.getPreviousSubscription(), prevSubscription);
+ Assert.assertEquals(transition.getNextSubscription(), nextSubscription);
+ Assert.assertEquals(transition.getRequestedTimestamp(), requestedTimestamp);
+ }
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ Assert.assertSame(transition, transition);
+ Assert.assertEquals(transition, transition);
+ Assert.assertTrue(transition.equals(transition));
+
+ BusinessSubscriptionTransitionModelDao otherTransition;
+
+ otherTransition = new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, new DateTime(), event, prevSubscription, nextSubscription);
+ Assert.assertTrue(!transition.equals(otherTransition));
+
+ otherTransition = new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, "12345", accountId, accountKey,
+ subscriptionId, requestedTimestamp, event, prevSubscription, nextSubscription);
+ Assert.assertTrue(!transition.equals(otherTransition));
+
+ otherTransition = new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, requestedTimestamp, event, prevSubscription, prevSubscription);
+ Assert.assertTrue(!transition.equals(otherTransition));
+
+ otherTransition = new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, requestedTimestamp, event, nextSubscription, nextSubscription);
+ Assert.assertTrue(!transition.equals(otherTransition));
+
+ otherTransition = new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, requestedTimestamp, event, nextSubscription, prevSubscription);
+ Assert.assertTrue(!transition.equals(otherTransition));
+ }
+
+ @Test(groups = "fast")
+ public void testRejectInvalidTransitions() throws Exception {
+ try {
+ new BusinessSubscriptionTransitionModelDao(null, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, requestedTimestamp, event, prevSubscription, nextSubscription);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ try {
+ new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, null, accountId, accountKey,
+ subscriptionId, requestedTimestamp, event, prevSubscription, nextSubscription);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ try {
+ new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, null, event, prevSubscription, nextSubscription);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ try {
+ new BusinessSubscriptionTransitionModelDao(totalOrdering, bundleId, externalKey, accountId, accountKey,
+ subscriptionId, requestedTimestamp, null, prevSubscription, nextSubscription);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionField.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionField.java
new file mode 100644
index 0000000..b016bbf
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionField.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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessSubscriptionTransitionField extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId = UUID.randomUUID();
+ final String externalKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString();
+ final String value = UUID.randomUUID().toString();
+ final BusinessSubscriptionTransitionFieldModelDao subscriptionTransitionField = new BusinessSubscriptionTransitionFieldModelDao(accountKey,
+ bundleId,
+ externalKey,
+ name,
+ value);
+ Assert.assertSame(subscriptionTransitionField, subscriptionTransitionField);
+ Assert.assertEquals(subscriptionTransitionField, subscriptionTransitionField);
+ Assert.assertTrue(subscriptionTransitionField.equals(subscriptionTransitionField));
+ Assert.assertEquals(subscriptionTransitionField.getAccountKey(), accountKey);
+ Assert.assertEquals(subscriptionTransitionField.getBundleId(), bundleId);
+ Assert.assertEquals(subscriptionTransitionField.getExternalKey(), externalKey);
+ Assert.assertEquals(subscriptionTransitionField.getName(), name);
+ Assert.assertEquals(subscriptionTransitionField.getValue(), value);
+
+ final BusinessSubscriptionTransitionFieldModelDao otherSubscriptionField = new BusinessSubscriptionTransitionFieldModelDao(UUID.randomUUID().toString(),
+ UUID.randomUUID(),
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString());
+ Assert.assertFalse(subscriptionTransitionField.equals(otherSubscriptionField));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionTag.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionTag.java
new file mode 100644
index 0000000..5b7bb79
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/model/TestBusinessSubscriptionTransitionTag.java
@@ -0,0 +1,52 @@
+/*
+ * 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.model;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestBusinessSubscriptionTransitionTag extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final String accountKey = UUID.randomUUID().toString();
+ final UUID bundleId = UUID.randomUUID();
+ final String externalKey = UUID.randomUUID().toString();
+ final String name = UUID.randomUUID().toString();
+ final BusinessSubscriptionTransitionTagModelDao subscriptionTransitionTag = new BusinessSubscriptionTransitionTagModelDao(accountKey,
+ bundleId,
+ externalKey,
+ name);
+ Assert.assertSame(subscriptionTransitionTag, subscriptionTransitionTag);
+ Assert.assertEquals(subscriptionTransitionTag, subscriptionTransitionTag);
+ Assert.assertTrue(subscriptionTransitionTag.equals(subscriptionTransitionTag));
+ Assert.assertEquals(subscriptionTransitionTag.getAccountKey(), accountKey);
+ Assert.assertEquals(subscriptionTransitionTag.getBundleId(), bundleId);
+ Assert.assertEquals(subscriptionTransitionTag.getExternalKey(), externalKey);
+ Assert.assertEquals(subscriptionTransitionTag.getName(), name);
+
+ final BusinessSubscriptionTransitionTagModelDao otherTransitionTag = new BusinessSubscriptionTransitionTagModelDao(UUID.randomUUID().toString(),
+ UUID.randomUUID(),
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString());
+ Assert.assertFalse(subscriptionTransitionTag.equals(otherTransitionTag));
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessInvoiceRecorder.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessInvoiceRecorder.java
new file mode 100644
index 0000000..37c7ebd
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessInvoiceRecorder.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.LocalDate;
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessInvoiceItemModelDao;
+
+public class TestBusinessInvoiceRecorder extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testShouldBeAbleToHandleNullFieldsInInvoiceItem() throws Exception {
+ final InvoiceItem invoiceItem = Mockito.mock(InvoiceItem.class);
+ Mockito.when(invoiceItem.getAmount()).thenReturn(BigDecimal.TEN);
+ Mockito.when(invoiceItem.getCurrency()).thenReturn(Currency.AUD);
+ Mockito.when(invoiceItem.getEndDate()).thenReturn(new LocalDate(1200, 1, 12));
+ final UUID invoiceId = UUID.randomUUID();
+ Mockito.when(invoiceItem.getInvoiceId()).thenReturn(invoiceId);
+ final UUID id = UUID.randomUUID();
+ Mockito.when(invoiceItem.getId()).thenReturn(id);
+ Mockito.when(invoiceItem.getStartDate()).thenReturn(new LocalDate(1985, 9, 10));
+ Mockito.when(invoiceItem.getInvoiceItemType()).thenReturn(InvoiceItemType.CREDIT_ADJ);
+
+ final BusinessInvoiceItemModelDao bii = invoiceDao.createBusinessInvoiceItem(invoiceItem, internalCallContext);
+ Assert.assertNotNull(bii);
+ Assert.assertEquals(bii.getAmount(), invoiceItem.getAmount());
+ Assert.assertEquals(bii.getCurrency(), invoiceItem.getCurrency());
+ Assert.assertEquals(bii.getEndDate(), invoiceItem.getEndDate());
+ Assert.assertEquals(bii.getInvoiceId(), invoiceItem.getInvoiceId());
+ Assert.assertEquals(bii.getItemId(), invoiceItem.getId());
+ Assert.assertEquals(bii.getStartDate(), invoiceItem.getStartDate());
+ Assert.assertEquals(bii.getItemType(), invoiceItem.getInvoiceItemType().toString());
+ Assert.assertNull(bii.getBillingPeriod());
+ Assert.assertNull(bii.getPhase());
+ Assert.assertNull(bii.getProductCategory());
+ Assert.assertNull(bii.getProductName());
+ Assert.assertNull(bii.getProductType());
+ Assert.assertNull(bii.getSlug());
+ Assert.assertNull(bii.getExternalKey());
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessSubscriptionTransitionRecorder.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessSubscriptionTransitionRecorder.java
new file mode 100644
index 0000000..5330aeb
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessSubscriptionTransitionRecorder.java
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.osgi.bundles.analytics.model.BusinessSubscriptionTransitionModelDao;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.events.EffectiveSubscriptionInternalEvent;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestBusinessSubscriptionTransitionRecorder extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testCreateAddOn() throws Exception {
+ final UUID bundleId = UUID.randomUUID();
+ final UUID externalKey = UUID.randomUUID();
+ final UUID accountId = UUID.randomUUID();
+ final UUID subscriptionId = UUID.randomUUID();
+
+ // Setup the catalog
+ Mockito.when(catalogService.getFullCatalog()).thenReturn(Mockito.mock(Catalog.class));
+
+ // Setup the entitlement API
+ final SubscriptionBundle bundle = Mockito.mock(SubscriptionBundle.class);
+ Mockito.when(bundle.getId()).thenReturn(bundleId);
+ Mockito.when(bundle.getAccountId()).thenReturn(accountId);
+ Mockito.when(bundle.getExternalKey()).thenReturn(externalKey.toString());
+ Mockito.when(entitlementInternalApi.getBundleFromId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(bundle);
+
+ // Setup the account API
+ final Account account = Mockito.mock(Account.class);
+ Mockito.when(account.getExternalKey()).thenReturn(externalKey.toString());
+ Mockito.when(accountInternalApi.getAccountById(Mockito.eq(bundle.getAccountId()), Mockito.<InternalTenantContext>any())).thenReturn(account);
+
+ // Create an new subscription event
+ final EffectiveSubscriptionInternalEvent eventEffective = Mockito.mock(EffectiveSubscriptionInternalEvent.class);
+ Mockito.when(eventEffective.getId()).thenReturn(UUID.randomUUID());
+ Mockito.when(eventEffective.getTransitionType()).thenReturn(SubscriptionTransitionType.CREATE);
+ Mockito.when(eventEffective.getSubscriptionId()).thenReturn(subscriptionId);
+ Mockito.when(eventEffective.getRequestedTransitionTime()).thenReturn(new DateTime(DateTimeZone.UTC));
+ Mockito.when(eventEffective.getNextPlan()).thenReturn(UUID.randomUUID().toString());
+ Mockito.when(eventEffective.getEffectiveTransitionTime()).thenReturn(new DateTime(DateTimeZone.UTC));
+ Mockito.when(eventEffective.getSubscriptionStartDate()).thenReturn(new DateTime(DateTimeZone.UTC));
+
+ final Subscription subscription = Mockito.mock(Subscription.class);
+ Mockito.when(subscription.getId()).thenReturn(subscriptionId);
+ Mockito.when(entitlementInternalApi.getAllTransitions(Mockito.eq(subscription), Mockito.<InternalTenantContext>any())).thenReturn(ImmutableList.<EffectiveSubscriptionInternalEvent>of(eventEffective));
+
+ Mockito.when(entitlementInternalApi.getSubscriptionsForBundle(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(ImmutableList.<Subscription>of(subscription));
+
+ subscriptionTransitionDao.rebuildTransitionsForBundle(bundle.getId(), internalCallContext);
+
+ Assert.assertEquals(subscriptionTransitionSqlDao.getTransitionsByKey(externalKey.toString(), internalCallContext).size(), 1);
+ final BusinessSubscriptionTransitionModelDao transition = subscriptionTransitionSqlDao.getTransitionsByKey(externalKey.toString(), internalCallContext).get(0);
+ Assert.assertEquals(transition.getTotalOrdering(), (long) eventEffective.getTotalOrdering());
+ Assert.assertEquals(transition.getAccountKey(), externalKey.toString());
+ // Make sure all the prev_ columns are null
+ Assert.assertNull(transition.getPreviousSubscription());
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessTagRecorder.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessTagRecorder.java
new file mode 100644
index 0000000..ee0e021
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestBusinessTagRecorder.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import java.util.UUID;
+
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.mock.MockAccountBuilder;
+import com.ning.billing.util.callcontext.InternalCallContext;
+
+public class TestBusinessTagRecorder extends AnalyticsTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testAddAndRemoveTagsForAccount() throws Exception {
+ final String name = UUID.randomUUID().toString().substring(0, 20);
+ final String accountKey = UUID.randomUUID().toString();
+
+ final Account accountData = new MockAccountBuilder(UUID.randomUUID())
+ .externalKey(accountKey)
+ .currency(Currency.MXN)
+ .build();
+ Mockito.when(accountInternalApi.getAccountById(Mockito.eq(accountData.getId()), Mockito.<InternalCallContext>any())).thenReturn(accountData);
+ Mockito.when(accountInternalApi.getAccountByKey(Mockito.eq(accountData.getExternalKey()), Mockito.<InternalCallContext>any())).thenReturn(accountData);
+ final UUID accountId = accountData.getId();
+
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey, internalCallContext).size(), 0);
+ tagDao.tagAdded(ObjectType.ACCOUNT, accountId, name, internalCallContext);
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey, internalCallContext).size(), 1);
+ tagDao.tagRemoved(ObjectType.ACCOUNT, accountId, name, internalCallContext);
+ Assert.assertEquals(accountTagSqlDao.getTagsForAccountByKey(accountKey, internalCallContext).size(), 0);
+ }
+
+ @Test(groups = "slow")
+ public void testAddAndRemoveTagsForBundle() throws Exception {
+ final String name = UUID.randomUUID().toString().substring(0, 20);
+ final String externalKey = UUID.randomUUID().toString();
+
+ final Account accountData = new MockAccountBuilder()
+ .currency(Currency.MXN)
+ .build();
+ Mockito.when(accountInternalApi.getAccountById(Mockito.eq(accountData.getId()), Mockito.<InternalCallContext>any())).thenReturn(accountData);
+ Mockito.when(accountInternalApi.getAccountByKey(Mockito.eq(accountData.getExternalKey()), Mockito.<InternalCallContext>any())).thenReturn(accountData);
+
+ final UUID bundleId = UUID.randomUUID();
+ final SubscriptionBundle bundle = Mockito.mock(SubscriptionBundle.class);
+ Mockito.when(bundle.getId()).thenReturn(bundleId);
+ Mockito.when(bundle.getAccountId()).thenReturn(accountData.getId());
+ Mockito.when(bundle.getExternalKey()).thenReturn(externalKey);
+ Mockito.when(entitlementInternalApi.getBundleFromId(Mockito.eq(bundleId), Mockito.<InternalCallContext>any())).thenReturn(bundle);
+
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext).size(), 0);
+ tagDao.tagAdded(ObjectType.BUNDLE, bundleId, name, internalCallContext);
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext).size(), 1);
+ tagDao.tagRemoved(ObjectType.BUNDLE, bundleId, name, internalCallContext);
+ Assert.assertEquals(subscriptionTransitionTagSqlDao.getTagsForBusinessSubscriptionTransitionByKey(externalKey, internalCallContext).size(), 0);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestPaymentMethodUtils.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestPaymentMethodUtils.java
new file mode 100644
index 0000000..371cbbf
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/TestPaymentMethodUtils.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;
+
+import java.util.UUID;
+
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.payment.api.PaymentMethodPlugin;
+
+public class TestPaymentMethodUtils extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testUnknowns() throws Exception {
+ Assert.assertNull(PaymentMethodUtils.getCardCountry(null));
+ Assert.assertNull(PaymentMethodUtils.getCardType(null));
+ Assert.assertNull(PaymentMethodUtils.getPaymentMethodType(null));
+
+ final PaymentMethodPlugin paymentMethodPlugin = Mockito.mock(PaymentMethodPlugin.class);
+ Assert.assertNull(PaymentMethodUtils.getCardCountry(paymentMethodPlugin));
+ Assert.assertNull(PaymentMethodUtils.getCardType(paymentMethodPlugin));
+ Assert.assertNull(PaymentMethodUtils.getPaymentMethodType(paymentMethodPlugin));
+ }
+
+ @Test(groups = "fast")
+ public void testCardCountry() throws Exception {
+ final String country = UUID.randomUUID().toString();
+ final String cardType = UUID.randomUUID().toString();
+ final String type = UUID.randomUUID().toString();
+
+ final PaymentMethodPlugin paymentMethodPlugin = Mockito.mock(PaymentMethodPlugin.class);
+ Mockito.when(paymentMethodPlugin.getValueString(PaymentMethodUtils.COUNTRY_KEY)).thenReturn(country);
+ Mockito.when(paymentMethodPlugin.getValueString(PaymentMethodUtils.CARD_TYPE_KEY)).thenReturn(cardType);
+ Mockito.when(paymentMethodPlugin.getValueString(PaymentMethodUtils.TYPE_KEY)).thenReturn(type);
+
+ Assert.assertEquals(PaymentMethodUtils.getCardCountry(paymentMethodPlugin), country);
+ Assert.assertEquals(PaymentMethodUtils.getCardType(paymentMethodPlugin), cardType);
+ Assert.assertEquals(PaymentMethodUtils.getPaymentMethodType(paymentMethodPlugin), type);
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/utils/TestRounder.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/utils/TestRounder.java
new file mode 100644
index 0000000..3e3cbec
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/utils/TestRounder.java
@@ -0,0 +1,40 @@
+/*
+ * 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.utils;
+
+import java.math.BigDecimal;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.osgi.bundles.analytics.AnalyticsTestSuiteNoDB;
+
+public class TestRounder extends AnalyticsTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testRound() throws Exception {
+ Assert.assertEquals(Rounder.round(null), 0.0);
+ Assert.assertEquals(Rounder.round(BigDecimal.ZERO), 0.0);
+ Assert.assertEquals(Rounder.round(BigDecimal.ONE), 1.0);
+ Assert.assertEquals(Rounder.round(BigDecimal.TEN), 10.0);
+ Assert.assertEquals(Rounder.round(BigDecimal.valueOf(1.33333)), 1.3333);
+ Assert.assertEquals(Rounder.round(BigDecimal.valueOf(4444.33333)), 4444.3333);
+ Assert.assertEquals(Rounder.round(BigDecimal.valueOf(10.11111)), 10.1111);
+ Assert.assertEquals(Rounder.round(BigDecimal.valueOf(10.11115)), 10.1112);
+ Assert.assertEquals(Rounder.round(BigDecimal.valueOf(10.11116)), 10.1112);
+ }
+}
osgi-bundles/defaultbundles/pom.xml 4(+4 -0)
diff --git a/osgi-bundles/defaultbundles/pom.xml b/osgi-bundles/defaultbundles/pom.xml
index 3f94eec..1e88c52 100644
--- a/osgi-bundles/defaultbundles/pom.xml
+++ b/osgi-bundles/defaultbundles/pom.xml
@@ -29,6 +29,10 @@
<dependencies>
<dependency>
<groupId>com.ning.billing</groupId>
+ <artifactId>killbill-osgi-bundles-analytics</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
<artifactId>killbill-osgi-bundles-jruby</artifactId>
</dependency>
<dependency>