killbill-aplcache
Changes
account/pom.xml 2(+1 -1)
analytics/pom.xml 2(+1 -1)
api/pom.xml 2(+1 -1)
beatrix/pom.xml 2(+1 -1)
catalog/pom.xml 2(+1 -1)
entitlement/pom.xml 2(+1 -1)
entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java 5(+4 -1)
invoice/pom.xml 2(+1 -1)
invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java 232(+114 -118)
payment/pom.xml 2(+1 -1)
pom.xml 2(+1 -1)
util/pom.xml 2(+1 -1)
Details
account/pom.xml 2(+1 -1)
diff --git a/account/pom.xml b/account/pom.xml
index 153f0bd..141e6cb 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
analytics/pom.xml 2(+1 -1)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index 7368654..18bd687 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-analytics</artifactId>
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index 7c0dcd7..afbca6a 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index d7bd49e..4e1ffaa 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -69,7 +69,7 @@ public enum ErrorCode {
CAT_NO_PRICE_FOR_CURRENCY(2010, "This price does not have a value for the currency '%s'."),
/* Price value explicitly set to NULL meaning there is no price available in that currency */
- CAT_PRICE_VALUE_NULL_FOR_CURRENCY(2011, "The value for the currency '%s' is NULL. This plan cannot be bought in this currnency."),
+ CAT_PRICE_VALUE_NULL_FOR_CURRENCY(2011, "The value for the currency '%s' is NULL. This plan cannot be bought in this currency."),
CAT_NULL_PRICE_LIST_NAME(2012,"Price list name was null"),
CAT_PRICE_LIST_NOT_FOUND(2013, "Could not find a pricelist with name '%s'"),
/*
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
index 44c46a7..a9070fd 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
@@ -34,9 +34,11 @@ public interface InvoiceItem extends Entity, Comparable<InvoiceItem> {
String getDescription();
- BigDecimal getAmount();
+ BigDecimal getRecurringAmount();
- BigDecimal getRate();
+ BigDecimal getRecurringRate();
+
+ BigDecimal getFixedAmount();
Currency getCurrency();
diff --git a/api/src/main/java/com/ning/billing/invoice/api/test/InvoiceTestApi.java b/api/src/main/java/com/ning/billing/invoice/api/test/InvoiceTestApi.java
new file mode 100644
index 0000000..9edcd8c
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/test/InvoiceTestApi.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010-2011 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.invoice.api.test;
+
+import com.ning.billing.invoice.api.Invoice;
+
+public interface InvoiceTestApi {
+ public void create(Invoice invoice);
+}
beatrix/pom.xml 2(+1 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 792a09e..ded6f0f 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-beatrix</artifactId>
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
index a4a4ce2..83115de 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
@@ -16,7 +16,6 @@
package com.ning.billing.beatrix.lifecycle;
-
import com.ning.billing.lifecycle.KillbillService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,7 +24,13 @@ import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
import java.util.jar.JarFile;
public class ServiceFinder {
@@ -81,8 +86,6 @@ public class ServiceFinder {
}
for (int h = 0; h < classPaths.length; h++) {
-
-
Enumeration<?> files = null;
JarFile module = null;
File classPath = new File( (URL.class).isInstance(classPaths[h]) ?
@@ -93,7 +96,7 @@ public class ServiceFinder {
List<String> dirListing = new ArrayList<String>();
recursivelyListDir(dirListing, classPath, new StringBuffer() );
- files = Collections.enumeration( dirListing );
+ files = Collections.enumeration(dirListing);
} else if (classPath.getName().endsWith(".jar")) {
log.debug("JAR : " + classPath);
catalog/pom.xml 2(+1 -1)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index 09e0e48..635fac3 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
index c290979..cc3a679 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
@@ -19,7 +19,6 @@ package com.ning.billing.catalog;
import com.ning.billing.catalog.api.Currency;
import java.math.BigDecimal;
-import java.util.Date;
public class MockInternationalPrice extends DefaultInternationalPrice {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
index b9e9afe..53c73fe 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
@@ -34,6 +34,14 @@ public class MockPlan extends DefaultPlan {
setPlansAllowedInBundle(1);
}
+ public MockPlan(String planName) {
+ setName(planName);
+ setProduct(new MockProduct());
+ setFinalPhase(new MockPlanPhase(this));
+ setInitialPhases(null);
+ setPlansAllowedInBundle(1);
+ }
+
public MockPlan(MockPlanPhase mockPlanPhase) {
setName("test-plan");
setProduct(new MockProduct());
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index b75837c..805436d 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
index c212b75..4c5e0af 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
@@ -64,10 +64,13 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
for (final Subscription subscription: subscriptions) {
for (final SubscriptionTransition transition : subscription.getAllTransitions()) {
try {
- result.add(new DefaultBillingEvent(transition, subscription, calculateBCD(transition, accountId)));
+ BillingEvent event = new DefaultBillingEvent(transition, subscription, calculateBCD(transition, accountId));
+ result.add(event);
} catch (CatalogApiException e) {
log.error("Failing to identify catalog components while creating BillingEvent from transition: " +
transition.getId().toString(), e);
+ } catch (Exception e) {
+ log.warn("Failed while getting BillingEvent", e);
}
}
}
invoice/pom.xml 2(+1 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 6b7cb14..e685de0 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-invoice</artifactId>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/test/DefaultInvoiceTestApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/test/DefaultInvoiceTestApi.java
new file mode 100644
index 0000000..bbec57f
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/test/DefaultInvoiceTestApi.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2011 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.invoice.api.test;
+
+import com.google.inject.Inject;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.dao.InvoiceDao;
+
+public class DefaultInvoiceTestApi implements InvoiceTestApi {
+ private final InvoiceDao invoiceDao;
+
+ @Inject
+ public DefaultInvoiceTestApi(InvoiceDao invoiceDao) {
+ this.invoiceDao = invoiceDao;
+ }
+
+ @Override
+ public void create(Invoice invoice) {
+ invoiceDao.create(invoice);
+ }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index aa2cb63..4d963bb 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -239,13 +239,17 @@ public class DefaultInvoiceDao implements InvoiceDao {
private void notifyOfFutureBillingEvents(final InvoiceSqlDao dao, final List<InvoiceItem> invoiceItems) {
for (final InvoiceItem item : invoiceItems) {
- notifier.insertNextBillingNotification(dao, item.getSubscriptionId(), item.getEndDate());
+ if (item.getEndDate() != null) {
+ notifier.insertNextBillingNotification(dao, item.getSubscriptionId(), item.getEndDate());
+ }
}
}
private void setChargedThroughDates(final InvoiceSqlDao dao, final Collection<InvoiceItem> invoiceItems) {
for (InvoiceItem invoiceItem : invoiceItems) {
- entitlementBillingApi.setChargedThroughDateFromTransaction(dao, invoiceItem.getSubscriptionId(), invoiceItem.getEndDate());
+ if (invoiceItem.getEndDate() != null) {
+ entitlementBillingApi.setChargedThroughDateFromTransaction(dao, invoiceItem.getSubscriptionId(), invoiceItem.getEndDate());
+ }
}
}
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
index 6f4e47b..76e0dbf 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
@@ -19,17 +19,26 @@ package com.ning.billing.invoice.dao;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.model.DefaultInvoiceItem;
-import com.ning.billing.util.entity.EntityCollectionDao;
import com.ning.billing.util.entity.EntityDao;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.SQLStatement;
import org.skife.jdbi.v2.StatementContext;
-import org.skife.jdbi.v2.sqlobject.*;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlBatch;
+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 org.skife.jdbi.v2.tweak.ResultSetMapper;
-import java.lang.annotation.*;
+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.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -71,10 +80,11 @@ public interface InvoiceItemSqlDao extends EntityDao<InvoiceItem> {
q.bind("invoiceId", item.getInvoiceId().toString());
q.bind("subscriptionId", item.getSubscriptionId().toString());
q.bind("startDate", item.getStartDate().toDate());
- q.bind("endDate", item.getEndDate().toDate());
+ q.bind("endDate", item.getEndDate() == null ? null : item.getEndDate().toDate());
q.bind("description", item.getDescription());
- q.bind("amount", item.getAmount());
- q.bind("rate", item.getRate());
+ q.bind("recurringAmount", item.getRecurringAmount() == null ? BigDecimal.ZERO : item.getRecurringAmount());
+ q.bind("recurringRate", item.getRecurringRate() == null ? BigDecimal.ZERO : item.getRecurringRate());
+ q.bind("fixedAmount", item.getFixedAmount() == null ? BigDecimal.ZERO : item.getFixedAmount());
q.bind("currency", item.getCurrency().toString());
}
};
@@ -91,11 +101,13 @@ public interface InvoiceItemSqlDao extends EntityDao<InvoiceItem> {
DateTime startDate = new DateTime(result.getTimestamp("start_date"));
DateTime endDate = new DateTime(result.getTimestamp("end_date"));
String description = result.getString("description");
- BigDecimal amount = result.getBigDecimal("amount");
- BigDecimal rate = result.getBigDecimal("rate");
+ BigDecimal recurringAmount = result.getBigDecimal("recurring_amount");
+ BigDecimal recurringRate = result.getBigDecimal("recurring_rate");
+ BigDecimal fixedAmount = result.getBigDecimal("fixed_amount");
Currency currency = Currency.valueOf(result.getString("currency"));
- return new DefaultInvoiceItem(id, invoiceId, subscriptionId, startDate, endDate, description, amount, rate , currency);
+ return new DefaultInvoiceItem(id, invoiceId, subscriptionId, startDate, endDate,
+ description, recurringAmount, recurringRate, fixedAmount, currency);
}
}
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java b/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java
index 54efe1b..ec42757 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java
@@ -108,9 +108,9 @@ public class InvoiceListener {
Invoice invoice = generator.generateInvoice(accountId, billingEvents, invoiceItemList, targetDate, targetCurrency);
if (invoice != null) {
- //if (invoice.getNumberOfItems() > 0) {
+ if (invoice.getNumberOfItems() > 0) {
invoiceDao.create(invoice);
- //}
+ }
}
}
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
index 899b4a5..47f5d67 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
@@ -35,12 +35,14 @@ import com.ning.billing.entitlement.api.billing.BillingModeType;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
+import javax.annotation.Nullable;
+
public class DefaultInvoiceGenerator implements InvoiceGenerator {
private static final Logger log = LoggerFactory.getLogger(DefaultInvoiceGenerator.class);
@Override
public Invoice generateInvoice(final UUID accountId, final BillingEventSet events,
- final InvoiceItemList existingItems, final DateTime targetDate,
+ @Nullable final InvoiceItemList existingItems, final DateTime targetDate,
final Currency targetCurrency) {
if (events == null) {return null;}
if (events.size() == 0) {return null;}
@@ -94,6 +96,8 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
currentItems.add(existingItem.asCredit(existingItem.getInvoiceId()));
}
+ currentItems.cleanupDuplicatedItems();
+
return currentItems;
}
@@ -128,18 +132,21 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
private void processEvent(final UUID invoiceId, final BillingEvent event, final List<InvoiceItem> items,
final DateTime targetDate, final Currency targetCurrency) {
try {
- //TODO: Jeff getPrice() -> getRecurringPrice()
- InternationalPrice recurringPrice = event.getRecurringPrice();
- BigDecimal rate = (recurringPrice == null) ? BigDecimal.ZERO : recurringPrice.getPrice(targetCurrency);
+ BigDecimal recurringRate = event.getRecurringPrice() == null ? null : event.getRecurringPrice().getPrice(targetCurrency);
+ BigDecimal fixedPrice = event.getFixedPrice() == null ? null : event.getFixedPrice().getPrice(targetCurrency);
- BigDecimal numberOfBillingPeriods = calculateNumberOfBillingPeriods(event, targetDate);
- if (numberOfBillingPeriods.compareTo(BigDecimal.ZERO) != 0) {
- BigDecimal invoiceItemAmount = numberOfBillingPeriods.multiply(rate);
- BillingMode billingMode = getBillingMode(event.getBillingMode());
- DateTime billThroughDate = billingMode.calculateEffectiveEndDate(event.getEffectiveDate(), targetDate, event.getBillCycleDay(), event.getBillingPeriod());
+ BigDecimal numberOfBillingPeriods;
+ BigDecimal recurringAmount =null;
- addInvoiceItem(invoiceId, items, event, billThroughDate, invoiceItemAmount, rate, targetCurrency);
+ if (recurringRate != null) {
+ numberOfBillingPeriods = calculateNumberOfBillingPeriods(event, targetDate);
+ recurringAmount = numberOfBillingPeriods.multiply(recurringRate);
}
+
+ BillingMode billingMode = getBillingMode(event.getBillingMode());
+ DateTime billThroughDate = billingMode.calculateEffectiveEndDate(event.getEffectiveDate(), targetDate, event.getBillCycleDay(), event.getBillingPeriod());
+
+ addInvoiceItem(invoiceId, items, event, billThroughDate, recurringAmount, recurringRate, fixedPrice, targetCurrency);
} catch (CatalogApiException e) {
log.error(String.format("Encountered a catalog error processing invoice %s for billing event on date %s",
invoiceId.toString(),
@@ -150,18 +157,21 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
private void processEvents(final UUID invoiceId, final BillingEvent firstEvent, final BillingEvent secondEvent,
final List<InvoiceItem> items, final DateTime targetDate, final Currency targetCurrency) {
try {
- InternationalPrice recurringPrice = firstEvent.getRecurringPrice();
- if (recurringPrice != null) {
- BigDecimal rate = recurringPrice.getPrice(targetCurrency);
- BigDecimal numberOfBillingPeriods = calculateNumberOfBillingPeriods(firstEvent, secondEvent, targetDate);
- if (numberOfBillingPeriods.compareTo(BigDecimal.ZERO) != 0) {
- BigDecimal invoiceItemAmount = numberOfBillingPeriods.multiply(rate);
- BillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
- DateTime billThroughDate = billingMode.calculateEffectiveEndDate(firstEvent.getEffectiveDate(), secondEvent.getEffectiveDate(), targetDate, firstEvent.getBillCycleDay(), firstEvent.getBillingPeriod());
-
- addInvoiceItem(invoiceId, items, firstEvent, billThroughDate, invoiceItemAmount, rate, targetCurrency);
- }
+ BigDecimal recurringRate = firstEvent.getRecurringPrice() == null ? null : firstEvent.getRecurringPrice().getPrice(targetCurrency);
+ BigDecimal fixedPrice = firstEvent.getFixedPrice() == null ? null : firstEvent.getFixedPrice().getPrice(targetCurrency);
+
+ BigDecimal numberOfBillingPeriods;
+ BigDecimal recurringAmount =null;
+
+ if (recurringRate != null) {
+ numberOfBillingPeriods = calculateNumberOfBillingPeriods(firstEvent, secondEvent, targetDate);
+ recurringAmount = numberOfBillingPeriods.multiply(recurringRate);
}
+
+ BillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
+ DateTime billThroughDate = billingMode.calculateEffectiveEndDate(firstEvent.getEffectiveDate(), secondEvent.getEffectiveDate(), targetDate, firstEvent.getBillCycleDay(), firstEvent.getBillingPeriod());
+
+ addInvoiceItem(invoiceId, items, firstEvent, billThroughDate, recurringAmount, recurringRate, fixedPrice, targetCurrency);
} catch (CatalogApiException e) {
log.error(String.format("Encountered a catalog error processing invoice %s for billing event on date %s",
invoiceId.toString(),
@@ -171,8 +181,9 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
private void addInvoiceItem(final UUID invoiceId, final List<InvoiceItem> items, final BillingEvent event,
final DateTime billThroughDate, final BigDecimal amount, final BigDecimal rate,
- final Currency currency) {
- DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, event.getSubscription().getId(), event.getEffectiveDate(), billThroughDate, event.getDescription(), amount, rate, currency);
+ final BigDecimal fixedAmount, final Currency currency) {
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, event.getSubscription().getId(), event.getEffectiveDate(),
+ billThroughDate, event.getDescription(), amount, rate, fixedAmount, currency);
items.add(item);
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceItem.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceItem.java
index eb54aeb..136967c 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceItem.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceItem.java
@@ -20,6 +20,7 @@ import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.api.InvoiceItem;
import org.joda.time.DateTime;
+import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.util.UUID;
@@ -30,23 +31,30 @@ public class DefaultInvoiceItem implements InvoiceItem {
private DateTime startDate;
private DateTime endDate;
private final String description;
- private BigDecimal amount;
- private final BigDecimal rate;
+ private BigDecimal recurringAmount;
+ private final BigDecimal recurringRate;
+ private BigDecimal fixedAmount;
private final Currency currency;
- public DefaultInvoiceItem(UUID invoiceId, UUID subscriptionId, DateTime startDate, DateTime endDate, String description, BigDecimal amount, BigDecimal rate, Currency currency) {
- this(UUID.randomUUID(), invoiceId, subscriptionId, startDate, endDate, description, amount, rate, currency);
+ public DefaultInvoiceItem(UUID invoiceId, UUID subscriptionId, DateTime startDate, DateTime endDate,
+ String description, BigDecimal recurringAmount, BigDecimal recurringRate,
+ BigDecimal fixedAmount, Currency currency) {
+ this(UUID.randomUUID(), invoiceId, subscriptionId, startDate, endDate, description,
+ recurringAmount, recurringRate, fixedAmount, currency);
}
- public DefaultInvoiceItem(UUID id, UUID invoiceId, UUID subscriptionId, DateTime startDate, DateTime endDate, String description, BigDecimal amount, BigDecimal rate, Currency currency) {
+ public DefaultInvoiceItem(UUID id, UUID invoiceId, UUID subscriptionId, DateTime startDate, DateTime endDate,
+ String description, BigDecimal recurringAmount, BigDecimal recurringRate,
+ BigDecimal fixedAmount, Currency currency) {
this.id = id;
this.invoiceId = invoiceId;
this.subscriptionId = subscriptionId;
this.startDate = startDate;
this.endDate = endDate;
this.description = description;
- this.amount = amount;
- this.rate = rate;
+ this.recurringAmount = recurringAmount;
+ this.recurringRate = recurringRate;
+ this.fixedAmount = fixedAmount;
this.currency = currency;
}
@@ -57,14 +65,18 @@ public class DefaultInvoiceItem implements InvoiceItem {
this.startDate = that.getStartDate();
this.endDate = that.getEndDate();
this.description = that.getDescription();
- this.amount = that.getAmount();
- this.rate = that.getRate();
+ this.recurringAmount = that.getRecurringAmount();
+ this.recurringRate = that.getRecurringRate();
+ this.fixedAmount = that.getFixedAmount();
this.currency = that.getCurrency();
}
@Override
public InvoiceItem asCredit(UUID invoiceId) {
- return new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, description, amount.negate(), rate, currency);
+ BigDecimal recurringAmountNegated = recurringAmount == null ? null : recurringAmount.negate();
+ BigDecimal fixedAmountNegated = fixedAmount == null ? null : fixedAmount.negate();
+ return new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, description,
+ recurringAmountNegated, recurringRate, fixedAmountNegated, currency);
}
@Override
@@ -98,13 +110,18 @@ public class DefaultInvoiceItem implements InvoiceItem {
}
@Override
- public BigDecimal getAmount() {
- return amount;
+ public BigDecimal getRecurringAmount() {
+ return recurringAmount;
}
@Override
- public BigDecimal getRate() {
- return rate;
+ public BigDecimal getRecurringRate() {
+ return recurringRate;
+ }
+
+ @Override
+ public BigDecimal getFixedAmount() {
+ return fixedAmount;
}
@Override
@@ -113,11 +130,20 @@ public class DefaultInvoiceItem implements InvoiceItem {
}
@Override
- public int compareTo(InvoiceItem invoiceItem) {
- int compareSubscriptions = getSubscriptionId().compareTo(invoiceItem.getSubscriptionId());
+ public int compareTo(InvoiceItem that) {
+ int compareSubscriptions = getSubscriptionId().compareTo(that.getSubscriptionId());
if (compareSubscriptions == 0) {
- return getStartDate().compareTo(invoiceItem.getStartDate());
+ // move null end dates to the end of the set
+ if ((this.endDate != null) && (that.getEndDate() == null)) {
+ return -1;
+ }
+
+ if ((this.endDate == null) && (that.getEndDate() != null)) {
+ return 1;
+ }
+
+ return getStartDate().compareTo(that.getStartDate());
} else {
return compareSubscriptions;
}
@@ -128,44 +154,89 @@ public class DefaultInvoiceItem implements InvoiceItem {
public void subtract(InvoiceItem that) {
if (this.startDate.equals(that.getStartDate()) && this.endDate.equals(that.getEndDate())) {
this.startDate = this.endDate;
- this.amount = this.amount.subtract(that.getAmount());
+ this.recurringAmount = safeSubtract(this.recurringAmount, that.getRecurringAmount());
+ this.fixedAmount = safeSubtract(this.fixedAmount, that.getFixedAmount());
} else {
if (this.startDate.equals(that.getStartDate())) {
this.startDate = that.getEndDate();
- this.amount = this.amount.subtract(that.getAmount());
+ this.recurringAmount = safeSubtract(this.recurringAmount, that.getRecurringAmount());
+ this.fixedAmount = safeSubtract(this.fixedAmount, that.getFixedAmount());
}
if (this.endDate.equals(that.getEndDate())) {
this.endDate = that.getStartDate();
- this.amount = this.amount.subtract(that.getAmount());
+ this.recurringAmount = safeSubtract(this.recurringAmount, that.getRecurringAmount());
+ this.fixedAmount = safeSubtract(this.fixedAmount, that.getFixedAmount());
}
}
}
+ private BigDecimal safeSubtract(BigDecimal minuend, BigDecimal subtrahend) {
+ // minuend - subtrahend == difference
+ if (minuend == null) {
+ if (subtrahend == null) {
+ return BigDecimal.ZERO;
+ } else {
+ return subtrahend.negate();
+ }
+ } else {
+ if (subtrahend == null) {
+ return minuend;
+ } else {
+ return minuend.subtract(subtrahend);
+ }
+ }
+
+ }
+
@Override
public boolean duplicates(InvoiceItem that) {
if(!this.getSubscriptionId().equals(that.getSubscriptionId())) {return false;}
- if(!this.getRate().equals(that.getRate())) {return false;}
+
+ //if (!compareNullableBigDecimal(this.getRecurringAmount(), that.getRecurringAmount())) {return false;}
+ if (!compareNullableBigDecimal(this.getRecurringRate(), that.getRecurringRate())) {return false;}
+ if (!compareNullableBigDecimal(this.getFixedAmount(), that.getFixedAmount())) {return false;}
+
if(!this.getCurrency().equals(that.getCurrency())) {return false;}
DateRange thisDateRange = new DateRange(this.getStartDate(), this.getEndDate());
return thisDateRange.contains(that.getStartDate()) && thisDateRange.contains(that.getEndDate());
}
+ private boolean compareNullableBigDecimal(@Nullable BigDecimal value1, @Nullable BigDecimal value2) {
+ if ((value1 == null) && (value2 != null)) {return false;}
+ if ((value1 != null) && (value2 == null)) {return false;}
+
+ if ((value1 != null) && (value2 != null)) {
+ if (!value1.equals(value2)) {return false;}
+ }
+
+ return true;
+ }
+
/**
* indicates whether the supplied item is a cancelling item for this item
- * @param that
- * @return
+ * @param that the InvoiceItem to be examined
+ * @return true if the two invoice items cancel each other out (same subscription, same date range, sum of amounts = 0)
*/
@Override
public boolean cancels(InvoiceItem that) {
if(!this.getSubscriptionId().equals(that.getSubscriptionId())) {return false;}
if(!this.getEndDate().equals(that.getEndDate())) {return false;}
if(!this.getStartDate().equals(that.getStartDate())) {return false;}
- if(!this.getAmount().equals(that.getAmount().negate())) {return false;}
- if(!this.getRate().equals(that.getRate())) {return false;}
+
+ if (!safeCheckForZeroSum(this.getRecurringAmount(), that.getRecurringAmount())) {return false;}
+ if(!this.getRecurringRate().equals(that.getRecurringRate())) {return false;}
+
+ if (!safeCheckForZeroSum(this.getFixedAmount(), that.getFixedAmount())) {return false;}
if(!this.getCurrency().equals(that.getCurrency())) {return false;}
return true;
}
+
+ private boolean safeCheckForZeroSum(final BigDecimal value1, final BigDecimal value2) {
+ if ((value1 == null) && (value2 == null)) {return true;}
+ if ((value1 == null) ^ (value2 == null)) {return false;}
+ return (value1.add(value2).compareTo(BigDecimal.ZERO) == 0);
+ }
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java
index b4d81a7..626993e 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java
@@ -20,8 +20,9 @@ import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.api.Invoice;
import org.joda.time.DateTime;
+import javax.annotation.Nullable;
import java.util.UUID;
public interface InvoiceGenerator {
- public Invoice generateInvoice(UUID accountId, BillingEventSet events, InvoiceItemList items, DateTime targetDate, Currency targetCurrency);
+ public Invoice generateInvoice(UUID accountId, BillingEventSet events, @Nullable InvoiceItemList items, DateTime targetDate, Currency targetCurrency);
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
index 8cae782..5a10928 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
@@ -18,12 +18,14 @@ package com.ning.billing.invoice.model;
import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import com.ning.billing.invoice.api.InvoiceItem;
public class InvoiceItemList extends ArrayList<InvoiceItem> {
private static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
private static final int ROUNDING_METHOD = InvoicingConfiguration.getRoundingMethod();
+
public InvoiceItemList() {
super();
}
@@ -34,11 +36,17 @@ public class InvoiceItemList extends ArrayList<InvoiceItem> {
}
public BigDecimal getTotalAmount() {
- // TODO: Jeff -- naive implementation, assumes all invoice items share the same currency
- BigDecimal total = new BigDecimal("0");
+ // naive implementation, assumes all invoice items share the same currency
+ BigDecimal total = BigDecimal.ZERO.setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
for (final InvoiceItem item : this) {
- total = total.add(item.getAmount());
+ if (item.getRecurringAmount() != null) {
+ total = total.add(item.getRecurringAmount());
+ }
+
+ if (item.getFixedAmount() != null) {
+ total = total.add(item.getFixedAmount());
+ }
}
return total.setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
@@ -60,4 +68,21 @@ public class InvoiceItemList extends ArrayList<InvoiceItem> {
this.removeAll(itemsToRemove);
}
+
+ /*
+ * removes items from the list that have a recurring amount of zero, but a recurring rate that is not zero
+ */
+ public void cleanupDuplicatedItems() {
+ Iterator<InvoiceItem> iterator = this.iterator();
+ while (iterator.hasNext()) {
+ InvoiceItem item = iterator.next();
+ Boolean hasZeroRecurringAmount = item.getRecurringAmount() == null || (item.getRecurringAmount().compareTo(BigDecimal.ZERO) == 0);
+ Boolean hasRecurringRate = item.getRecurringRate() == null || (item.getRecurringRate().compareTo(BigDecimal.ZERO) != 0);
+ Boolean hasZeroFixedAmount = item.getFixedAmount() == null || (item.getFixedAmount().compareTo(BigDecimal.ZERO) == 0);
+
+ if (hasZeroRecurringAmount && hasRecurringRate & hasZeroFixedAmount) {
+ iterator.remove();
+ }
+ }
+ }
}
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
index 4dc783f..39fcd24 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
@@ -1,39 +1,54 @@
group InvoiceItemDao;
+invoiceItemFields(prefix) ::= <<
+ <prefix>id,
+ <prefix>invoice_id,
+ <prefix>subscription_id,
+ <prefix>start_date,
+ <prefix>end_date,
+ <prefix>description,
+ <prefix>recurring_amount,
+ <prefix>recurring_rate,
+ <prefix>fixed_amount,
+ <prefix>currency
+>>
+
getById() ::= <<
- SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+ SELECT <invoiceItemFields()>
FROM invoice_items
WHERE id = :id;
>>
getInvoiceItemsByInvoice() ::= <<
- SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+ SELECT <invoiceItemFields()>
FROM invoice_items
WHERE invoice_id = :invoiceId;
>>
getInvoiceItemsByAccount() ::= <<
- SELECT ii.id, ii.invoice_id, ii.subscription_id, ii.start_date, ii.end_date, ii.description, ii.amount, ii.rate, ii.currency
+ SELECT <invoiceItemFields("ii.")>
FROM invoice_items ii
INNER JOIN invoices i ON i.id = ii.invoice_id
WHERE i.account_id = :accountId;
>>
getInvoiceItemsBySubscription() ::= <<
- SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+ SELECT <invoiceItemFields()>
FROM invoice_items
WHERE subscription_id = :subscriptionId;
>>
create() ::= <<
- INSERT INTO invoice_items(id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency)
- VALUES(:id, :invoiceId, :subscriptionId, :startDate, :endDate, :description, :amount, :rate, :currency);
+ INSERT INTO invoice_items(<invoiceItemFields()>)
+ VALUES(:id, :invoiceId, :subscriptionId, :startDate, :endDate, :description,
+ :recurringAmount, :recurringRate, :fixedAmount, :currency);
>>
update() ::= <<
UPDATE invoice_items
SET invoice_id = :invoiceId, subscription_id = :subscriptionId, start_date = :startDate, end_date = :endDate,
- description = :description, amount = :amount, rate = :rate, currency = :currency
+ description = :description, recurring_amount = :recurringAmount, recurring_rate = :recurringRate,
+ fixed_amount = :fixedAmount, currency = :currency
WHERE id = :id;
>>
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql b/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
index da13062..348f423 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
+++ b/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
@@ -4,10 +4,11 @@ CREATE TABLE invoice_items (
invoice_id char(36) NOT NULL,
subscription_id char(36) NOT NULL,
start_date datetime NOT NULL,
- end_date datetime NOT NULL,
+ end_date datetime NULL,
description varchar(100) NOT NULL,
- amount numeric(10,4) NOT NULL,
- rate numeric(10,4) NOT NULL,
+ recurring_amount numeric(10,4) NOT NULL,
+ recurring_rate numeric(10,4) NOT NULL,
+ fixed_amount numeric(10,4) NOT NULL,
currency char(3) NOT NULL,
PRIMARY KEY(id)
) ENGINE=innodb;
@@ -45,6 +46,6 @@ GROUP BY invoice_id;
DROP VIEW IF EXISTS invoice_item_summary;
CREATE VIEW invoice_item_summary AS
-select invoice_id, sum(amount) AS total_amount
+select invoice_id, sum(recurring_amount) + SUM(fixed_amount) AS total_amount
from invoice_items
group by invoice_id;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
index 66ad993..b63c230 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
@@ -23,14 +23,10 @@ import com.ning.billing.catalog.MockPlanPhase;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.entitlement.api.billing.BillingEvent;
import com.ning.billing.entitlement.api.billing.BillingModeType;
import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionTransition;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.api.InvoicePayment;
@@ -87,7 +83,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
UUID subscriptionId = UUID.randomUUID();
DateTime startDate = new DateTime(2010, 1, 1, 0, 0, 0, 0);
DateTime endDate = new DateTime(2010, 4, 1, 0, 0, 0, 0);
- InvoiceItem invoiceItem = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", new BigDecimal("21.00"), new BigDecimal("7.00"), Currency.USD);
+ InvoiceItem invoiceItem = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", new BigDecimal("21.00"), new BigDecimal("7.00"), null, Currency.USD);
invoice.addInvoiceItem(invoiceItem);
invoiceDao.create(invoice);
@@ -184,7 +180,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate = new BigDecimal("9.0");
BigDecimal amount = rate.multiply(new BigDecimal("3.0"));
- DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, targetDate, endDate, "test", amount, rate, Currency.USD);
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, targetDate, endDate, "test", amount, rate, null, Currency.USD);
invoice.addInvoiceItem(item);
invoiceDao.create(invoice);
@@ -279,16 +275,16 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
DateTime endDate = startDate.plusMonths(1);
- DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoiceId1, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
+ DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoiceId1, subscriptionId1, startDate, endDate, "test A", rate1, rate1, null, Currency.USD);
invoiceItemDao.create(item1);
- DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoiceId1, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
+ DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoiceId1, subscriptionId2, startDate, endDate, "test B", rate2, rate2, null, Currency.USD);
invoiceItemDao.create(item2);
- DefaultInvoiceItem item3 = new DefaultInvoiceItem(invoiceId1, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
+ DefaultInvoiceItem item3 = new DefaultInvoiceItem(invoiceId1, subscriptionId3, startDate, endDate, "test C", rate3, rate3, null, Currency.USD);
invoiceItemDao.create(item3);
- DefaultInvoiceItem item4 = new DefaultInvoiceItem(invoiceId1, subscriptionId4, startDate, endDate, "test D", rate4, rate4, Currency.USD);
+ DefaultInvoiceItem item4 = new DefaultInvoiceItem(invoiceId1, subscriptionId4, startDate, endDate, "test D", rate4, rate4, null, Currency.USD);
invoiceItemDao.create(item4);
// create invoice 2 (subscriptions 1-3)
@@ -300,13 +296,13 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
startDate = endDate;
endDate = startDate.plusMonths(1);
- DefaultInvoiceItem item5 = new DefaultInvoiceItem(invoiceId2, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
+ DefaultInvoiceItem item5 = new DefaultInvoiceItem(invoiceId2, subscriptionId1, startDate, endDate, "test A", rate1, rate1, null, Currency.USD);
invoiceItemDao.create(item5);
- DefaultInvoiceItem item6 = new DefaultInvoiceItem(invoiceId2, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
+ DefaultInvoiceItem item6 = new DefaultInvoiceItem(invoiceId2, subscriptionId2, startDate, endDate, "test B", rate2, rate2, null, Currency.USD);
invoiceItemDao.create(item6);
- DefaultInvoiceItem item7 = new DefaultInvoiceItem(invoiceId2, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
+ DefaultInvoiceItem item7 = new DefaultInvoiceItem(invoiceId2, subscriptionId3, startDate, endDate, "test C", rate3, rate3, null, Currency.USD);
invoiceItemDao.create(item7);
// check that each subscription returns the correct number of invoices
@@ -365,10 +361,10 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate1 = new BigDecimal("17.0");
BigDecimal rate2 = new BigDecimal("42.0");
- DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, Currency.USD);
+ DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, null, Currency.USD);
invoiceItemDao.create(item1);
- DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, Currency.USD);
+ DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, null, Currency.USD);
invoiceItemDao.create(item2);
BigDecimal payment1 = new BigDecimal("48.0");
@@ -392,10 +388,10 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate1 = new BigDecimal("17.0");
BigDecimal rate2 = new BigDecimal("42.0");
- DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, Currency.USD);
+ DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, null, Currency.USD);
invoiceItemDao.create(item1);
- DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, Currency.USD);
+ DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, null, Currency.USD);
invoiceItemDao.create(item2);
BigDecimal balance = invoiceDao.getAccountBalance(accountId);
@@ -430,10 +426,10 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate1 = new BigDecimal("17.0");
BigDecimal rate2 = new BigDecimal("42.0");
- DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, Currency.USD);
+ DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, null, Currency.USD);
invoiceItemDao.create(item1);
- DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, Currency.USD);
+ DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, null, Currency.USD);
invoiceItemDao.create(item2);
DateTime upToDate;
@@ -456,7 +452,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate3 = new BigDecimal("21.0");
- DefaultInvoiceItem item3 = new DefaultInvoiceItem(invoice2.getId(), UUID.randomUUID(), startDate2, endDate2, "test C", rate3, rate3, Currency.USD);
+ DefaultInvoiceItem item3 = new DefaultInvoiceItem(invoice2.getId(), UUID.randomUUID(), startDate2, endDate2, "test C", rate3, rate3, null, Currency.USD);
invoiceItemDao.create(item3);
upToDate = new DateTime(2011, 1, 1, 0, 0, 0, 0);
@@ -558,98 +554,4 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, new DateTime(), Currency.USD);
assertNull(invoice);
}
-
- private class MockSubscription implements Subscription {
- private UUID subscriptionId = UUID.randomUUID();
-
- @Override
- public void cancel(DateTime requestedDate, boolean eot) throws EntitlementUserApiException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void uncancel() throws EntitlementUserApiException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void changePlan(String productName, BillingPeriod term, String planSet, DateTime requestedDate) throws EntitlementUserApiException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void pause() throws EntitlementUserApiException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void resume() throws EntitlementUserApiException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public UUID getId() {
- return subscriptionId;
- }
-
- @Override
- public UUID getBundleId() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SubscriptionState getState() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DateTime getStartDate() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DateTime getEndDate() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Plan getCurrentPlan() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getCurrentPriceList() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public PlanPhase getCurrentPhase() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DateTime getChargedThroughDate() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DateTime getPaidThroughDate() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public List<SubscriptionTransition> getActiveTransitions() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public List<SubscriptionTransition> getAllTransitions() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SubscriptionTransition getPendingTransition() {
- throw new UnsupportedOperationException();
- }
- }
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
index dc2afd8..92a90b3 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
@@ -45,7 +45,7 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
DateTime endDate = new DateTime(2011, 11, 1, 0, 0, 0, 0);
BigDecimal rate = new BigDecimal("20.00");
- InvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", rate, rate, Currency.USD);
+ InvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", rate, rate, rate, Currency.USD);
invoiceItemDao.create(item);
InvoiceItem thisItem = invoiceItemDao.getById(item.getId().toString());
@@ -56,8 +56,9 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
assertEquals(thisItem.getStartDate(), item.getStartDate());
assertEquals(thisItem.getEndDate(), item.getEndDate());
assertEquals(thisItem.getDescription(), item.getDescription());
- assertEquals(thisItem.getAmount().compareTo(item.getAmount()), 0);
- assertEquals(thisItem.getRate().compareTo(item.getRate()), 0);
+ assertEquals(thisItem.getRecurringAmount().compareTo(item.getRecurringAmount()), 0);
+ assertEquals(thisItem.getRecurringRate().compareTo(item.getRecurringRate()), 0);
+ assertEquals(thisItem.getFixedAmount().compareTo(item.getFixedAmount()), 0);
assertEquals(thisItem.getCurrency(), item.getCurrency());
}
@@ -69,7 +70,7 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
for (int i = 0; i < 3; i++) {
UUID invoiceId = UUID.randomUUID();
- DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate.plusMonths(i), startDate.plusMonths(i + 1), "test", rate, rate, Currency.USD);
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate.plusMonths(i), startDate.plusMonths(i + 1), "test", rate, rate, null, Currency.USD);
invoiceItemDao.create(item);
}
@@ -86,7 +87,7 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
for (int i = 0; i < 5; i++) {
UUID subscriptionId = UUID.randomUUID();
BigDecimal amount = rate.multiply(new BigDecimal(i + 1));
- DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", amount, amount, Currency.USD);
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", amount, amount, amount, Currency.USD);
invoiceItemDao.create(item);
}
@@ -107,7 +108,7 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
BigDecimal rate = new BigDecimal("20.00");
UUID subscriptionId = UUID.randomUUID();
- DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", rate, rate, Currency.USD);
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", rate, rate, rate, Currency.USD);
invoiceItemDao.create(item);
List<InvoiceItem> items = invoiceItemDao.getInvoiceItemsByAccount(accountId.toString());
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
new file mode 100644
index 0000000..005a605
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010-2011 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.invoice.dao;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+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.SubscriptionTransition;
+import org.joda.time.DateTime;
+
+import java.util.List;
+import java.util.UUID;
+
+public class MockSubscription implements Subscription {
+ private UUID subscriptionId = UUID.randomUUID();
+
+ @Override
+ public void cancel(DateTime requestedDate, boolean eot) throws EntitlementUserApiException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void uncancel() throws EntitlementUserApiException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void changePlan(String productName, BillingPeriod term, String planSet, DateTime requestedDate) throws EntitlementUserApiException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void pause() throws EntitlementUserApiException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void resume() throws EntitlementUserApiException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public UUID getId() {
+ return subscriptionId;
+ }
+
+ @Override
+ public UUID getBundleId() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SubscriptionState getState() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DateTime getStartDate() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DateTime getEndDate() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Plan getCurrentPlan() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getCurrentPriceList() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PlanPhase getCurrentPhase() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DateTime getChargedThroughDate() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DateTime getPaidThroughDate() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<SubscriptionTransition> getActiveTransitions() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<SubscriptionTransition> getAllTransitions() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SubscriptionTransition getPendingTransition() {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
index fb29cc6..1d0c358 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
@@ -18,6 +18,8 @@ package com.ning.billing.invoice.glue;
import java.io.IOException;
+import com.ning.billing.invoice.api.test.InvoiceTestApi;
+import com.ning.billing.invoice.api.test.DefaultInvoiceTestApi;
import com.ning.billing.invoice.dao.InvoicePaymentSqlDao;
import org.skife.jdbi.v2.IDBI;
import com.ning.billing.account.glue.AccountModule;
@@ -72,6 +74,8 @@ public class InvoiceModuleWithEmbeddedDb extends InvoiceModule {
super.configure();
+ bind(InvoiceTestApi.class).to(DefaultInvoiceTestApi.class).asEagerSingleton();
+
install(new BusModule());
}
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
index 11c3b1d..702801b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
@@ -16,9 +16,13 @@
package com.ning.billing.invoice.tests;
-import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.DefaultPrice;
+import com.ning.billing.catalog.MockInternationalPrice;
+import com.ning.billing.catalog.MockPlan;
+import com.ning.billing.catalog.MockPlanPhase;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.entitlement.api.billing.BillingEvent;
@@ -37,7 +41,9 @@ import com.ning.billing.invoice.model.InvoiceItemList;
import org.joda.time.DateTime;
import org.testng.annotations.Test;
+import javax.annotation.Nullable;
import java.math.BigDecimal;
+import java.util.List;
import java.util.UUID;
import static org.testng.Assert.assertEquals;
@@ -47,7 +53,6 @@ import static org.testng.Assert.assertNull;
@Test(groups = {"fast", "invoicing", "invoiceGenerator"})
public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
private final InvoiceGenerator generator = new DefaultInvoiceGenerator();
- private final MockCatalog catalog = new MockCatalog();
@Test
public void testWithNullEventSetAndNullInvoiceSet() {
@@ -74,14 +79,12 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
DateTime startDate = buildDateTime(2011, 9, 1);
- MockCatalog catalog = new MockCatalog();
- Plan plan = catalog.getCurrentPlans()[0];
- PlanPhase phase = plan.getAllPhases()[0];
+
+ Plan plan = new MockPlan();
+ BigDecimal rate1 = TEN;
+ PlanPhase phase = createMockMonthlyPlanPhase(rate1);
- BillingEvent event = new DefaultBillingEvent(sub, startDate, plan, phase,
- new InternationalPriceMock(ZERO),
- new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE, "Test");
+ BillingEvent event = createBillingEvent(sub.getId(), startDate, plan, phase, 1);
events.add(event);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -102,14 +105,11 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
DateTime startDate = buildDateTime(2011, 9, 1);
- MockCatalog catalog = new MockCatalog();
- Plan plan = catalog.getCurrentPlans()[0];
- PlanPhase phase = plan.getAllPhases()[0];
+
+ Plan plan = new MockPlan();
BigDecimal rate = TEN;
- BillingEvent event = new DefaultBillingEvent(sub, startDate, plan, phase,
- new InternationalPriceMock(ZERO),
- new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
- 15, BillingModeType.IN_ADVANCE,"Test");
+ PlanPhase phase = createMockMonthlyPlanPhase(rate);
+ BillingEvent event = createBillingEvent(sub.getId(), startDate, plan, phase, 15);
events.add(event);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -131,23 +131,20 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
public void testTwoMonthlySubscriptionsWithAlignedBillingDates() {
BillingEventSet events = new BillingEventSet();
- Plan plan1 = catalog.getCurrentPlans()[0];
- PlanPhase phase1 = plan1.getAllPhases()[0];
- Plan plan2 = catalog.getCurrentPlans()[1];
- PlanPhase phase2 = plan2.getAllPhases()[0];
+ Plan plan1 = new MockPlan();
+ BigDecimal rate1 = FIVE;
+ PlanPhase phase1 = createMockMonthlyPlanPhase(rate1);
+
+ Plan plan2 = new MockPlan();
+ BigDecimal rate2 = TEN;
+ PlanPhase phase2 = createMockMonthlyPlanPhase(rate2);
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
- BillingEvent event1 = new DefaultBillingEvent(sub, buildDateTime(2011, 9, 1), plan1, phase1,
- new InternationalPriceMock(ZERO),
- new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE, "Test");
+ BillingEvent event1 = createBillingEvent(sub.getId(), buildDateTime(2011, 9, 1), plan1, phase1, 1);
events.add(event1);
- BillingEvent event2 = new DefaultBillingEvent(sub, buildDateTime(2011, 10, 1), plan2, phase2,
- new InternationalPriceMock(ZERO),
- new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE, "Test");
+ BillingEvent event2 = createBillingEvent(sub.getId(), buildDateTime(2011, 10, 1), plan2, phase2, 1);
events.add(event2);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -157,29 +154,25 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
assertNotNull(invoice);
assertEquals(invoice.getNumberOfItems(), 2);
- assertEquals(invoice.getTotalAmount(), FIVE.add(TEN).setScale(NUMBER_OF_DECIMALS));
+ assertEquals(invoice.getTotalAmount(), rate1.add(rate2).setScale(NUMBER_OF_DECIMALS));
}
@Test
public void testOnePlan_TwoMonthlyPhases_ChangeImmediate() {
BillingEventSet events = new BillingEventSet();
- MockCatalog catalog = new MockCatalog();
- Plan plan1 = catalog.getCurrentPlans()[0];
- PlanPhase phase1 = plan1.getAllPhases()[0];
+ Plan plan1 = new MockPlan();
+ BigDecimal rate1 = FIVE;
+ PlanPhase phase1 = createMockMonthlyPlanPhase(rate1);
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
- BillingEvent event1 = new DefaultBillingEvent(sub, buildDateTime(2011, 9, 1),
- plan1,phase1,
- new InternationalPriceMock(ZERO),new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE,"Test");
+ BillingEvent event1 = createBillingEvent(sub.getId(), buildDateTime(2011, 9, 1), plan1,phase1, 1);
events.add(event1);
- BillingEvent event2 = new DefaultBillingEvent(sub, buildDateTime(2011, 10, 15),
- plan1,phase1, //technically should be a different phase but it doesn't impact the test
- new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 15, BillingModeType.IN_ADVANCE,"Test");
+ BigDecimal rate2 = TEN;
+ PlanPhase phase2 = createMockMonthlyPlanPhase(rate2);
+ BillingEvent event2 = createBillingEvent(sub.getId(), buildDateTime(2011, 10, 15), plan1, phase2, 15);
events.add(event2);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -196,8 +189,8 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BigDecimal numberOfCyclesEvent2 = TWO;
BigDecimal expectedValue;
- expectedValue = numberOfCyclesEvent1.multiply(FIVE);
- expectedValue = expectedValue.add(numberOfCyclesEvent2.multiply(TEN));
+ expectedValue = numberOfCyclesEvent1.multiply(rate1);
+ expectedValue = expectedValue.add(numberOfCyclesEvent2.multiply(rate2));
expectedValue = expectedValue.setScale(NUMBER_OF_DECIMALS);
assertEquals(invoice.getTotalAmount(), expectedValue);
@@ -207,28 +200,22 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
public void testOnePlan_ThreeMonthlyPhases_ChangeEOT() {
BillingEventSet events = new BillingEventSet();
- MockCatalog catalog = new MockCatalog();
- Plan plan1 = catalog.getCurrentPlans()[0];
- PlanPhase phase1 = plan1.getAllPhases()[0];
-
+ Plan plan1 = new MockPlan();
+ BigDecimal rate1 = FIVE;
+ PlanPhase phase1 = createMockMonthlyPlanPhase(rate1);
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
- BillingEvent event1 = new DefaultBillingEvent(sub, buildDateTime(2011, 9, 1),
- plan1,phase1,
- new InternationalPriceMock(ZERO),new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE,"Test");
+ BillingEvent event1 = createBillingEvent(sub.getId(), buildDateTime(2011, 9, 1), plan1, phase1, 1);
events.add(event1);
- BillingEvent event2 = new DefaultBillingEvent(sub, buildDateTime(2011, 10, 1),
- plan1,phase1, //technically should be a different phase but it doesn't impact the test
- new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE,"Test");
+ BigDecimal rate2 = TEN;
+ PlanPhase phase2 = createMockMonthlyPlanPhase(rate2);
+ BillingEvent event2 = createBillingEvent(sub.getId(), buildDateTime(2011, 10, 1), plan1, phase2, 1);
events.add(event2);
- BillingEvent event3 = new DefaultBillingEvent(sub, buildDateTime(2011, 11, 1),
- plan1,phase1, //technically should be a different phase but it doesn't impact the test
- new InternationalPriceMock(ZERO),new InternationalPriceMock(THIRTY), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE,"Test");
+ BigDecimal rate3 = THIRTY;
+ PlanPhase phase3 = createMockMonthlyPlanPhase(rate3);
+ BillingEvent event3 = createBillingEvent(sub.getId(), buildDateTime(2011, 11, 1), plan1, phase3, 1);
events.add(event3);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -238,7 +225,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
assertNotNull(invoice);
assertEquals(invoice.getNumberOfItems(), 3);
- assertEquals(invoice.getTotalAmount(), FIVE.add(TEN).add(TWO.multiply(THIRTY)).setScale(NUMBER_OF_DECIMALS));
+ assertEquals(invoice.getTotalAmount(), rate1.add(rate2).add(TWO.multiply(rate3)).setScale(NUMBER_OF_DECIMALS));
}
@Test
@@ -247,30 +234,24 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
DateTime startDate = buildDateTime(2011, 9, 1);
-
- MockCatalog catalog = new MockCatalog();
- Plan plan1 = catalog.getCurrentPlans()[0];
- PlanPhase phase1 = plan1.getAllPhases()[0];
-
+
+ Plan plan1 = new MockPlan();
BigDecimal rate = FIVE;
- BillingEvent event1 = new DefaultBillingEvent(sub, startDate,
- plan1,phase1,
- new InternationalPriceMock(ZERO),new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
- 1, BillingModeType.IN_ADVANCE,"Test");
+ PlanPhase phase1 = createMockMonthlyPlanPhase(rate);
+
+ BillingEvent event1 = createBillingEvent(sub.getId(), startDate, plan1, phase1, 1);
events.add(event1);
+ DateTime targetDate = buildDateTime(2011, 12, 1);
+ UUID accountId = UUID.randomUUID();
+ Invoice invoice1 = generator.generateInvoice(accountId, events, null, targetDate, Currency.USD);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
- InvoiceItem invoiceItem = new DefaultInvoiceItem(UUID.randomUUID(), sub.getId(), startDate, buildDateTime(2012, 1, 1), "",
- rate.multiply(FOUR), rate, Currency.USD);
- existingInvoiceItems.add(invoiceItem);
+ existingInvoiceItems.addAll(invoice1.getInvoiceItems());
- DateTime targetDate = buildDateTime(2011, 12, 3);
- UUID accountId = UUID.randomUUID();
- Invoice invoice = generator.generateInvoice(accountId, events, existingInvoiceItems, targetDate, Currency.USD);
+ targetDate = buildDateTime(2011, 12, 3);
+ Invoice invoice2 = generator.generateInvoice(accountId, events, existingInvoiceItems, targetDate, Currency.USD);
- assertNotNull(invoice);
- assertEquals(invoice.getNumberOfItems(), 0);
- assertEquals(invoice.getTotalAmount(), ZERO);
+ assertNull(invoice2);
}
@Test
@@ -282,37 +263,44 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
// plan 5: addon to plan 2, with bill cycle alignment to plan; immediate cancellation
UUID subscriptionId1 = UUID.randomUUID();
- Plan plan1 = catalog.getCurrentPlans()[0];
- PlanPhase plan1Phase1 = plan1.getAllPhases()[0]; PlanPhase plan1Phase2 = plan1.getAllPhases()[0]; PlanPhase plan1Phase3 = plan1.getAllPhases()[0];
+ UUID subscriptionId2 = UUID.randomUUID();
+ UUID subscriptionId3 = UUID.randomUUID();
+ UUID subscriptionId4 = UUID.randomUUID();
+ UUID subscriptionId5 = UUID.randomUUID();
+
+ Plan plan1 = new MockPlan("Change from trial to discount with immediate cancellation");
+ PlanPhase plan1Phase1 = createMockMonthlyPlanPhase(EIGHT, PhaseType.TRIAL);
+ PlanPhase plan1Phase2 = createMockMonthlyPlanPhase(TWELVE, PhaseType.DISCOUNT);
+ PlanPhase plan1Phase3 = createMockMonthlyPlanPhase();
DateTime plan1StartDate = buildDateTime(2011, 1, 5);
DateTime plan1PhaseChangeDate = buildDateTime(2011, 4, 5);
DateTime plan1CancelDate = buildDateTime(2011, 4, 29);
- UUID subscriptionId2 = UUID.randomUUID();
- Plan plan2 = catalog.getCurrentPlans()[1];
- PlanPhase plan2Phase1 = plan2.getAllPhases()[0]; PlanPhase plan2Phase2 = plan2.getAllPhases()[0]; PlanPhase plan2Phase3 = plan2.getAllPhases()[0];
+ Plan plan2 = new MockPlan("Change phase from trial to discount to evergreen");
+ PlanPhase plan2Phase1 = createMockMonthlyPlanPhase(TWENTY, PhaseType.TRIAL);
+ PlanPhase plan2Phase2 = createMockMonthlyPlanPhase(THIRTY, PhaseType.DISCOUNT);
+ PlanPhase plan2Phase3 = createMockMonthlyPlanPhase(FORTY, PhaseType.EVERGREEN);
DateTime plan2StartDate = buildDateTime(2011, 3, 10);
DateTime plan2PhaseChangeToDiscountDate = buildDateTime(2011, 6, 10);
DateTime plan2PhaseChangeToEvergreenDate = buildDateTime(2011, 9, 10);
- UUID subscriptionId3 = UUID.randomUUID();
- Plan plan3 = catalog.getCurrentPlans()[2];
- PlanPhase plan3Phase1 = plan3.getAllPhases()[0]; PlanPhase plan3Phase2 = plan3.getAllPhases()[0];
+ Plan plan3 = new MockPlan("Upgrade with immediate change, BCD = 31");
+ PlanPhase plan3Phase1 = createMockMonthlyPlanPhase(TEN, PhaseType.EVERGREEN);
+ PlanPhase plan3Phase2 = createMockAnnualPlanPhase(ONE_HUNDRED, PhaseType.EVERGREEN);
DateTime plan3StartDate = buildDateTime(2011, 5, 20);
DateTime plan3UpgradeToAnnualDate = buildDateTime(2011, 7, 31);
- UUID subscriptionId4 = UUID.randomUUID();
- Plan plan4a = catalog.getCurrentPlans()[0];
- Plan plan4b = catalog.getCurrentPlans()[1];
- PlanPhase plan4aPhase1 = plan4a.getAllPhases()[0];
- PlanPhase plan4bPhase1 = plan4b.getAllPhases()[0];
+ Plan plan4a = new MockPlan("Plan change effective EOT; plan 1");
+ Plan plan4b = new MockPlan("Plan change effective EOT; plan 2");
+ PlanPhase plan4aPhase1 = createMockMonthlyPlanPhase(FIFTEEN);
+ PlanPhase plan4bPhase1 = createMockMonthlyPlanPhase(TWENTY_FOUR);
DateTime plan4StartDate = buildDateTime(2011, 6, 7);
DateTime plan4ChangeOfPlanDate = buildDateTime(2011, 8, 7);
- UUID subscriptionId5 = UUID.randomUUID();
- Plan plan5 = catalog.getCurrentPlans()[2];
- PlanPhase plan5Phase1 = plan5.getAllPhases()[0]; PlanPhase plan5Phase2 = plan5.getAllPhases()[0];
+ Plan plan5 = new MockPlan("Add-on");
+ PlanPhase plan5Phase1 = createMockMonthlyPlanPhase(TWENTY);
+ PlanPhase plan5Phase2 = createMockMonthlyPlanPhase();
DateTime plan5StartDate = buildDateTime(2011, 6, 21);
DateTime plan5CancelDate = buildDateTime(2011, 10, 7);
@@ -321,7 +309,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BillingEventSet events = new BillingEventSet();
// on 1/5/2011, create subscription 1 (trial)
- events.add(createBillingEvent(subscriptionId1, plan1StartDate, plan1, plan1Phase1, EIGHT, 5));
+ events.add(createBillingEvent(subscriptionId1, plan1StartDate, plan1, plan1Phase1, 5));
expectedAmount = EIGHT;
testInvoiceGeneration(events, invoiceItems, plan1StartDate, 1, expectedAmount);
@@ -334,12 +322,12 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
testInvoiceGeneration(events, invoiceItems, buildDateTime(2011, 3, 5), 1, expectedAmount);
// on 3/10/2011, create subscription 2 (trial)
- events.add(createBillingEvent(subscriptionId2, plan2StartDate, plan2, plan2Phase1, TWENTY, 10));
+ events.add(createBillingEvent(subscriptionId2, plan2StartDate, plan2, plan2Phase1, 10));
expectedAmount = TWENTY;
testInvoiceGeneration(events, invoiceItems, plan2StartDate, 1, expectedAmount);
// on 4/5/2011, invoice subscription 1 (discount)
- events.add(createBillingEvent(subscriptionId1, plan1PhaseChangeDate, plan1, plan1Phase2, TWELVE, 5));
+ events.add(createBillingEvent(subscriptionId1, plan1PhaseChangeDate, plan1, plan1Phase2, 5));
expectedAmount = TWELVE;
testInvoiceGeneration(events, invoiceItems, plan1PhaseChangeDate, 1, expectedAmount);
@@ -348,7 +336,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
testInvoiceGeneration(events, invoiceItems, buildDateTime(2011, 4, 10), 1, expectedAmount);
// on 4/29/2011, cancel subscription 1
- events.add(createBillingEvent(subscriptionId1, plan1CancelDate, plan1, plan1Phase3, ZERO, 5));
+ events.add(createBillingEvent(subscriptionId1, plan1CancelDate, plan1, plan1Phase3, 5));
expectedAmount = TWELVE.multiply(SIX.divide(THIRTY, NUMBER_OF_DECIMALS, ROUNDING_METHOD)).negate().setScale(NUMBER_OF_DECIMALS);
testInvoiceGeneration(events, invoiceItems, plan1CancelDate, 2, expectedAmount);
@@ -357,17 +345,17 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
testInvoiceGeneration(events, invoiceItems, buildDateTime(2011, 5, 10), 1, expectedAmount);
// on 5/20/2011, create subscription 3 (monthly)
- events.add(createBillingEvent(subscriptionId3, plan3StartDate, plan3, plan3Phase1, TEN, 20));
+ events.add(createBillingEvent(subscriptionId3, plan3StartDate, plan3, plan3Phase1, 20));
expectedAmount = TEN;
testInvoiceGeneration(events, invoiceItems, plan3StartDate, 1, expectedAmount);
// on 6/7/2011, create subscription 4
- events.add(createBillingEvent(subscriptionId4, plan4StartDate, plan4a, plan4aPhase1, FIFTEEN, 7));
+ events.add(createBillingEvent(subscriptionId4, plan4StartDate, plan4a, plan4aPhase1, 7));
expectedAmount = FIFTEEN;
testInvoiceGeneration(events, invoiceItems, plan4StartDate, 1, expectedAmount);
// on 6/10/2011, invoice subscription 2 (discount)
- events.add(createBillingEvent(subscriptionId2, plan2PhaseChangeToDiscountDate, plan2, plan2Phase2, THIRTY, 10));
+ events.add(createBillingEvent(subscriptionId2, plan2PhaseChangeToDiscountDate, plan2, plan2Phase2, 10));
expectedAmount = THIRTY;
testInvoiceGeneration(events, invoiceItems, plan2PhaseChangeToDiscountDate, 1, expectedAmount);
@@ -376,7 +364,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
testInvoiceGeneration(events, invoiceItems, buildDateTime(2011, 6, 20), 1, expectedAmount);
// on 6/21/2011, create add-on (subscription 5)
- events.add(createBillingEvent(subscriptionId5, plan5StartDate, plan5, plan5Phase1, TWENTY, 10));
+ events.add(createBillingEvent(subscriptionId5, plan5StartDate, plan5, plan5Phase1, 10));
expectedAmount = TWENTY.multiply(NINETEEN.divide(THIRTY, NUMBER_OF_DECIMALS, ROUNDING_METHOD)).setScale(NUMBER_OF_DECIMALS);
testInvoiceGeneration(events, invoiceItems, plan5StartDate, 1, expectedAmount);
@@ -393,14 +381,14 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
testInvoiceGeneration(events, invoiceItems, buildDateTime(2011, 7, 20), 1, expectedAmount);
// on 7/31/2011, convert subscription 3 to annual
- events.add(createAnnualBillingEvent(subscriptionId3, plan3UpgradeToAnnualDate, plan3, plan3Phase2, ONE_HUNDRED, 31));
+ events.add(createBillingEvent(subscriptionId3, plan3UpgradeToAnnualDate, plan3, plan3Phase2, 31));
expectedAmount = ONE_HUNDRED.subtract(TEN);
expectedAmount = expectedAmount.add(TEN.multiply(ELEVEN.divide(THIRTY_ONE, NUMBER_OF_DECIMALS, ROUNDING_METHOD)));
expectedAmount = expectedAmount.setScale(NUMBER_OF_DECIMALS);
testInvoiceGeneration(events, invoiceItems, plan3UpgradeToAnnualDate, 3, expectedAmount);
// on 8/7/2011, invoice subscription 4 (plan 2)
- events.add(createBillingEvent(subscriptionId4, plan4ChangeOfPlanDate, plan4b, plan4bPhase1, TWENTY_FOUR, 7));
+ events.add(createBillingEvent(subscriptionId4, plan4ChangeOfPlanDate, plan4b, plan4bPhase1, 7));
expectedAmount = TWENTY_FOUR;
testInvoiceGeneration(events, invoiceItems, plan4ChangeOfPlanDate, 1, expectedAmount);
@@ -413,12 +401,12 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
testInvoiceGeneration(events, invoiceItems, buildDateTime(2011, 9, 7), 1, expectedAmount);
// on 9/10/2011, invoice plan 2 (evergreen), invoice subscription 5
- events.add(createBillingEvent(subscriptionId2, plan2PhaseChangeToEvergreenDate, plan2, plan2Phase3, FORTY, 10));
+ events.add(createBillingEvent(subscriptionId2, plan2PhaseChangeToEvergreenDate, plan2, plan2Phase3, 10));
expectedAmount = FORTY.add(TWENTY);
testInvoiceGeneration(events, invoiceItems, plan2PhaseChangeToEvergreenDate, 2, expectedAmount);
// on 10/7/2011, invoice subscription 4 (plan 2), cancel subscription 5
- events.add(createBillingEvent(subscriptionId5, plan5CancelDate, plan5, plan5Phase2, ZERO, 10));
+ events.add(createBillingEvent(subscriptionId5, plan5CancelDate, plan5, plan5Phase2, 10));
expectedAmount = TWENTY_FOUR.add(TWENTY.multiply(THREE.divide(THIRTY)).negate().setScale(NUMBER_OF_DECIMALS));
testInvoiceGeneration(events, invoiceItems, plan5CancelDate, 3, expectedAmount);
@@ -427,24 +415,32 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
testInvoiceGeneration(events, invoiceItems, buildDateTime(2011, 10, 10), 1, expectedAmount);
}
- private DefaultBillingEvent createBillingEvent(final UUID subscriptionId, final DateTime startDate,
- final Plan plan, final PlanPhase planPhase,
- final BigDecimal rate, final int billCycleDay) {
- Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(subscriptionId));
+ private MockPlanPhase createMockMonthlyPlanPhase() {
+ return new MockPlanPhase(null, null, BillingPeriod.MONTHLY);
+ }
- return new DefaultBillingEvent(sub, startDate, plan, planPhase,
- new InternationalPriceMock(ZERO),
- new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
- billCycleDay, BillingModeType.IN_ADVANCE,"Test");
+ private MockPlanPhase createMockMonthlyPlanPhase(@Nullable final BigDecimal recurringRate) {
+ return new MockPlanPhase(new MockInternationalPrice(new DefaultPrice(recurringRate, Currency.USD)),
+ null, BillingPeriod.MONTHLY);
+ }
+
+ private MockPlanPhase createMockMonthlyPlanPhase(final BigDecimal recurringRate, final PhaseType phaseType) {
+ return new MockPlanPhase(new MockInternationalPrice(new DefaultPrice(recurringRate, Currency.USD)),
+ null, BillingPeriod.MONTHLY, phaseType);
}
- private DefaultBillingEvent createAnnualBillingEvent(final UUID subscriptionId, final DateTime startDate,
- final Plan plan, final PlanPhase planPhase,
- final BigDecimal rate, final int billCycleDay) {
+ private MockPlanPhase createMockAnnualPlanPhase(final BigDecimal recurringRate, final PhaseType phaseType) {
+ return new MockPlanPhase(new MockInternationalPrice(new DefaultPrice(recurringRate, Currency.USD)),
+ null, BillingPeriod.ANNUAL, phaseType);
+ }
+
+ private DefaultBillingEvent createBillingEvent(final UUID subscriptionId, final DateTime startDate,
+ final Plan plan, final PlanPhase planPhase, final int billCycleDay) {
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(subscriptionId));
+
return new DefaultBillingEvent(sub, startDate, plan, planPhase,
- new InternationalPriceMock(ZERO),
- new InternationalPriceMock(rate), BillingPeriod.ANNUAL,
+ planPhase.getFixedPrice(),
+ planPhase.getRecurringPrice(), planPhase.getBillingPeriod(),
billCycleDay, BillingModeType.IN_ADVANCE,"Test");
}
payment/pom.xml 2(+1 -1)
diff --git a/payment/pom.xml b/payment/pom.xml
index 17acd85..3e050f0 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
index 5e3f076..22d3c50 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
@@ -74,6 +74,7 @@ public abstract class TestPaymentApi {
"Test",
amount,
new BigDecimal("1.0"),
+ null,
Currency.USD));
List<Either<PaymentError, PaymentInfo>> results = paymentApi.createPayment(account.getExternalKey(), Arrays.asList(invoice.getId().toString()));
diff --git a/payment/src/test/java/com/ning/billing/payment/TestHelper.java b/payment/src/test/java/com/ning/billing/payment/TestHelper.java
index c690352..b4df1ba 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestHelper.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestHelper.java
@@ -71,8 +71,9 @@ public class TestHelper {
item.getStartDate(),
item.getEndDate(),
item.getDescription(),
- item.getAmount(),
- item.getRate(),
+ item.getRecurringAmount(),
+ item.getRecurringRate(),
+ item.getFixedAmount(),
item.getCurrency()));
}
invoiceDao.create(invoice);
@@ -83,7 +84,7 @@ public class TestHelper {
final DateTime now = new DateTime(DateTimeZone.UTC);
final UUID subscriptionId = UUID.randomUUID();
final BigDecimal amount = new BigDecimal("10.00");
- final InvoiceItem item = new DefaultInvoiceItem(null, subscriptionId, now, now.plusMonths(1), "Test", amount, new BigDecimal("1.0"), Currency.USD);
+ final InvoiceItem item = new DefaultInvoiceItem(null, subscriptionId, now, now.plusMonths(1), "Test", amount, new BigDecimal("1.0"), null, Currency.USD);
return createTestInvoice(account, now, Currency.USD, item);
}
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 7aa42a0..5ec08b5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
<packaging>pom</packaging>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<name>killbill</name>
<description>Library for managing recurring subscriptions and the associated billing</description>
<url>http://github.com/ning/killbill</url>
util/pom.xml 2(+1 -1)
diff --git a/util/pom.xml b/util/pom.xml
index 8013122..b16ecfa 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.1.4-SNAPSHOT</version>
+ <version>0.1.5-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>