killbill-aplcache
Changes
analytics/pom.xml 10(+10 -0)
Details
analytics/pom.xml 10(+10 -0)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index 10f94d4..ad46c31 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -89,6 +89,16 @@
</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>
<scope>test</scope>
</dependency>
diff --git a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
index 1735062..ba9dc2a 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
@@ -22,22 +22,22 @@ import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.account.api.AccountChangeNotification;
import com.ning.billing.account.api.AccountCreationNotification;
import com.ning.billing.entitlement.api.user.SubscriptionTransition;
+import com.ning.billing.invoice.api.InvoiceCreationNotification;
+import com.ning.billing.payment.api.PaymentError;
+import com.ning.billing.payment.api.PaymentInfo;
-public class AnalyticsListener
-{
+public class AnalyticsListener {
private final BusinessSubscriptionTransitionRecorder bstRecorder;
private final BusinessAccountRecorder bacRecorder;
@Inject
- public AnalyticsListener(final BusinessSubscriptionTransitionRecorder bstRecorder, final BusinessAccountRecorder bacRecorder)
- {
+ public AnalyticsListener(final BusinessSubscriptionTransitionRecorder bstRecorder, final BusinessAccountRecorder bacRecorder) {
this.bstRecorder = bstRecorder;
this.bacRecorder = bacRecorder;
}
@Subscribe
- public void handleSubscriptionTransitionChange(final SubscriptionTransition event) throws AccountApiException
- {
+ public void handleSubscriptionTransitionChange(final SubscriptionTransition event) throws AccountApiException {
switch (event.getTransitionType()) {
case MIGRATE_ENTITLEMENT:
// TODO do nothing for now
@@ -68,18 +68,31 @@ public class AnalyticsListener
}
@Subscribe
- public void handleAccountCreation(final AccountCreationNotification event)
- {
+ public void handleAccountCreation(final AccountCreationNotification event) {
bacRecorder.accountCreated(event.getData());
}
@Subscribe
- public void handleAccountChange(final AccountChangeNotification event)
- {
+ public void handleAccountChange(final AccountChangeNotification event) {
if (!event.hasChanges()) {
return;
}
bacRecorder.accountUpdated(event.getAccountId(), event.getChangedFields());
}
+
+ @Subscribe
+ public void handleInvoice(final InvoiceCreationNotification event) {
+ bacRecorder.accountUpdated(event.getAccountId());
+ }
+
+ @Subscribe
+ public void handlePaymentInfo(final PaymentInfo paymentInfo) {
+ bacRecorder.accountUpdated(paymentInfo);
+ }
+
+ @Subscribe
+ public void handlePaymentError(final PaymentError paymentError) {
+ // TODO - we can't tie the error back to an account yet
+ }
}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
index f7081c7..31d1e6c 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
@@ -22,57 +22,164 @@ import com.ning.billing.account.api.AccountData;
import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.account.api.ChangedField;
import com.ning.billing.analytics.dao.BusinessAccountDao;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.payment.api.PaymentApi;
+import com.ning.billing.payment.api.PaymentAttempt;
+import com.ning.billing.payment.api.PaymentInfo;
import com.ning.billing.util.tag.Tag;
+import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-public class BusinessAccountRecorder
-{
+public class BusinessAccountRecorder {
private static final Logger log = LoggerFactory.getLogger(BusinessAccountRecorder.class);
private final BusinessAccountDao dao;
private final AccountUserApi accountApi;
+ private final InvoiceUserApi invoiceUserApi;
+ private final PaymentApi paymentApi;
@Inject
- public BusinessAccountRecorder(final BusinessAccountDao dao, final AccountUserApi accountApi)
- {
+ public BusinessAccountRecorder(final BusinessAccountDao dao, final AccountUserApi accountApi, final InvoiceUserApi invoiceUserApi, final PaymentApi paymentApi) {
this.dao = dao;
this.accountApi = accountApi;
+ this.invoiceUserApi = invoiceUserApi;
+ this.paymentApi = paymentApi;
}
- public void accountCreated(final AccountData data)
- {
+ public void accountCreated(final AccountData data) {
final Account account = accountApi.getAccountByKey(data.getExternalKey());
+ final BusinessAccount bac = createBusinessAccountFromAccount(account);
+ log.info("ACCOUNT CREATION " + bac);
+ dao.createAccount(bac);
+ }
+
+ /**
+ * Notification handler for Account changes
+ *
+ * @param accountId account id changed
+ * @param changedFields list of changed fields
+ */
+ public void accountUpdated(final UUID accountId, final List<ChangedField> changedFields) {
+ // None of the fields updated interest us so far - see DefaultAccountChangeNotification
+ // TODO We'll need notifications for tags changes eventually
+ }
+
+ /**
+ * Notification handler for Payment creations
+ *
+ * @param paymentInfo payment object (from the payment plugin)
+ */
+ public void accountUpdated(final PaymentInfo paymentInfo) {
+ final PaymentAttempt paymentAttempt = paymentApi.getPaymentAttemptForPaymentId(paymentInfo.getPaymentId());
+ if (paymentAttempt == null) {
+ return;
+ }
+
+ final Account account = accountApi.getAccountById(paymentAttempt.getAccountId());
+ if (account == null) {
+ return;
+ }
+
+ accountUpdated(account.getId());
+ }
+
+ /**
+ * Notification handler for Invoice creations
+ *
+ * @param accountId account id associated with the created invoice
+ */
+ public void accountUpdated(final UUID accountId) {
+ final Account account = accountApi.getAccountById(accountId);
+ BusinessAccount bac = dao.getAccount(accountId.toString());
+
+ if (account == null) {
+ log.warn("Couldn't find account {}", accountId);
+ } else if (bac == null) {
+ bac = createBusinessAccountFromAccount(account);
+ log.info("ACCOUNT CREATION " + bac);
+ dao.createAccount(bac);
+ } else {
+ updateBusinessAccountFromAccount(account, bac);
+ log.info("ACCOUNT UPDATE " + bac);
+ dao.saveAccount(bac);
+ }
+ }
+
+ private BusinessAccount createBusinessAccountFromAccount(final Account account) {
final List<String> tags = new ArrayList<String>();
for (final Tag tag : account.getTagList()) {
tags.add(tag.getTagDefinitionName());
}
- // TODO Need payment and invoice api to fill most fields
final BusinessAccount bac = new BusinessAccount(
- account.getExternalKey(),
- null, // TODO
- tags,
- null, // TODO
- null, // TODO
- null, // TODO
- null, // TODO
- null, // TODO
- null // TODO
+ account.getExternalKey(),
+ null, // TODO We need an API for the account balance
+ tags,
+ // These fields will be updated below
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
);
+ updateBusinessAccountFromAccount(account, bac);
- log.info("ACCOUNT CREATION " + bac);
- dao.createAccount(bac);
+ return bac;
}
- public void accountUpdated(final UUID accountId, final List<ChangedField> changedFields)
- {
- // None of the fields updated interest us so far - see DefaultAccountChangeNotification
- // TODO We'll need notifications for tags changes eventually
+ private void updateBusinessAccountFromAccount(final Account account, final BusinessAccount bac) {
+ DateTime lastInvoiceDate = null;
+ BigDecimal totalInvoiceBalance = BigDecimal.ZERO;
+ String lastPaymentStatus = null;
+ String paymentMethod = null;
+ String creditCardType = null;
+ String billingAddressCountry = null;
+
+ // Retrieve invoices information
+ final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId());
+ if (invoices != null && invoices.size() > 0) {
+ final List<String> invoiceIds = new ArrayList<String>();
+ for (final Invoice invoice : invoices) {
+ invoiceIds.add(invoice.getId().toString());
+ 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<PaymentInfo> payments = paymentApi.getPaymentInfo(invoiceIds);
+ if (payments != null) {
+ for (final PaymentInfo payment : payments) {
+ // Use the last payment method/type/country as the default one for the account
+ if (lastPaymentDate == null || payment.getCreatedDate().isAfter(lastPaymentDate)) {
+ lastPaymentDate = payment.getCreatedDate();
+
+ lastPaymentStatus = payment.getStatus();
+ paymentMethod = payment.getPaymentMethod();
+ creditCardType = payment.getCardType();
+ billingAddressCountry = payment.getCardCountry();
+ }
+ }
+ }
+ }
+
+ bac.setLastPaymentStatus(lastPaymentStatus);
+ bac.setPaymentMethod(paymentMethod);
+ bac.setCreditCardType(creditCardType);
+ bac.setBillingAddressCountry(billingAddressCountry);
+ bac.setLastInvoiceDate(lastInvoiceDate);
+ bac.setTotalInvoiceBalance(totalInvoiceBalance);
}
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
index 25496b5..5c7ffae 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
@@ -16,6 +16,8 @@
package com.ning.billing.analytics;
+import com.ning.billing.invoice.glue.InvoiceModule;
+import com.ning.billing.payment.setup.PaymentModule;
import org.skife.jdbi.v2.IDBI;
import com.ning.billing.account.glue.AccountModule;
import com.ning.billing.analytics.setup.AnalyticsModule;
@@ -41,6 +43,8 @@ public class AnalyticsTestModule extends AnalyticsModule
install(new CatalogModule());
install(new BusModule());
install(new EntitlementModule());
+ install(new InvoiceModule());
+ install(new PaymentModule());
install(new ClockModule());
install(new TagStoreModule());
install(new NotificationQueueModule());
diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index c413f0d..83419a2 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -139,12 +139,16 @@ public class TestAnalyticsService
final String analyticsDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/analytics/ddl.sql"));
final String accountDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
final String entitlementDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/entitlement/ddl.sql"));
+ final String invoiceDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
+ final String paymentDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/payment/ddl.sql"));
final String utilDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
helper.startMysql();
helper.initDb(analyticsDdl);
helper.initDb(accountDdl);
helper.initDb(entitlementDdl);
+ helper.initDb(invoiceDdl);
+ helper.initDb(paymentDdl);
helper.initDb(utilDdl);
}
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/DefaultPaymentDao.java b/payment/src/main/java/com/ning/billing/payment/dao/DefaultPaymentDao.java
index b505fa0..8c1611d 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/DefaultPaymentDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/DefaultPaymentDao.java
@@ -20,6 +20,7 @@ import java.util.Date;
import java.util.List;
import java.util.UUID;
+import com.google.common.collect.ImmutableList;
import com.ning.billing.util.clock.Clock;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.IDBI;
@@ -29,6 +30,8 @@ import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.payment.api.PaymentAttempt;
import com.ning.billing.payment.api.PaymentInfo;
+import javax.annotation.concurrent.Immutable;
+
public class DefaultPaymentDao implements PaymentDao {
private final PaymentSqlDao sqlDao;
private final Clock clock;
@@ -80,12 +83,20 @@ public class DefaultPaymentDao implements PaymentDao {
@Override
public List<PaymentInfo> getPaymentInfo(List<String> invoiceIds) {
- return sqlDao.getPaymentInfos(invoiceIds);
+ if (invoiceIds == null || invoiceIds.size() == 0) {
+ return ImmutableList.<PaymentInfo>of();
+ } else {
+ return sqlDao.getPaymentInfos(invoiceIds);
+ }
}
@Override
public List<PaymentAttempt> getPaymentAttemptsForInvoiceIds(List<String> invoiceIds) {
- return sqlDao.getPaymentAttemptsForInvoiceIds(invoiceIds);
+ if (invoiceIds == null || invoiceIds.size() == 0) {
+ return ImmutableList.<PaymentAttempt>of();
+ } else {
+ return sqlDao.getPaymentAttemptsForInvoiceIds(invoiceIds);
+ }
}
@Override