diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceRecorder.java
index 554ee50..4dfd681 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceRecorder.java
@@ -47,7 +47,10 @@ import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.api.InvoiceUserApi;
import com.ning.billing.util.clock.Clock;
+import com.google.common.annotations.VisibleForTesting;
+
public class BusinessInvoiceRecorder {
+
private static final Logger log = LoggerFactory.getLogger(BusinessInvoiceRecorder.class);
private final AccountUserApi accountApi;
@@ -160,42 +163,35 @@ public class BusinessInvoiceRecorder {
accountSqlDao.saveAccount(account);
}
- private BusinessInvoiceItem createBusinessInvoiceItem(final InvoiceItem invoiceItem) {
- final String externalKey;
- try {
- final SubscriptionBundle bundle = entitlementApi.getBundleFromId(invoiceItem.getBundleId());
- externalKey = bundle.getKey();
- } catch (EntitlementUserApiException e) {
- log.warn("Ignoring invoice item {} for bundle {} (bundle does not exist)",
- invoiceItem.getId().toString(),
- invoiceItem.getBundleId().toString());
- return null;
- }
-
- final Subscription subscription;
- try {
- subscription = entitlementApi.getSubscriptionFromId(invoiceItem.getSubscriptionId());
- } catch (EntitlementUserApiException e) {
- log.warn("Ignoring invoice item {} for subscription {} (subscription does not exist)",
- invoiceItem.getId().toString(),
- invoiceItem.getSubscriptionId().toString());
- return null;
- }
-
- final Plan plan = subscription.getCurrentPlan();
- if (plan == null) {
- log.warn("Ignoring invoice item {} for subscription {} (null plan)",
- invoiceItem.getId().toString(),
- invoiceItem.getSubscriptionId().toString());
- return null;
+ @VisibleForTesting
+ BusinessInvoiceItem createBusinessInvoiceItem(final InvoiceItem invoiceItem) {
+ 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());
+ externalKey = bundle.getKey();
+ } catch (EntitlementUserApiException e) {
+ log.warn("Ignoring subscription fields for invoice item {} for bundle {} (bundle does not exist)",
+ invoiceItem.getId().toString(),
+ invoiceItem.getBundleId().toString());
+ }
}
- final PlanPhase planPhase = subscription.getCurrentPhase();
- if (planPhase == null) {
- log.warn("Ignoring invoice item {} for subscription {} (null phase)",
- invoiceItem.getId().toString(),
- invoiceItem.getSubscriptionId().toString());
- return null;
+ if (invoiceItem.getSubscriptionId() != null) {
+ final Subscription subscription;
+ try {
+ subscription = entitlementApi.getSubscriptionFromId(invoiceItem.getSubscriptionId());
+ plan = subscription.getCurrentPlan();
+ planPhase = subscription.getCurrentPhase();
+ } catch (EntitlementUserApiException e) {
+ log.warn("Ignoring subscription fields for invoice item {} for subscription {} (subscription does not exist)",
+ invoiceItem.getId().toString(),
+ invoiceItem.getSubscriptionId().toString());
+ }
}
return new BusinessInvoiceItem(externalKey, invoiceItem, plan, planPhase);
diff --git a/analytics/src/main/java/com/ning/billing/analytics/model/BusinessInvoiceItem.java b/analytics/src/main/java/com/ning/billing/analytics/model/BusinessInvoiceItem.java
index 518227b..bdbd945 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/model/BusinessInvoiceItem.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/model/BusinessInvoiceItem.java
@@ -19,6 +19,8 @@ package com.ning.billing.analytics.model;
import java.math.BigDecimal;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
@@ -30,6 +32,7 @@ import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.invoice.api.InvoiceItem;
public class BusinessInvoiceItem {
+
private final UUID itemId;
private final DateTime createdDate;
private final DateTime updatedDate;
@@ -47,11 +50,11 @@ public class BusinessInvoiceItem {
private final BigDecimal amount;
private final Currency currency;
- public BusinessInvoiceItem(final BigDecimal amount, final String billingPeriod, final DateTime createdDate,
+ public BusinessInvoiceItem(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, final String itemType, final String phase,
- final String productCategory, final String productName, final String productType,
- final String slug, final LocalDate startDate, final DateTime updatedDate) {
+ final UUID invoiceId, final UUID itemId, 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) {
this.amount = amount;
this.billingPeriod = billingPeriod;
this.createdDate = createdDate;
@@ -70,11 +73,12 @@ public class BusinessInvoiceItem {
this.updatedDate = updatedDate;
}
- public BusinessInvoiceItem(final String externalKey, final InvoiceItem invoiceItem, final Plan plan, final PlanPhase planPhase) {
- this(invoiceItem.getAmount(), planPhase.getBillingPeriod().toString(), new DateTime(DateTimeZone.UTC), invoiceItem.getCurrency(), invoiceItem.getEndDate(),
- externalKey, invoiceItem.getInvoiceId(), invoiceItem.getId(), invoiceItem.getInvoiceItemType().toString(),
- planPhase.getPhaseType().toString(), plan.getProduct().getCategory().toString(), plan.getProduct().getName(), plan.getProduct().getCatalogName(),
- planPhase.getName(), invoiceItem.getStartDate(), new DateTime(DateTimeZone.UTC));
+ public BusinessInvoiceItem(@Nullable final String externalKey, final InvoiceItem invoiceItem, @Nullable final Plan plan, @Nullable final PlanPhase planPhase) {
+ this(invoiceItem.getAmount(), planPhase != null ? planPhase.getBillingPeriod().toString() : null, new DateTime(DateTimeZone.UTC), invoiceItem.getCurrency(),
+ invoiceItem.getEndDate(), externalKey, invoiceItem.getInvoiceId(), invoiceItem.getId(), 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(), new DateTime(DateTimeZone.UTC));
}
public DateTime getCreatedDate() {
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessInvoiceRecorder.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessInvoiceRecorder.java
new file mode 100644
index 0000000..31e76e3
--- /dev/null
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessInvoiceRecorder.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.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.account.api.AccountUserApi;
+import com.ning.billing.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.analytics.model.BusinessInvoiceItem;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.util.clock.Clock;
+
+public class TestBusinessInvoiceRecorder {
+
+ private final AccountUserApi accountApi = Mockito.mock(AccountUserApi.class);
+ private final EntitlementUserApi entitlementApi = Mockito.mock(EntitlementUserApi.class);
+ private final InvoiceUserApi invoiceApi = Mockito.mock(InvoiceUserApi.class);
+ private final BusinessInvoiceSqlDao sqlDao = Mockito.mock(BusinessInvoiceSqlDao.class);
+ private final Clock clock = Mockito.mock(Clock.class);
+
+ @Test(groups = "fast")
+ public void testShouldBeAbleToHandleNullFieldsInInvoiceItem() throws Exception {
+ final BusinessInvoiceRecorder recorder = new BusinessInvoiceRecorder(accountApi, entitlementApi, invoiceApi, sqlDao, clock);
+
+ 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 BusinessInvoiceItem bii = recorder.createBusinessInvoiceItem(invoiceItem);
+ 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());
+ }
+}