killbill-memoizeit
Changes
account/pom.xml 2(+1 -1)
analytics/pom.xml 11(+8 -3)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java 4(+4 -0)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.java 2(+1 -1)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDaoProvider.java 38(+38 -0)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java 40(+21 -19)
analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg 8(+7 -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/engine/core/ApiEventProcessorBase.java 23(+22 -1)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java 31(+12 -19)
entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java 6(+5 -1)
invoice/pom.xml 2(+1 -1)
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 0ac8223..f92d35b 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
analytics/pom.xml 11(+8 -3)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index e747b12..cb22965 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-analytics</artifactId>
@@ -21,8 +21,9 @@
<packaging>jar</packaging>
<dependencies>
<dependency>
- <groupId>org.jdbi</groupId>
- <artifactId>jdbi</artifactId>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
@@ -63,6 +64,10 @@
<scope>runtime</scope>
</dependency>
<dependency>
+ <groupId>org.jdbi</groupId>
+ <artifactId>jdbi</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
diff --git a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
index a80d32b..25cef98 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
@@ -19,7 +19,7 @@ package com.ning.billing.analytics;
import com.google.inject.Inject;
import com.ning.billing.account.api.IAccount;
import com.ning.billing.account.api.IAccountUserApi;
-import com.ning.billing.analytics.dao.EventDao;
+import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDao;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.entitlement.api.user.IEntitlementUserApi;
import com.ning.billing.entitlement.api.user.ISubscriptionBundle;
@@ -34,52 +34,56 @@ import java.util.List;
public class AnalyticsListener /* implements IApiListener */
{
private static final Logger log = LoggerFactory.getLogger(AnalyticsListener.class);
- private final EventDao dao;
+
+ private final BusinessSubscriptionTransitionDao dao;
private final IEntitlementUserApi entitlementApi;
private final IAccountUserApi accountApi;
- public AnalyticsListener(final EventDao dao, final IEntitlementUserApi entitlementApi, final IAccountUserApi accountApi)
+ @Inject
+ public AnalyticsListener(final BusinessSubscriptionTransitionDao dao, final IEntitlementUserApi entitlementApi, final IAccountUserApi accountApi)
{
this.dao = dao;
this.entitlementApi = entitlementApi;
this.accountApi = accountApi;
}
-
- public void subscriptionCreated(ISubscriptionTransition created)
+ @Override
+ public void subscriptionCreated(final ISubscriptionTransition created)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCreated(created.getNextPlan());
recordTransition(event, created);
}
-
- public void subscriptionCancelled(ISubscriptionTransition cancelled)
+ @Override
+ public void subscriptionCancelled(final ISubscriptionTransition cancelled)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(cancelled.getNextPlan());
recordTransition(event, cancelled);
}
-
- public void subscriptionChanged(ISubscriptionTransition changed)
+ @Override
+ public void subscriptionChanged(final ISubscriptionTransition changed)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionChanged(changed.getNextPlan());
recordTransition(event, changed);
}
-
- public void subscriptionPaused(ISubscriptionTransition paused)
+ @Override
+ public void subscriptionPaused(final ISubscriptionTransition paused)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionPaused(paused.getNextPlan());
recordTransition(event, paused);
}
- public void subscriptionResumed(ISubscriptionTransition resumed)
+ @Override
+ public void subscriptionResumed(final ISubscriptionTransition resumed)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionResumed(resumed.getNextPlan());
recordTransition(event, resumed);
}
- public void subscriptionPhaseChanged(ISubscriptionTransition phaseChanged)
+ @Override
+ public void subscriptionPhaseChanged(final ISubscriptionTransition phaseChanged)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionPhaseChanged(phaseChanged.getNextPlan(), phaseChanged.getNextState());
recordTransition(event, phaseChanged);
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccount.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccount.java
new file mode 100644
index 0000000..aaf75a1
--- /dev/null
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccount.java
@@ -0,0 +1,254 @@
+/*
+ * 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.analytics;
+
+import com.ning.billing.analytics.utils.Rounder;
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+public class BusinessAccount
+{
+ // Populated by the database
+ private DateTime createdDt = null;
+ private DateTime updatedDt = null;
+
+ private final String key;
+ private BigDecimal balance;
+ private List<String> tags;
+ private DateTime lastInvoiceDate;
+ private BigDecimal totalInvoiceBalance;
+ private String lastPaymentStatus;
+ private String paymentMethod;
+ private String creditCardType;
+ private String billingAddressCountry;
+
+ public BusinessAccount(final String key, final BigDecimal balance, final List<String> tags, final DateTime lastInvoiceDate, final BigDecimal totalInvoiceBalance, final String lastPaymentStatus, final String paymentMethod, final String creditCardType, final String billingAddressCountry)
+ {
+ this.key = key;
+ this.balance = balance;
+ this.billingAddressCountry = billingAddressCountry;
+ this.creditCardType = creditCardType;
+ this.lastInvoiceDate = lastInvoiceDate;
+ this.lastPaymentStatus = lastPaymentStatus;
+ this.paymentMethod = paymentMethod;
+ this.tags = tags;
+ this.totalInvoiceBalance = totalInvoiceBalance;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public BigDecimal getBalance()
+ {
+ return balance;
+ }
+
+ public Double getRoundedBalance()
+ {
+ return Rounder.round(balance);
+ }
+
+ public void setBalance(final BigDecimal balance)
+ {
+ this.balance = balance;
+ }
+
+ public String getBillingAddressCountry()
+ {
+ return billingAddressCountry;
+ }
+
+ public void setBillingAddressCountry(final String billingAddressCountry)
+ {
+ this.billingAddressCountry = billingAddressCountry;
+ }
+
+ public DateTime getCreatedDt()
+ {
+ return createdDt;
+ }
+
+ public void setCreatedDt(final DateTime createdDt)
+ {
+ this.createdDt = createdDt;
+ }
+
+ public String getCreditCardType()
+ {
+ return creditCardType;
+ }
+
+ public void setCreditCardType(final String creditCardType)
+ {
+ this.creditCardType = creditCardType;
+ }
+
+ public DateTime getLastInvoiceDate()
+ {
+ return lastInvoiceDate;
+ }
+
+ public void setLastInvoiceDate(final DateTime lastInvoiceDate)
+ {
+ this.lastInvoiceDate = lastInvoiceDate;
+ }
+
+ public String getLastPaymentStatus()
+ {
+ return lastPaymentStatus;
+ }
+
+ public void setLastPaymentStatus(final String lastPaymentStatus)
+ {
+ this.lastPaymentStatus = lastPaymentStatus;
+ }
+
+ public String getPaymentMethod()
+ {
+ return paymentMethod;
+ }
+
+ public void setPaymentMethod(final String paymentMethod)
+ {
+ this.paymentMethod = paymentMethod;
+ }
+
+ public List<String> getTags()
+ {
+ return tags;
+ }
+
+ public void setTags(final List<String> tags)
+ {
+ this.tags = tags;
+ }
+
+ public BigDecimal getTotalInvoiceBalance()
+ {
+ return totalInvoiceBalance;
+ }
+
+ public Double getRoundedTotalInvoiceBalance()
+ {
+ return Rounder.round(totalInvoiceBalance);
+ }
+
+ public void setTotalInvoiceBalance(final BigDecimal totalInvoiceBalance)
+ {
+ this.totalInvoiceBalance = totalInvoiceBalance;
+ }
+
+ public DateTime getUpdatedDt()
+ {
+ return updatedDt;
+ }
+
+ public void setUpdatedDt(final DateTime updatedDt)
+ {
+ this.updatedDt = updatedDt;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BusinessAccount");
+ sb.append("{balance=").append(balance);
+ sb.append(", createdDt=").append(createdDt);
+ sb.append(", updatedDt=").append(updatedDt);
+ sb.append(", key='").append(key).append('\'');
+ sb.append(", tags=").append(tags);
+ sb.append(", lastInvoiceDate=").append(lastInvoiceDate);
+ sb.append(", totalInvoiceBalance=").append(totalInvoiceBalance);
+ sb.append(", lastPaymentStatus='").append(lastPaymentStatus).append('\'');
+ sb.append(", paymentMethod='").append(paymentMethod).append('\'');
+ sb.append(", creditCardType='").append(creditCardType).append('\'');
+ sb.append(", billingAddressCountry='").append(billingAddressCountry).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o)
+ {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final BusinessAccount that = (BusinessAccount) o;
+
+ if (balance != null ? !(Rounder.round(balance) == Rounder.round(that.balance)) : that.balance != null) {
+ return false;
+ }
+ if (billingAddressCountry != null ? !billingAddressCountry.equals(that.billingAddressCountry) : that.billingAddressCountry != null) {
+ return false;
+ }
+ if (createdDt != null ? !createdDt.equals(that.createdDt) : that.createdDt != null) {
+ return false;
+ }
+ if (creditCardType != null ? !creditCardType.equals(that.creditCardType) : that.creditCardType != null) {
+ return false;
+ }
+ if (key != null ? !key.equals(that.key) : that.key != null) {
+ return false;
+ }
+ if (lastInvoiceDate != null ? !lastInvoiceDate.equals(that.lastInvoiceDate) : that.lastInvoiceDate != null) {
+ return false;
+ }
+ if (lastPaymentStatus != null ? !lastPaymentStatus.equals(that.lastPaymentStatus) : that.lastPaymentStatus != null) {
+ return false;
+ }
+ if (paymentMethod != null ? !paymentMethod.equals(that.paymentMethod) : that.paymentMethod != null) {
+ return false;
+ }
+ if (tags != null ? !tags.equals(that.tags) : that.tags != null) {
+ return false;
+ }
+ if (totalInvoiceBalance != null ? !(Rounder.round(totalInvoiceBalance) == Rounder.round(that.totalInvoiceBalance)) : that.totalInvoiceBalance != null) {
+ return false;
+ }
+ if (updatedDt != null ? !updatedDt.equals(that.updatedDt) : that.updatedDt != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = createdDt != null ? createdDt.hashCode() : 0;
+ result = 31 * result + (updatedDt != null ? updatedDt.hashCode() : 0);
+ result = 31 * result + (key != null ? key.hashCode() : 0);
+ result = 31 * result + (balance != null ? balance.hashCode() : 0);
+ result = 31 * result + (tags != null ? tags.hashCode() : 0);
+ result = 31 * result + (lastInvoiceDate != null ? lastInvoiceDate.hashCode() : 0);
+ result = 31 * result + (totalInvoiceBalance != null ? totalInvoiceBalance.hashCode() : 0);
+ result = 31 * result + (lastPaymentStatus != null ? lastPaymentStatus.hashCode() : 0);
+ result = 31 * result + (paymentMethod != null ? paymentMethod.hashCode() : 0);
+ result = 31 * result + (creditCardType != null ? creditCardType.hashCode() : 0);
+ result = 31 * result + (billingAddressCountry != null ? billingAddressCountry.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
index 474c854..b85f6f3 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
@@ -16,6 +16,7 @@
package com.ning.billing.analytics;
+import com.ning.billing.analytics.utils.Rounder;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.IDuration;
import com.ning.billing.catalog.api.IPlan;
@@ -44,13 +45,13 @@ public class BusinessSubscription
private static final BigDecimal DAYS_IN_MONTH = BigDecimal.valueOf(30);
private static final BigDecimal MONTHS_IN_YEAR = BigDecimal.valueOf(12);
private static final Currency USD = Currency.valueOf("USD");
- private static final int SCALE = 4;
private final String productName;
private final String productType;
private final ProductCategory productCategory;
private final String slug;
private final String phase;
+ private final String billingPeriod;
private final BigDecimal price;
private final BigDecimal mrr;
private final String currency;
@@ -59,13 +60,14 @@ public class BusinessSubscription
private final UUID subscriptionId;
private final UUID bundleId;
- public BusinessSubscription(final String productName, final String productType, final ProductCategory productCategory, final String slug, final String phase, final BigDecimal price, final BigDecimal mrr, final String currency, final DateTime startDate, final SubscriptionState state, final UUID subscriptionId, final UUID bundleId)
+ public BusinessSubscription(final String productName, final String productType, final ProductCategory productCategory, final String slug, final String phase, final String billingPeriod, final BigDecimal price, final BigDecimal mrr, final String currency, final DateTime startDate, final SubscriptionState state, final UUID subscriptionId, final UUID bundleId)
{
this.productName = productName;
this.productType = productType;
this.productCategory = productCategory;
this.slug = slug;
this.phase = phase;
+ this.billingPeriod = billingPeriod;
this.price = price;
this.mrr = mrr;
this.currency = currency;
@@ -111,9 +113,11 @@ public class BusinessSubscription
if (currentPhase.getPhaseType() != null) {
phase = currentPhase.getPhaseType().toString();
+ billingPeriod = currentPhase.getBillingPeriod().toString();
}
else {
phase = null;
+ billingPeriod = null;
}
if (currentPhase.getRecurringPrice() != null) {
@@ -128,6 +132,7 @@ public class BusinessSubscription
else {
slug = null;
phase = null;
+ billingPeriod = null;
price = null;
mrr = null;
}
@@ -145,6 +150,11 @@ public class BusinessSubscription
this.bundleId = bundleId;
}
+ public String getBillingPeriod()
+ {
+ return billingPeriod;
+ }
+
public UUID getBundleId()
{
return bundleId;
@@ -162,7 +172,7 @@ public class BusinessSubscription
public double getRoundedMrr()
{
- return round(mrr);
+ return Rounder.round(mrr);
}
public String getPhase()
@@ -177,7 +187,7 @@ public class BusinessSubscription
public double getRoundedPrice()
{
- return round(price);
+ return Rounder.round(price);
}
public ProductCategory getProductCategory()
@@ -228,10 +238,10 @@ public class BusinessSubscription
return price.multiply(DAYS_IN_MONTH).multiply(BigDecimal.valueOf(duration.getLength()));
}
else if (duration.getUnit().equals(TimeUnit.MONTHS)) {
- return price.divide(BigDecimal.valueOf(duration.getLength()), SCALE, BigDecimal.ROUND_HALF_UP);
+ return price.divide(BigDecimal.valueOf(duration.getLength()), Rounder.SCALE, BigDecimal.ROUND_HALF_UP);
}
else if (duration.getUnit().equals(TimeUnit.YEARS)) {
- return price.divide(BigDecimal.valueOf(duration.getLength()), SCALE, RoundingMode.HALF_UP).divide(MONTHS_IN_YEAR, SCALE, RoundingMode.HALF_UP);
+ return price.divide(BigDecimal.valueOf(duration.getLength()), Rounder.SCALE, RoundingMode.HALF_UP).divide(MONTHS_IN_YEAR, Rounder.SCALE, RoundingMode.HALF_UP);
}
else {
log.error("Unknown duration [" + duration + "], can't compute mrr");
@@ -239,25 +249,15 @@ public class BusinessSubscription
}
}
- public static double round(final BigDecimal decimal)
- {
- if (decimal == null) {
- return 0;
- }
- else {
- return decimal.setScale(SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
- }
- }
-
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append("BusinessSubscription");
- sb.append("{bundleId=").append(bundleId);
+ sb.append("{billingPeriod='").append(billingPeriod).append('\'');
sb.append(", productName='").append(productName).append('\'');
sb.append(", productType='").append(productType).append('\'');
- sb.append(", productCategory='").append(productCategory).append('\'');
+ sb.append(", productCategory=").append(productCategory);
sb.append(", slug='").append(slug).append('\'');
sb.append(", phase='").append(phase).append('\'');
sb.append(", price=").append(price);
@@ -266,6 +266,7 @@ public class BusinessSubscription
sb.append(", startDate=").append(startDate);
sb.append(", state=").append(state);
sb.append(", subscriptionId=").append(subscriptionId);
+ sb.append(", bundleId=").append(bundleId);
sb.append('}');
return sb.toString();
}
@@ -282,19 +283,22 @@ public class BusinessSubscription
final BusinessSubscription that = (BusinessSubscription) o;
+ if (billingPeriod != null ? !billingPeriod.equals(that.billingPeriod) : that.billingPeriod != null) {
+ return false;
+ }
if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
return false;
}
if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
return false;
}
- if (mrr != null ? !(round(mrr) == round(that.mrr)) : that.mrr != null) {
+ if (mrr != null ? !(Rounder.round(mrr) == Rounder.round(that.mrr)) : that.mrr != null) {
return false;
}
if (phase != null ? !phase.equals(that.phase) : that.phase != null) {
return false;
}
- if (price != null ? !(round(price) == round(that.price)) : that.price != null) {
+ if (price != null ? !(Rounder.round(price) == Rounder.round(that.price)) : that.price != null) {
return false;
}
if (productCategory != null ? !productCategory.equals(that.productCategory) : that.productCategory != null) {
@@ -337,6 +341,7 @@ public class BusinessSubscription
result = 31 * result + (state != null ? state.hashCode() : 0);
result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+ result = 31 * result + (billingPeriod != null ? billingPeriod.hashCode() : 0);
return result;
}
}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountBinder.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountBinder.java
new file mode 100644
index 0000000..6a3e218
--- /dev/null
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountBinder.java
@@ -0,0 +1,72 @@
+/*
+ * 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.analytics.dao;
+
+import com.google.common.base.Joiner;
+import com.ning.billing.analytics.BusinessAccount;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@BindingAnnotation(BusinessAccountBinder.BacBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface BusinessAccountBinder
+{
+ public static class BacBinderFactory implements BinderFactory
+ {
+ private final Joiner joiner = Joiner.on(";").skipNulls();
+
+ public Binder build(final Annotation annotation)
+ {
+ return new Binder<BusinessAccountBinder, BusinessAccount>()
+ {
+ public void bind(final SQLStatement q, final BusinessAccountBinder bind, final BusinessAccount account)
+ {
+ final DateTime dateTimeNow = new DateTime(DateTimeZone.UTC);
+
+ if (account.getCreatedDt() != null) {
+ q.bind("created_dt", account.getCreatedDt().getMillis());
+ }
+ else {
+ q.bind("created_dt", dateTimeNow.getMillis());
+ }
+ q.bind("updated_dt", dateTimeNow.getMillis());
+
+ q.bind("account_key", account.getKey());
+ q.bind("balance", account.getRoundedBalance());
+ q.bind("tags", joiner.join(account.getTags()));
+ q.bind("last_invoice_date", account.getLastInvoiceDate().getMillis());
+ q.bind("total_invoice_balance", account.getRoundedTotalInvoiceBalance());
+ q.bind("last_payment_status", account.getLastPaymentStatus());
+ q.bind("payment_method", account.getPaymentMethod());
+ q.bind("credit_card_type", account.getCreditCardType());
+ q.bind("billing_address_country", account.getBillingAddressCountry());
+ }
+ };
+ }
+ }
+}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountDao.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountDao.java
new file mode 100644
index 0000000..7223f82
--- /dev/null
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountDao.java
@@ -0,0 +1,41 @@
+/*
+ * 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.analytics.dao;
+
+import com.ning.billing.analytics.BusinessAccount;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(BusinessAccountMapper.class)
+public interface BusinessAccountDao
+{
+ @SqlQuery
+ BusinessAccount getAccount(@Bind("account_key") final String key);
+
+ @SqlUpdate
+ int createAccount(@BusinessAccountBinder final BusinessAccount account);
+
+ @SqlUpdate
+ int saveAccount(@BusinessAccountBinder final BusinessAccount account);
+
+ @SqlUpdate
+ void test();
+}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountMapper.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountMapper.java
new file mode 100644
index 0000000..48e22e0
--- /dev/null
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountMapper.java
@@ -0,0 +1,59 @@
+/*
+ * 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.analytics.dao;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.ning.billing.analytics.BusinessAccount;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BusinessAccountMapper implements ResultSetMapper<BusinessAccount>
+{
+ private final Splitter splitter = Splitter.on(";").trimResults().omitEmptyStrings();
+
+ @Override
+ public BusinessAccount map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException
+ {
+ final List<String> tags = new ArrayList<String>();
+ Iterables.addAll(tags, splitter.split(r.getString(5)));
+
+ final BusinessAccount account = new BusinessAccount(
+ r.getString(1),
+ BigDecimal.valueOf(r.getDouble(4)),
+ tags,
+ new DateTime(r.getLong(6), DateTimeZone.UTC),
+ BigDecimal.valueOf(r.getDouble(7)),
+ r.getString(8),
+ r.getString(9),
+ r.getString(10),
+ r.getString(11)
+ );
+ account.setCreatedDt(new DateTime(r.getLong(2), DateTimeZone.UTC));
+ account.setUpdatedDt(new DateTime(r.getLong(3), DateTimeZone.UTC));
+
+ return account;
+ }
+}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
index 6a10741..ccf2a2b 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
@@ -54,6 +54,7 @@ public @interface BusinessSubscriptionTransitionBinder
q.bindNull("prev_product_category", Types.VARCHAR);
q.bindNull("prev_slug", Types.VARCHAR);
q.bindNull("prev_phase", Types.VARCHAR);
+ q.bindNull("prev_billing_period", Types.VARCHAR);
q.bindNull("prev_price", Types.NUMERIC);
q.bindNull("prev_mrr", Types.NUMERIC);
q.bindNull("prev_currency", Types.VARCHAR);
@@ -73,6 +74,7 @@ public @interface BusinessSubscriptionTransitionBinder
}
q.bind("prev_slug", previousSubscription.getSlug());
q.bind("prev_phase", previousSubscription.getPhase());
+ q.bind("prev_billing_period", previousSubscription.getBillingPeriod());
q.bind("prev_price", previousSubscription.getRoundedPrice());
q.bind("prev_mrr", previousSubscription.getRoundedMrr());
q.bind("prev_currency", previousSubscription.getCurrency());
@@ -109,6 +111,7 @@ public @interface BusinessSubscriptionTransitionBinder
q.bindNull("next_product_category", Types.VARCHAR);
q.bindNull("next_slug", Types.VARCHAR);
q.bindNull("next_phase", Types.VARCHAR);
+ q.bindNull("next_billing_period", Types.VARCHAR);
q.bindNull("next_price", Types.NUMERIC);
q.bindNull("next_mrr", Types.NUMERIC);
q.bindNull("next_currency", Types.VARCHAR);
@@ -128,6 +131,7 @@ public @interface BusinessSubscriptionTransitionBinder
}
q.bind("next_slug", nextSubscription.getSlug());
q.bind("next_phase", nextSubscription.getPhase());
+ q.bind("next_billing_period", nextSubscription.getBillingPeriod());
q.bind("next_price", nextSubscription.getRoundedPrice());
q.bind("next_mrr", nextSubscription.getRoundedMrr());
q.bind("next_currency", nextSubscription.getCurrency());
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDaoProvider.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDaoProvider.java
new file mode 100644
index 0000000..86b5665
--- /dev/null
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDaoProvider.java
@@ -0,0 +1,38 @@
+/*
+ * 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.analytics.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import org.skife.jdbi.v2.DBI;
+
+public class BusinessSubscriptionTransitionDaoProvider implements Provider<BusinessSubscriptionTransitionDao>
+{
+ private final DBI dbi;
+
+ @Inject
+ public BusinessSubscriptionTransitionDaoProvider(final DBI dbi)
+ {
+ this.dbi = dbi;
+ }
+
+ @Override
+ public BusinessSubscriptionTransitionDao get()
+ {
+ return dbi.onDemand(BusinessSubscriptionTransitionDao.class);
+ }
+}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
index 1788193..55aedb9 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
@@ -43,13 +43,14 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
r.getString(6) == null ? null : ProductCategory.valueOf(r.getString(6)), // productCategory
r.getString(7), // slug
r.getString(8), // phase
- BigDecimal.valueOf(r.getDouble(9)), // price
- BigDecimal.valueOf(r.getDouble(10)), // mrr
- r.getString(11), // currency
- r.getLong(12) == 0 ? null : new DateTime(r.getLong(12), DateTimeZone.UTC), // startDate
- r.getString(13) == null ? null : SubscriptionState.valueOf(r.getString(13)), // state
- r.getString(14) == null ? null : UUID.fromString(r.getString(14)), // subscriptionId
- r.getString(15) == null ? null : UUID.fromString(r.getString(15)) //bundleId
+ r.getString(9), // billing period
+ BigDecimal.valueOf(r.getDouble(10)), // price
+ BigDecimal.valueOf(r.getDouble(11)), // mrr
+ r.getString(12), // currency
+ r.getLong(13) == 0 ? null : new DateTime(r.getLong(13), DateTimeZone.UTC), // startDate
+ r.getString(14) == null ? null : SubscriptionState.valueOf(r.getString(14)), // state
+ r.getString(15) == null ? null : UUID.fromString(r.getString(15)), // subscriptionId
+ r.getString(16) == null ? null : UUID.fromString(r.getString(16)) //bundleId
);
// Avoid creating a dummy subscriptions with all null fields
@@ -58,18 +59,19 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
}
BusinessSubscription next = new BusinessSubscription(
- r.getString(16), // productName
- r.getString(17), // productType
- r.getString(18) == null ? null : ProductCategory.valueOf(r.getString(18)), // productCategory
- r.getString(19), // slug8
- r.getString(20), // phase
- BigDecimal.valueOf(r.getDouble(21)), // price
- BigDecimal.valueOf(r.getDouble(22)), // mrr
- r.getString(23), // currency
- r.getLong(24) == 0 ? null : new DateTime(r.getLong(24), DateTimeZone.UTC), // startDate
- r.getString(25) == null ? null : SubscriptionState.valueOf(r.getString(25)), // state
- r.getString(26) == null ? null : UUID.fromString(r.getString(26)), // subscriptionId
- r.getString(27) == null ? null : UUID.fromString(r.getString(27)) //bundleId
+ r.getString(17), // productName
+ r.getString(18), // productType
+ r.getString(19) == null ? null : ProductCategory.valueOf(r.getString(19)), // productCategory
+ r.getString(20), // slug8
+ r.getString(21), // phase
+ r.getString(22), // billing period
+ BigDecimal.valueOf(r.getDouble(23)), // price
+ BigDecimal.valueOf(r.getDouble(24)), // mrr
+ r.getString(25), // currency
+ r.getLong(26) == 0 ? null : new DateTime(r.getLong(26), DateTimeZone.UTC), // startDate
+ r.getString(27) == null ? null : SubscriptionState.valueOf(r.getString(27)), // state
+ r.getString(28) == null ? null : UUID.fromString(r.getString(28)), // subscriptionId
+ r.getString(29) == null ? null : UUID.fromString(r.getString(29)) //bundleId
);
// Avoid creating a dummy subscriptions with all null fields
diff --git a/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java b/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java
index 46e9131..7c74808 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java
@@ -18,14 +18,17 @@ package com.ning.billing.analytics.setup;
import com.google.inject.AbstractModule;
-import com.ning.billing.analytics.dao.EventDao;
-import com.ning.billing.analytics.dao.EventDaoProvider;
+import com.ning.billing.analytics.dao.BusinessAccountDao;
+import com.ning.billing.analytics.dao.BusinessAccountDaoProvider;
+import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDao;
+import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDaoProvider;
public class AnalyticsModule extends AbstractModule
{
@Override
protected void configure()
{
- bind(EventDao.class).toProvider(EventDaoProvider.class).asEagerSingleton();
+ bind(BusinessSubscriptionTransitionDao.class).toProvider(BusinessSubscriptionTransitionDaoProvider.class).asEagerSingleton();
+ bind(BusinessAccountDao.class).toProvider(BusinessAccountDaoProvider.class).asEagerSingleton();
}
}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/utils/Rounder.java b/analytics/src/main/java/com/ning/billing/analytics/utils/Rounder.java
new file mode 100644
index 0000000..0f0adef
--- /dev/null
+++ b/analytics/src/main/java/com/ning/billing/analytics/utils/Rounder.java
@@ -0,0 +1,34 @@
+/*
+ * 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.analytics.utils;
+
+import java.math.BigDecimal;
+
+public class Rounder
+{
+ public static final int SCALE = 4;
+
+ public static double round(final BigDecimal decimal)
+ {
+ if (decimal == null) {
+ return 0;
+ }
+ else {
+ return decimal.setScale(SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
+ }
+ }
+}
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessAccountDao.sql.stg b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessAccountDao.sql.stg
new file mode 100644
index 0000000..55f03e8
--- /dev/null
+++ b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessAccountDao.sql.stg
@@ -0,0 +1,67 @@
+group BusinessAccount;
+
+getAccount(account_key) ::= <<
+ select
+ account_key
+ , created_dt
+ , updated_dt
+ , balance
+ , tags
+ , last_invoice_date
+ , total_invoice_balance
+ , last_payment_status
+ , payment_method
+ , credit_card_type
+ , billing_address_country
+ from bac
+ where account_key=:account_key
+ limit 1
+ ;
+>>
+
+createAccount() ::= <<
+ insert into bac(
+ account_key
+ , created_dt
+ , updated_dt
+ , balance
+ , tags
+ , last_invoice_date
+ , total_invoice_balance
+ , last_payment_status
+ , payment_method
+ , credit_card_type
+ , billing_address_country
+ ) values (
+ :account_key
+ , :created_dt
+ , :updated_dt
+ , :balance
+ , :tags
+ , :last_invoice_date
+ , :total_invoice_balance
+ , :last_payment_status
+ , :payment_method
+ , :credit_card_type
+ , :billing_address_country
+ );
+>>
+
+saveAccount() ::= <<
+ update bac set
+ updated_dt=:updated_dt
+ , balance=:balance
+ , tags=:tags
+ , last_invoice_date=:last_invoice_date
+ , total_invoice_balance=:total_invoice_balance
+ , last_payment_status=:last_payment_status
+ , payment_method=:payment_method
+ , credit_card_type=:credit_card_type
+ , billing_address_country=:billing_address_country
+ where account_key=:account_key
+ ;
+>>
+
+test() ::= <<
+ select 1 from bac;
+>>
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql b/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
index f7be5f4..908715a 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
+++ b/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
@@ -8,6 +8,7 @@ create table bst (
, prev_product_category varchar(32) default null
, prev_slug varchar(50) default null
, prev_phase varchar(32) default null
+, prev_billing_period varchar(32) default null
, prev_price numeric(10, 4) default 0
, prev_mrr numeric(10, 4) default 0
, prev_currency varchar(32) default null
@@ -20,6 +21,7 @@ create table bst (
, next_product_category varchar(32) default null
, next_slug varchar(50) default null
, next_phase varchar(32) default null
+, next_billing_period varchar(32) default null
, next_price numeric(10, 4) default 0
, next_mrr numeric(10, 4) default 0
, next_currency varchar(32) default null
@@ -28,5 +30,20 @@ create table bst (
, next_subscription_id varchar(100) default null
, next_bundle_id varchar(100) default null
) engine=innodb;
-
create index bst_key_index on bst (event_key, requested_timestamp asc);
+
+drop table if exists bac;
+create table bac (
+ account_key varchar(50) not null
+, created_dt bigint not null
+, updated_dt bigint not null
+, balance numeric(10, 4) default 0
+, tags varchar(500) default null
+, last_invoice_date bigint default null
+, total_invoice_balance numeric(10, 4) default 0
+, last_payment_status varchar(100) default null
+, payment_method varchar(100) default null
+, credit_card_type varchar(32) default null
+, billing_address_country varchar(100) default null
+) engine=innodb;
+create unique index bac_key_index on bac (account_key);
\ No newline at end of file
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
index 54c0773..5075a92 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
@@ -83,7 +83,7 @@ public class MockPhase implements IPlanPhase
@Override
public BillingPeriod getBillingPeriod()
{
- throw new UnsupportedOperationException();
+ return BillingPeriod.MONTHLY;
}
@Override
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
index 7717796..e208852 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -44,13 +44,13 @@ public class MockSubscription implements ISubscription
}
@Override
- public void cancel()
+ public void cancel(DateTime requestedDate, boolean eot)
{
throw new UnsupportedOperationException();
}
@Override
- public void changePlan(final String productName, final BillingPeriod term, final String planSet)
+ public void changePlan(final String productName, final BillingPeriod term, final String planSet, DateTime requestedDate)
{
throw new UnsupportedOperationException();
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessAccount.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessAccount.java
new file mode 100644
index 0000000..5bdba44
--- /dev/null
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessAccount.java
@@ -0,0 +1,47 @@
+/*
+ * 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.analytics;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+
+public class TestBusinessAccount
+{
+ private BusinessAccount account;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ account = new BusinessAccount("pierre", BigDecimal.ONE, Collections.singletonList("batch15"), new DateTime(), BigDecimal.TEN, "ERROR_NOT_ENOUGH_FUNDS", "CreditCard", "Visa", "");
+ }
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception
+ {
+ Assert.assertSame(account, account);
+ Assert.assertEquals(account, account);
+ Assert.assertTrue(account.equals(account));
+
+ final BusinessAccount otherAccount = new BusinessAccount("pierre", BigDecimal.ONE, Collections.singletonList("batch15"), new DateTime(), BigDecimal.TEN, "ERROR_NOT_ENOUGH_FUNDS", "CreditCard", "Visa", "");
+ Assert.assertFalse(account.equals(otherAccount));
+ }
+}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
index 2def231..f185a2a 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
@@ -84,6 +84,7 @@ public class TestBusinessSubscription
Assert.assertEquals(subscription.getRoundedMrr(), 0.0);
Assert.assertEquals(subscription.getSlug(), phase.getName());
Assert.assertEquals(subscription.getPhase(), phase.getPhaseType().toString());
+ Assert.assertEquals(subscription.getBillingPeriod(), phase.getBillingPeriod().toString());
Assert.assertEquals(subscription.getPrice(), phase.getRecurringPrice().getPrice(null));
Assert.assertEquals(subscription.getProductCategory(), product.getCategory());
Assert.assertEquals(subscription.getProductName(), product.getName());
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index 5cfa476..834c8f1 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -14,7 +14,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/catalog/api/BillingPeriod.java b/api/src/main/java/com/ning/billing/catalog/api/BillingPeriod.java
index aa8b20c..7d129af 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/BillingPeriod.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/BillingPeriod.java
@@ -20,8 +20,9 @@ public enum BillingPeriod {
MONTHLY(1),
QUARTERLY(3),
//SEMI_ANNUAL(6), ** not yet supported
- ANNUAL(12);
+ ANNUAL(12),
//BI_ANNUAL(24); ** not yet supported
+ NO_BILLING_PERIOD(0);
private final int numberOfMonths;
diff --git a/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java b/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java
index 403adec..5a5f872 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java
@@ -22,11 +22,7 @@ import java.util.List;
public interface ICatalog {
public abstract IProduct[] getProducts();
-
- public abstract IPriceListSet getPriceLists();
-
- public abstract IPriceList getPriceListFromName(String priceListName);
-
+
public abstract IPlan getPlan(String productName, BillingPeriod term, String priceList);
public abstract Currency[] getSupportedCurrencies();
diff --git a/api/src/main/java/com/ning/billing/catalog/api/IPriceListSet.java b/api/src/main/java/com/ning/billing/catalog/api/IPriceListSet.java
index f973b9e..bbbb3c2 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/IPriceListSet.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/IPriceListSet.java
@@ -17,13 +17,9 @@
package com.ning.billing.catalog.api;
public interface IPriceListSet {
-
- public static final String DEFAULT_PRICELIST_NAME = "DEFAULT";
- public abstract IPriceList getDefaultPricelist();
+ public static final String DEFAULT_PRICELIST_NAME="DEFAULT";
- public abstract IPriceList[] getChildPriceLists();
-
- public abstract IPriceList getPriceListFromName(String priceListName);
+ public abstract IPlan getPlanListFrom(String priceListName, IProduct product, BillingPeriod period);
}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/config/IEntitlementConfig.java b/api/src/main/java/com/ning/billing/config/IEntitlementConfig.java
index 0cb228b..167e1e5 100644
--- a/api/src/main/java/com/ning/billing/config/IEntitlementConfig.java
+++ b/api/src/main/java/com/ning/billing/config/IEntitlementConfig.java
@@ -26,14 +26,14 @@ public interface IEntitlementConfig {
public long getDaoClaimTimeMs();
@Config("killbill.entitlement.dao.ready.max")
- @Default("1")
+ @Default("10")
public int getDaoMaxReadyEvents();
- @Config("killbill.entitlement.catalog.config.file")
- @Default("hum, not sure")
- public String getCatalogConfigFileName();
-
@Config("killbill.entitlement.engine.notifications.sleep")
@Default("500")
public long getNotificationSleepTimeMs();
+
+ @Config("killbill.entitlement.engine.events.off")
+ @Default("false")
+ public boolean isEventProcessingOff();
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/IEntitlementService.java b/api/src/main/java/com/ning/billing/entitlement/api/IEntitlementService.java
index bd47c6b..071936d 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/IEntitlementService.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/IEntitlementService.java
@@ -17,6 +17,8 @@
package com.ning.billing.entitlement.api;
import com.ning.billing.entitlement.api.billing.IEntitlementBillingApi;
+import com.ning.billing.entitlement.api.test.IEntitlementTestApi;
+import com.ning.billing.entitlement.api.user.IApiListener;
import com.ning.billing.entitlement.api.user.IEntitlementUserApi;
import com.ning.billing.lifecycle.IService;
@@ -30,4 +32,7 @@ public interface IEntitlementService extends IService {
public IEntitlementBillingApi getBillingApi();
+ public IEntitlementTestApi getTestApi();
+
+
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/IEntitlementUserApi.java b/api/src/main/java/com/ning/billing/entitlement/api/user/IEntitlementUserApi.java
index b37b976..f45f450 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/IEntitlementUserApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/IEntitlementUserApi.java
@@ -19,6 +19,8 @@ package com.ning.billing.entitlement.api.user;
import java.util.List;
import java.util.UUID;
+import org.joda.time.DateTime;
+
import com.ning.billing.account.api.IAccount;
import com.ning.billing.catalog.api.BillingPeriod;
@@ -36,6 +38,6 @@ public interface IEntitlementUserApi {
public ISubscriptionBundle createBundleForAccount(IAccount account, String bundleKey)
throws EntitlementUserApiException;
- public ISubscription createSubscription(UUID bundleId, String productName, BillingPeriod term, String planSet)
+ public ISubscription createSubscription(UUID bundleId, String productName, BillingPeriod term, String planSet, DateTime requestedDate)
throws EntitlementUserApiException;
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscription.java
index 4795655..574de30 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscription.java
@@ -29,13 +29,13 @@ import com.ning.billing.catalog.api.ActionPolicy;
public interface ISubscription extends IPrivateFields {
- public void cancel()
+ public void cancel(DateTime requestedDate, boolean eot)
throws EntitlementUserApiException;
public void uncancel()
throws EntitlementUserApiException;
- public void changePlan(String productName, BillingPeriod term, String planSet)
+ public void changePlan(String productName, BillingPeriod term, String planSet, DateTime requestedDate)
throws EntitlementUserApiException ;
public void pause()
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index d89ff97..24ee8c7 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -28,7 +28,8 @@ public enum ErrorCode {
* Range 1000 : ENTITLEMENTS
*
*/
- /* Not yet */
+ /* Generic through APIs */
+ ENT_INVALID_REQUESTED_DATE(1001, "Requested in the future is not allowed : %s"),
/* Creation */
ENT_CREATE_BAD_CATALOG(1011, "Plan for product %s, term %s and set %s does not exist in the catalog"),
beatrix/pom.xml 2(+1 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 04a0938..a8c5515 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-beatrix</artifactId>
catalog/pom.xml 2(+1 -1)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index d61f61f..0b6b6a3 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Catalog.java b/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
index f588821..bc6482d 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
@@ -31,13 +31,12 @@ import com.ning.billing.catalog.api.BillingAlignment;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.ICatalog;
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.catalog.api.IPriceList;
import com.ning.billing.catalog.api.IProduct;
import com.ning.billing.catalog.api.PlanAlignmentChange;
import com.ning.billing.catalog.api.PlanAlignmentCreate;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.rules.PlanRules;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
@@ -111,40 +110,14 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
this.products = products;
}
- /* (non-Javadoc)
- * @see com.ning.billing.catalog.ICatalog#getPlanSets()
- */
- @Override
- public PriceListSet getPriceLists() {
- return priceLists;
- }
- /* (non-Javadoc)
- * @see com.ning.billing.catalog.ICatalog#getPriceListFromName(java.lang.String)
- */
- @Override
- public PriceList getPriceListFromName(String priceListName) {
- return priceLists.getPriceListFromName(priceListName);
- }
-
/* (non-Javadoc)
* @see com.ning.billing.catalog.ICatalog#getPlan(java.lang.String, java.lang.String)
*/
@Override
- public Plan getPlan(String productName, BillingPeriod term, String planSetName) {
-
- PriceList planSet = getPriceListFromName(planSetName);
- if (planSet == null) {
- return null;
- }
-
- for (Plan cur : planSet.getPlans()) {
- if (cur.getProduct().getName().equals(productName) &&
- cur.getBillingPeriod() == term) {
- return cur;
- }
- }
- return null;
+ public Plan getPlan(String productName, BillingPeriod period, String priceListName) {
+ IProduct product = getProductFromName(productName);
+ return priceLists.getPlanListFrom(priceListName, product, period);
}
@Override
@@ -292,11 +265,19 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
this.priceLists = priceLists;
}
+ public PriceListSet getPriceLists() {
+ return this.priceLists;
+ }
+
@Override
public void configureEffectiveDate(Date date) {
// Nothing to do here this is a method that is only inplemented on VersionedCatalog
}
+
+ public PriceList getPriceListFromName(String priceListName) {
+ return priceLists.findPriceListFrom(priceListName);
+ }
//TODO: MDW validation - only allow one default pricelist
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Plan.java b/catalog/src/main/java/com/ning/billing/catalog/Plan.java
index 1ae6199..92a2e06 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Plan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Plan.java
@@ -63,7 +63,7 @@ public class Plan extends ValidatingConfig<Catalog> implements IPlan {
public Plan(){}
- protected Plan(String name, Product product, PlanPhase finalPhase) {
+ public Plan(String name, Product product, PlanPhase finalPhase) {
this.name = name;
this.product = product;
this.finalPhase = finalPhase;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java b/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
index 36250b4..6d9630b 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
@@ -40,7 +40,7 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
private Duration duration;
@XmlElement(required=false)
- private BillingPeriod billingPeriod;
+ private BillingPeriod billingPeriod = BillingPeriod.NO_BILLING_PERIOD;
@XmlElement(required=false)
private InternationalPrice recurringPrice;
@@ -56,7 +56,7 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
public PlanPhase(){}
- protected PlanPhase(BillingPeriod period, PhaseType type) {
+ public PlanPhase(BillingPeriod period, PhaseType type) {
this.billingPeriod = period;
this.type = type;
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceList.java b/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
index de76149..c4842f9 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
@@ -18,21 +18,58 @@ package com.ning.billing.catalog;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlID;
+import javax.xml.bind.annotation.XmlIDREF;
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.catalog.api.IPriceList;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.IProduct;
import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public abstract class PriceList extends ValidatingConfig<Catalog> implements IPriceList {
+public class PriceList extends ValidatingConfig<Catalog> {
+ @XmlAttribute(required=true)
@XmlID
- public abstract String getName();
+ private String name;
- public abstract Plan[] getPlans();
+ @XmlElementWrapper(name="plans", required=true)
+ @XmlElement(name="plan", required=true)
+ @XmlIDREF
+ private Plan[] plans;
+
+ public PriceList(){}
+
+ public PriceList(Plan[] plans, String name) {
+ this.plans = plans;
+ this.name = name;
+ }
+
+ protected Plan[] getPlans() {
+ return plans;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Plan findPlan(IProduct product, BillingPeriod period) {
+ for (Plan cur : getPlans()) {
+ if (cur.getProduct().equals(product) &&
+ (cur.getBillingPeriod() == null || cur.getBillingPeriod().equals(period))) {
+ return cur;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ValidationErrors validate(Catalog root, ValidationErrors errors) {
+ return errors;
+ }
- public abstract IPlan findPlanByProductName(String productName);
- public abstract boolean isDefault();
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
index 770f391..781f44d 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
@@ -18,52 +18,28 @@ package com.ning.billing.catalog;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlIDREF;
-import com.ning.billing.catalog.api.IPriceList;
import com.ning.billing.catalog.api.IPriceListSet;
-import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class PriceListDefault extends PriceList implements IPriceList {
-
- @XmlElementWrapper(name="plans", required=true)
- @XmlElement(name="plan", required=true)
- @XmlIDREF
- private Plan[] plans;
-
- /* (non-Javadoc)
- * @see com.ning.billing.catalog.IPriceListDefault#getPlans()
- */
- @Override
- public Plan[] getPlans() {
- return plans;
- }
-
- /* (non-Javadoc)
- * @see com.ning.billing.catalog.IPriceListDefault#findPlanByProductName(java.lang.String)
- */
- @Override
- public Plan findPlanByProductName(String productName) {
- for (Plan cur : plans) {
- if (cur.getProduct().getName().equals(productName)) {
- return cur;
- }
- }
- return null;
- }
-
- public void setPlans(Plan[] plans) {
- this.plans = plans;
+public class PriceListDefault extends PriceList {
+
+ public PriceListDefault(){}
+
+ public PriceListDefault(Plan[] defaultPlans) {
+ super(defaultPlans, IPriceListSet.DEFAULT_PRICELIST_NAME);
}
@Override
public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+ if(getName().equals(IPriceListSet.DEFAULT_PRICELIST_NAME)) {
+ errors.add(new ValidationError("The name of the default pricelist must be 'DEFAULT'",
+ catalog.getCatalogURI(), PriceList.class, getName()));
+
+ }
return errors;
-
}
@Override
@@ -71,9 +47,4 @@ public class PriceListDefault extends PriceList implements IPriceList {
return IPriceListSet.DEFAULT_PRICELIST_NAME;
}
- @Override
- public boolean isDefault() {
- return true;
- }
-
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java b/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
index 08c2cf9..7cd2986 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
@@ -20,76 +20,77 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
-import com.ning.billing.catalog.api.IPriceList;
+import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.IPriceListSet;
+import com.ning.billing.catalog.api.IProduct;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class PriceListSet extends ValidatingConfig<Catalog> implements IPriceListSet {
+public class PriceListSet extends ValidatingConfig<Catalog> {
@XmlElement(required=true, name="defaultPriceList")
private PriceListDefault defaultPricelist;
@XmlElement(required=false, name="childPriceList")
- private PriceListChild[] childPriceLists;
+ private PriceList[] childPriceLists;
public PriceListSet() {
if(childPriceLists == null) {
- childPriceLists = new PriceListChild[0];
+ childPriceLists = new PriceList[0];
}
}
- /* (non-Javadoc)
- * @see com.ning.billing.catalog.IPriceListSet#getDefaultPricelist()
- */
- @Override
- public PriceListDefault getDefaultPricelist() {
- return defaultPricelist;
- }
-
- /* (non-Javadoc)
- * @see com.ning.billing.catalog.IPriceListSet#getChildPriceLists()
- */
- @Override
- public PriceListChild[] getChildPriceLists() {
- return childPriceLists;
+
+ public PriceListSet(PriceListDefault defaultPricelist, PriceList[] childPriceLists) {
+ this.defaultPricelist = defaultPricelist;
+ this.childPriceLists = childPriceLists;
}
- /* (non-Javadoc)
- * @see com.ning.billing.catalog.IPriceListSet#getPriceListFromName(String priceListName)
- */
- @Override
- public PriceList getPriceListFromName(String priceListName) {
- if(priceListName.equals(DEFAULT_PRICELIST_NAME)) {
- return getDefaultPricelist();
+ public Plan getPlanListFrom(String priceListName, IProduct product,
+ BillingPeriod period) {
+ Plan result = null;
+ PriceList pl = findPriceListFrom(priceListName);
+ if(pl != null) {
+ result = pl.findPlan(product, period);
}
- for(PriceListChild set : childPriceLists) {
- if(set.getName().equals(priceListName)) {
- return set;
- }
+ if(result != null) {
+ return result;
}
- return null;
+
+ return defaultPricelist.findPlan(product, period);
}
-
-
- public void setDefaultPricelist(PriceListDefault defaultPricelist) {
- this.defaultPricelist = defaultPricelist;
- }
-
- public void setChildPriceLists(PriceListChild[] childPriceLists) {
- this.childPriceLists = childPriceLists;
+ public PriceList findPriceListFrom (String priceListName) {
+ if (defaultPricelist.getName().equals(priceListName)) {
+ return defaultPricelist;
+ }
+ for(PriceList pl : childPriceLists) {
+ if(pl.getName().equals(priceListName)) {
+ return pl;
+ }
+ }
+ return null;
}
@Override
public ValidationErrors validate(Catalog root, ValidationErrors errors) {
//Check that the default pricelist name is not in use in the children
- for(PriceListChild pl : childPriceLists) {
- if(pl.getName().equals(DEFAULT_PRICELIST_NAME)){
- errors.add(new ValidationError("Pricelists cannot use the reserved name '" + DEFAULT_PRICELIST_NAME + "'", root.getCatalogURI(), PriceListSet.class, pl.getName()));
+ for(PriceList pl : childPriceLists) {
+ if(pl.getName().equals(IPriceListSet.DEFAULT_PRICELIST_NAME)){
+ errors.add(new ValidationError("Pricelists cannot use the reserved name '" + IPriceListSet.DEFAULT_PRICELIST_NAME + "'", root.getCatalogURI(), PriceListSet.class, pl.getName()));
}
}
return errors;
}
+
+ public PriceList getDefaultPricelist() {
+ return defaultPricelist;
+ }
+
+ public PriceList[] getChildPriceLists() {
+ return childPriceLists;
+ }
+
+
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Product.java b/catalog/src/main/java/com/ning/billing/catalog/Product.java
index 176b8d4..371c4be 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Product.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Product.java
@@ -76,7 +76,7 @@ public class Product extends ValidatingConfig<Catalog> implements IProduct {
public Product() {
}
- protected Product(String name, ProductCategory category) {
+ public Product(String name, ProductCategory category) {
this.category = category;
this.name = name;
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
new file mode 100644
index 0000000..ccd0f87
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
@@ -0,0 +1,59 @@
+/*
+ * 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.catalog.rules;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
+import com.ning.billing.catalog.PriceList;
+import com.ning.billing.catalog.Product;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class CasePriceList extends Case<PriceList> {
+
+ private PriceList toPriceList;
+
+ @XmlElement(required=false, name="fromProduct")
+ @XmlIDREF
+ public Product getProduct(){
+ return product;
+ }
+
+ @XmlElement(required=false, name="fromProductCategory")
+ public ProductCategory getProductCategory() {
+ return productCategory;
+ }
+
+ @XmlElement(required=false, name="fromBillingPeriod")
+ public BillingPeriod getBillingPeriod() {
+ return billingPeriod;
+ }
+
+ @XmlElement(required=false, name="fromPriceList")
+ @XmlIDREF
+ public PriceList getPriceList() {
+ return priceList;
+ }
+
+ @Override
+ @XmlElement(required=true, name="toPriceList")
+ @XmlIDREF
+ protected PriceList getResult() {
+ return toPriceList;
+ }
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
new file mode 100644
index 0000000..3b20634
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
@@ -0,0 +1,58 @@
+/*
+ * 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.catalog.rules;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
+import com.ning.billing.catalog.PriceList;
+import com.ning.billing.catalog.Product;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public abstract class CaseStandardNaming<T> extends Case<T> {
+
+ public CaseStandardNaming() {}
+
+ public CaseStandardNaming(Product product, ProductCategory productCategory,
+ BillingPeriod billingPeriod, PriceList priceList, T result) {
+ super(product, productCategory, billingPeriod, priceList, result);
+ }
+
+ @XmlElement(required=false, name="product")
+ @XmlIDREF
+ public Product getProduct(){
+ return product;
+ }
+
+ @XmlElement(required=false, name="productCategory")
+ public ProductCategory getProductCategory() {
+ return productCategory;
+ }
+
+ @XmlElement(required=false, name="billingPeriod")
+ public BillingPeriod getBillingPeriod() {
+ return billingPeriod;
+ }
+
+ @XmlElement(required=false, name="priceList")
+ @XmlIDREF
+ public PriceList getPriceList() {
+ return priceList;
+ }
+
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
index 676123b..288c3df 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -30,7 +30,6 @@ import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.ICatalog;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
-import com.ning.billing.catalog.api.IPriceList;
import com.ning.billing.catalog.api.IProduct;
import com.ning.billing.catalog.api.PlanAlignmentChange;
import com.ning.billing.catalog.api.PlanAlignmentCreate;
@@ -94,16 +93,6 @@ public class VersionedCatalog extends ValidatingConfig<Catalog> implements ICata
}
@Override
- public PriceListSet getPriceLists() {
- return currentCatalog.getPriceLists();
- }
-
- @Override
- public IPriceList getPriceListFromName(String planSetName) {
- return currentCatalog.getPriceListFromName(planSetName);
- }
-
- @Override
public IPlan getPlan(String productName, BillingPeriod term,
String planSetName) {
return currentCatalog.getPlan(productName, term, planSetName);
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
new file mode 100644
index 0000000..0825eb9
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
@@ -0,0 +1,79 @@
+/*
+ * 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.catalog;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.IPriceListSet;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class TestPriceListSet {
+ @Test(enabled=true)
+ public void testOverriding() {
+ Product foo = new Product("Foo", ProductCategory.BASE);
+ Product bar = new Product("Bar", ProductCategory.BASE);
+ Plan[] defaultPlans = new Plan[]{
+ new Plan("plan-foo-monthly", foo, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
+ new Plan("plan-bar-monthly", bar, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
+ new Plan("plan-foo-annual", foo, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.EVERGREEN)),
+ new Plan("plan-bar-annual", bar, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.EVERGREEN))
+ };
+ Plan[] childPlans = new Plan[]{
+ new Plan("plan-foo", foo, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT)),
+ new Plan("plan-bar", bar, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT))
+ };
+ PriceListDefault defaultPriceList = new PriceListDefault(defaultPlans);
+ PriceList[] childPriceLists = new PriceList[] {
+ new PriceList(childPlans, "child")
+ };
+ PriceListSet set = new PriceListSet(defaultPriceList, childPriceLists);
+
+ Assert.assertEquals(set.getPlanListFrom(IPriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanListFrom(IPriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.DISCOUNT);
+ Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ }
+
+ public void testForNullBillingPeriod() {
+ Product foo = new Product("Foo", ProductCategory.BASE);
+ Product bar = new Product("Bar", ProductCategory.BASE);
+ Plan[] defaultPlans = new Plan[]{
+ new Plan("plan-foo-monthly", foo, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
+ new Plan("plan-bar-monthly", bar, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
+ new Plan("plan-foo-annual", foo, new PlanPhase(null, PhaseType.EVERGREEN)),
+ new Plan("plan-bar-annual", bar, new PlanPhase(null, PhaseType.EVERGREEN))
+ };
+ Plan[] childPlans = new Plan[]{
+ new Plan("plan-foo", foo, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT)),
+ new Plan("plan-bar", bar, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT))
+ };
+ PriceListDefault defaultPriceList = new PriceListDefault(defaultPlans);
+ PriceList[] childPriceLists = new PriceList[] {
+ new PriceList(childPlans, "child")
+ };
+ PriceListSet set = new PriceListSet(defaultPriceList, childPriceLists);
+
+ Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.DISCOUNT);
+ Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanListFrom(IPriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanListFrom(IPriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ }
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
index 4515af1..fc456ac 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
@@ -30,6 +30,8 @@ import org.testng.annotations.Test;
import org.xml.sax.SAXException;
import com.google.common.io.Resources;
+import com.ning.billing.catalog.Catalog;
+import com.ning.billing.catalog.VersionedCatalog;
import com.ning.billing.catalog.api.InvalidConfigException;
import com.ning.billing.catalog.io.VersionedCatalogLoader;
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
index ccba4c0..2214b04 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
@@ -153,7 +153,7 @@
</plan>
</plans>
<priceLists>
- <defaultPriceList>
+ <defaultPriceList name="DEFAULT">
<plans>
<plan>pistol-monthly</plan>
<plan>shotgun-monthly</plan>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
index e97d5ba..7d0e1b8 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
@@ -16,7 +16,7 @@
-->
<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="../../../main/resources/CatalogSchema.xsd ">
+ xsi:noNamespaceSchemaLocation="../CatalogSchema.xsd ">
<effectiveDate>2011-02-02T00:00:00+00:00</effectiveDate>
<catalogName>WeaponsHireSmall</catalogName>
@@ -153,7 +153,7 @@
</plan>
</plans>
<priceLists>
- <defaultPriceList>
+ <defaultPriceList name="DEFAULT">
<plans>
<plan>pistol-monthly</plan>
<plan>shotgun-monthly</plan>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
index 568ec5e..070adbe 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
@@ -16,7 +16,7 @@
-->
<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="../../../main/resources/CatalogSchema.xsd ">
+ xsi:noNamespaceSchemaLocation="../CatalogSchema.xsd ">
<effectiveDate>2011-03-03T00:00:00+00:00</effectiveDate>
<catalogName>WeaponsHireSmall</catalogName>
@@ -153,7 +153,7 @@
</plan>
</plans>
<priceLists>
- <defaultPriceList>
+ <defaultPriceList name="DEFAULT">
<plans>
<plan>pistol-monthly</plan>
<plan>shotgun-monthly</plan>
diff --git a/catalog/src/test/resources/WeaponsHire.xml b/catalog/src/test/resources/WeaponsHire.xml
index e9c041b..cfd445b 100644
--- a/catalog/src/test/resources/WeaponsHire.xml
+++ b/catalog/src/test/resources/WeaponsHire.xml
@@ -152,6 +152,10 @@ Use Cases to do:
<productCategory>ADD_ON</productCategory>
<alignment>BUNDLE</alignment>
</billingAlignmentCase>
+ <priceListCase>
+ <fromPriceList>rescue</fromPriceList>
+ <toPriceList>DEFAULT</toPriceList>
+ </priceListCase>
</rules>
<plans>
@@ -549,7 +553,7 @@ Use Cases to do:
</plan>
</plans>
<priceLists>
- <defaultPriceList>
+ <defaultPriceList name="DEFAULT">
<plans>
<plan>pistol-monthly</plan>
<plan>shotgun-monthly</plan>
diff --git a/catalog/src/test/resources/WeaponsHireSmall.xml b/catalog/src/test/resources/WeaponsHireSmall.xml
index c6b25da..c4a098d 100644
--- a/catalog/src/test/resources/WeaponsHireSmall.xml
+++ b/catalog/src/test/resources/WeaponsHireSmall.xml
@@ -153,7 +153,7 @@
</plan>
</plans>
<priceLists>
- <defaultPriceList>
+ <defaultPriceList name="DEFAULT">
<plans>
<plan>pistol-monthly</plan>
<plan>shotgun-monthly</plan>
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index d4e6ed5..5f4d4ef 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/test/EntitlementTestApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/test/EntitlementTestApi.java
new file mode 100644
index 0000000..8ba459e
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/test/EntitlementTestApi.java
@@ -0,0 +1,44 @@
+/*
+ * 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.entitlement.api.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.config.IEntitlementConfig;
+import com.ning.billing.entitlement.engine.core.IApiEventProcessor;
+
+public class EntitlementTestApi implements IEntitlementTestApi {
+
+ private final static Logger log = LoggerFactory.getLogger(EntitlementTestApi.class);
+
+ private final IApiEventProcessor apiEventProcessor;
+ private final IEntitlementConfig config;
+
+ public EntitlementTestApi(IApiEventProcessor apiEventProcessor, IEntitlementConfig config) {
+ this.apiEventProcessor = apiEventProcessor;
+ this.config = config;
+ }
+
+ @Override
+ public void doProcessReadyEvents() {
+ if (config.isEventProcessingOff()) {
+ log.warn("Running event processing loop");
+ apiEventProcessor.processAllReadyEvents();
+ }
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
index 4e17a53..d813be0 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
@@ -29,6 +29,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.ICatalogService;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
+import com.ning.billing.catalog.api.IPriceListSet;
import com.ning.billing.entitlement.alignment.IPlanAligner;
import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
import com.ning.billing.entitlement.api.user.ISubscription;
@@ -89,12 +90,17 @@ public class EntitlementUserApi implements IEntitlementUserApi {
@Override
public ISubscription createSubscription(UUID bundleId, String productName,
- BillingPeriod term, String priceList) throws EntitlementUserApiException {
+ BillingPeriod term, String priceList, DateTime requestedDate) throws EntitlementUserApiException {
// STEPH Should really get 'standard' from catalog
- String realPriceList = (priceList == null) ? "standard" : priceList;
+ String realPriceList = (priceList == null) ? IPriceListSet.DEFAULT_PRICELIST_NAME : priceList;
DateTime now = clock.getUTCNow();
+ if (requestedDate != null && requestedDate.isAfter(now)) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
+ }
+
+ requestedDate = (requestedDate == null) ? now : requestedDate;
IPlan plan = catalogService.getCatalog().getPlan(productName, term, realPriceList);
if (plan == null) {
@@ -121,7 +127,7 @@ public class EntitlementUserApi implements IEntitlementUserApi {
if (baseSubscription != null) {
throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_BP_EXISTS, bundleId);
}
- bundleStartDate = now;
+ bundleStartDate = requestedDate;
break;
case ADD_ON:
if (baseSubscription == null) {
@@ -134,14 +140,14 @@ public class EntitlementUserApi implements IEntitlementUserApi {
plan.getProduct().getCategory().toString()));
}
- DateTime effectiveDate = now;
-
+ DateTime effectiveDate = requestedDate;
Subscription subscription = new Subscription(bundleId, plan.getProduct().getCategory(), bundleStartDate, effectiveDate);
TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnCreate(subscription, plan, realPriceList, effectiveDate);
ApiEventCreate creationEvent =
new ApiEventCreate(subscription.getId(), bundleStartDate, now, plan.getName(), currentTimedPhase.getPhase().getName(), realPriceList,
- now, effectiveDate, subscription.getActiveVersion());
+ requestedDate, effectiveDate, subscription.getActiveVersion());
+
TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnCreate(subscription, plan, realPriceList, effectiveDate);
IPhaseEvent nextPhaseEvent = PhaseEvent.getNextPhaseEvent(nextTimedPhase, subscription, now);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index a5cd11e..2c04998 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -206,7 +206,7 @@ public class Subscription extends PrivateFields implements ISubscription {
@Override
- public void cancel() throws EntitlementUserApiException {
+ public void cancel(DateTime requestedDate, boolean eot) throws EntitlementUserApiException {
SubscriptionState currentState = getState();
if (currentState != SubscriptionState.ACTIVE) {
@@ -214,6 +214,9 @@ public class Subscription extends PrivateFields implements ISubscription {
}
DateTime now = clock.getUTCNow();
+ if (requestedDate != null && requestedDate.isAfter(now)) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
+ }
IPlan currentPlan = getCurrentPlan();
PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
@@ -251,7 +254,7 @@ public class Subscription extends PrivateFields implements ISubscription {
@Override
public void changePlan(String productName, BillingPeriod term,
- String priceList) throws EntitlementUserApiException {
+ String priceList, DateTime requestedDate) throws EntitlementUserApiException {
String currentPriceList = getCurrentPriceList();
String realPriceList = (priceList == null) ? currentPriceList : priceList;
@@ -399,22 +402,6 @@ public class Subscription extends PrivateFields implements ISubscription {
return false;
}
- // STEPH do we need that? forgot?
- private boolean isSubscriptionFutureChanged() {
- if (transitions == null) {
- return false;
- }
-
- for (SubscriptionTransition cur : transitions) {
- if (cur.getEffectiveTransitionTime().isBefore(clock.getUTCNow()) ||
- cur.getEventType() == EventType.PHASE ||
- cur.getApiEventType() != ApiEventType.CHANGE) {
- continue;
- }
- return true;
- }
- return false;
- }
private DateTime getPlanChangeEffectiveDate(ActionPolicy policy, DateTime now) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java
index 9389969..541de37 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java
@@ -33,11 +33,11 @@ public class ApiEventProcessor extends ApiEventProcessorBase {
@Override
- protected void doProcessEvents(int sequenceId) {
+ protected boolean doProcessEvents(int sequenceId) {
long prev = nbProcessedEvents;
List<IEvent> claimedEvents = dao.getEventsReady(apiProcessorId, sequenceId);
if (claimedEvents.size() == 0) {
- return;
+ return false;
}
log.debug(String.format("ApiEventProcessor got %d events", claimedEvents.size()));
@@ -51,6 +51,7 @@ public class ApiEventProcessor extends ApiEventProcessorBase {
dao.clearEventsReady(apiProcessorId, claimedEvents);
log.debug(String.format("ApiEventProcessor cleared events %d", nbProcessedEvents - prev));
//log.debug(String.format("ApiEventProcessor seq = %d cleared events %s", sequenceId, claimedEvents.get(0).getId()));
+ return true;
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
index cf20530..c5b9bd4 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
@@ -77,6 +77,11 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
this.isProcessingEvents = true;
this.nbProcessedEvents = 0;
+
+ if (config.isEventProcessingOff()) {
+ log.warn("KILLBILL ENTITLEMENT EVENT PROCESSING IS OFF !!!");
+ return;
+ }
final ApiEventProcessorBase apiEventProcessor = this;
synchronized (this) {
@@ -166,5 +171,21 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
}
}
- protected abstract void doProcessEvents(int sequenceId);
+
+ // Used for system test purpose only when event processing has been disabled.
+ @Override
+ public void processAllReadyEvents() {
+
+
+ boolean keepProcessing = false;
+ /*
+ do {
+ */
+ keepProcessing = doProcessEvents(sequenceId.incrementAndGet());
+ /*
+ } while (keepProcessing);
+ */
+ }
+
+ protected abstract boolean doProcessEvents(int sequenceId);
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 86a5a6d..bf92822 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -28,6 +28,8 @@ import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
import com.ning.billing.entitlement.api.IEntitlementService;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.entitlement.api.billing.IEntitlementBillingApi;
+import com.ning.billing.entitlement.api.test.EntitlementTestApi;
+import com.ning.billing.entitlement.api.test.IEntitlementTestApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.IEntitlementUserApi;
import com.ning.billing.entitlement.api.user.Subscription;
@@ -37,6 +39,7 @@ import com.ning.billing.entitlement.events.IEvent.EventType;
import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.user.IUserEvent;
+import com.ning.billing.lifecycle.IService;
import com.ning.billing.lifecycle.LyfecycleHandlerType;
import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel;
import com.ning.billing.util.clock.IClock;
@@ -53,6 +56,9 @@ public class Engine implements IEventListener, IEntitlementService {
private final IPlanAligner planAligner;
private final IEntitlementUserApi userApi;
private final IEntitlementBillingApi billingApi;
+ private final IEntitlementTestApi testApi;
+ private final IEntitlementConfig config;
+ private List<IApiListener> observers;
@Inject
@@ -100,6 +106,11 @@ public class Engine implements IEventListener, IEntitlementService {
@Override
+ public IEntitlementTestApi getTestApi() {
+ return testApi;
+ }
+
+ @Override
public void processEventReady(IEvent event) {
Subscription subscription = (Subscription) dao.getSubscriptionFromId(event.getSubscriptionId());
if (subscription == null) {
@@ -154,4 +165,5 @@ public class Engine implements IEventListener, IEntitlementService {
dao.createNextPhaseEvent(subscription.getId(), nextPhaseEvent);
}
}
+
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IApiEventProcessor.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IApiEventProcessor.java
index 2f43320..f51ae7e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IApiEventProcessor.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IApiEventProcessor.java
@@ -19,4 +19,6 @@ package com.ning.billing.entitlement.engine.core;
public interface IApiEventProcessor extends IEventNotifier {
+ public void processAllReadyEvents();
+
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
index ae2236e..5f11030 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
@@ -201,7 +201,7 @@ public abstract class TestUserApiBase {
protected Subscription createSubscription(String productName, BillingPeriod term, String planSet) throws EntitlementUserApiException {
testListener.pushExpectedEvent(NextEvent.CREATE);
- Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSet);
+ Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSet, clock.getUTCNow());
assertNotNull(subscription);
assertTrue(testListener.isCompleted(5000));
return subscription;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
index 24468fe..6a8dee2 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
@@ -17,26 +17,21 @@
package com.ning.billing.entitlement.api.user;
import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
import java.util.List;
import org.joda.time.DateTime;
import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import com.ning.billing.catalog.PriceListSet;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.IDuration;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
+import com.ning.billing.catalog.api.IPriceListSet;
import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.util.clock.Clock;
@@ -52,7 +47,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
String prod = "Shotgun";
BillingPeriod term = BillingPeriod.MONTHLY;
- String planSet = PriceListSet.DEFAULT_PRICELIST_NAME;
+ String planSet = IPriceListSet.DEFAULT_PRICELIST_NAME;
// CREATE
Subscription subscription = createSubscription(prod, term, planSet);
@@ -67,7 +62,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CANCEL);
// CANCEL in trial period to get IMM policy
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
currentPhase = subscription.getCurrentPhase();
testListener.isCompleted(1000);
@@ -91,7 +86,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
String prod = "Shotgun";
BillingPeriod term = BillingPeriod.MONTHLY;
- String planSet = PriceListSet.DEFAULT_PRICELIST_NAME;
+ String planSet = IPriceListSet.DEFAULT_PRICELIST_NAME;
// CREATE
Subscription subscription = createSubscription(prod, term, planSet);
@@ -118,7 +113,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CANCEL);
// CANCEL
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
assertFalse(testListener.isCompleted(2000));
// MOVE TO EOT + RECHECK
@@ -144,7 +139,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
String prod = "Shotgun";
BillingPeriod term = BillingPeriod.MONTHLY;
- String planSet = PriceListSet.DEFAULT_PRICELIST_NAME;
+ String planSet = IPriceListSet.DEFAULT_PRICELIST_NAME;
// CREATE
Subscription subscription = createSubscription(prod, term, planSet);
@@ -165,7 +160,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CANCEL);
// CANCEL
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
assertTrue(testListener.isCompleted(2000));
IPlanPhase currentPhase = subscription.getCurrentPhase();
@@ -188,7 +183,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
String prod = "Shotgun";
BillingPeriod term = BillingPeriod.MONTHLY;
- String planSet = PriceListSet.DEFAULT_PRICELIST_NAME;
+ String planSet = IPriceListSet.DEFAULT_PRICELIST_NAME;
// CREATE
Subscription subscription = createSubscription(prod, term, planSet);
@@ -215,7 +210,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CANCEL);
// CANCEL
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
assertFalse(testListener.isCompleted(2000));
subscription.uncancel();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
index f187d9f..373db87 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
@@ -26,23 +26,16 @@ import java.util.List;
import org.joda.time.DateTime;
import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.catalog.PriceListSet;
import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.ICatalog;
import com.ning.billing.catalog.api.IDuration;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
+import com.ning.billing.catalog.api.IPriceListSet;
import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.entitlement.events.IEvent;
-import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.user.IUserEvent;
import com.ning.billing.util.clock.Clock;
@@ -67,7 +60,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
protected void testChangePlanBundleAlignEOTWithNoChargeThroughDateReal() {
- tChangePlanBundleAlignEOTWithNoChargeThroughDate("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, "Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
+ tChangePlanBundleAlignEOTWithNoChargeThroughDate("Shotgun", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME, "Pistol", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME);
}
@@ -92,7 +85,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
// CHANGE PLAN
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan(toProd, toTerm, toPlanSet);
+ subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
assertTrue(testListener.isCompleted(2000));
// CHECK CHANGE PLAN
@@ -138,7 +131,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
// RE READ SUBSCRIPTION + CHANGE PLAN
testListener.pushExpectedEvent(NextEvent.CHANGE);
subscription = (Subscription) entitlementApi.getSubscriptionFromId(subscription.getId());
- subscription.changePlan(toProd, toTerm, toPlanSet);
+ subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
testListener.reset();
@@ -171,7 +164,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
protected void testChangePlanBundleAlignIMMReal() {
- tChangePlanBundleAlignIMM("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, "Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
+ tChangePlanBundleAlignIMM("Shotgun", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME, "Assault-Rifle", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME);
}
@@ -190,7 +183,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
clock.setDeltaFromReality(moveALittleInTime, 0);
// CHANGE PLAN IMM
- subscription.changePlan(toProd, toTerm, toPlanSet);
+ subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
checkChangePlan(subscription, toProd, ProductCategory.BASE, toTerm, PhaseType.TRIAL);
assertTrue(testListener.isCompleted(2000));
@@ -213,7 +206,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
protected void testChangePlanChangePlanAlignEOTWithChargeThroughDateReal() {
- tChangePlanChangePlanAlignEOTWithChargeThroughDate("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, "Assault-Rifle", BillingPeriod.ANNUAL, "rescue");
+ tChangePlanChangePlanAlignEOTWithChargeThroughDate("Shotgun", BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME, "Assault-Rifle", BillingPeriod.ANNUAL, "rescue");
}
private void tChangePlanChangePlanAlignEOTWithChargeThroughDate(String fromProd, BillingPeriod fromTerm, String fromPlanSet,
@@ -252,7 +245,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
currentTime = clock.getUTCNow();
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan(toProd, toTerm, toPlanSet);
+ subscription.changePlan(toProd, toTerm, toPlanSet, clock.getUTCNow());
checkChangePlan(subscription, fromProd, ProductCategory.BASE, fromTerm, PhaseType.EVERGREEN);
@@ -317,12 +310,12 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
// CHANGE EOT
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount");
+ subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
// CHANGE
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount");
+ subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
IPlan currentPlan = subscription.getCurrentPlan();
@@ -364,13 +357,13 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
// CHANGE EOT
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Shotgun", BillingPeriod.MONTHLY, "gunclubDiscount");
+ subscription.changePlan("Shotgun", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
testListener.reset();
// CHANGE EOT
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount");
+ subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
testListener.reset();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
index c8eac1f..64f69c3 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
@@ -24,16 +24,12 @@ import java.util.List;
import org.joda.time.DateTime;
import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import com.ning.billing.catalog.PriceListSet;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
+import com.ning.billing.catalog.api.IPriceListSet;
import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.entitlement.events.IEvent;
@@ -52,11 +48,11 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
String productName = "Shotgun";
BillingPeriod term = BillingPeriod.MONTHLY;
- String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+ String planSetName = IPriceListSet.DEFAULT_PRICELIST_NAME;
testListener.pushExpectedEvent(NextEvent.CREATE);
- Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName);
+ Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, clock.getUTCNow());
assertNotNull(subscription);
assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
@@ -121,7 +117,7 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CREATE);
// CREATE SUBSCRIPTION
- Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName);
+ Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, clock.getUTCNow());
assertNotNull(subscription);
IPlanPhase currentPhase = subscription.getCurrentPhase();
@@ -164,11 +160,11 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
String productName = "Shotgun";
BillingPeriod term = BillingPeriod.ANNUAL;
- String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+ String planSetName = IPriceListSet.DEFAULT_PRICELIST_NAME;
testListener.pushExpectedEvent(NextEvent.CREATE);
- Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName);
+ Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, clock.getUTCNow());
assertNotNull(subscription);
} catch (EntitlementUserApiException e) {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
index 3fb58ee..90e7cde 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
@@ -80,7 +80,7 @@ public class TestUserApiDemos extends TestUserApiBase {
/* STEP 2. CHANGE PLAN WHILE IN TRIAL */
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount");
+ subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
assertTrue(testListener.isCompleted(3000));
displayState(subscription.getId(), "STEP 2. CHANGED PLAN WHILE IN TRIAL");
@@ -103,7 +103,7 @@ public class TestUserApiDemos extends TestUserApiBase {
subscription = (Subscription) entitlementApi.getSubscriptionFromId(subscription.getId());
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Shotgun", BillingPeriod.ANNUAL, "gunclubDiscount");
+ subscription.changePlan("Shotgun", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
testListener.reset();
@@ -111,7 +111,7 @@ public class TestUserApiDemos extends TestUserApiBase {
/* STEP 5. CHANGE AGAIN */
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount");
+ subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
testListener.reset();
@@ -154,7 +154,7 @@ public class TestUserApiDemos extends TestUserApiBase {
/* STEP 8. CANCEL IMM (NO CTD) */
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
displayState(subscription.getId(), "STEP 8. CANCELLATION");
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
index 1e6f454..3d8b84f 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
@@ -33,6 +33,7 @@ import com.ning.billing.catalog.PriceListSet;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.IDuration;
import com.ning.billing.catalog.api.IPlanPhase;
+import com.ning.billing.catalog.api.IPriceListSet;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.entitlement.glue.EngineModuleMemoryMock;
import com.ning.billing.util.clock.Clock;
@@ -58,10 +59,10 @@ public class TestUserApiError extends TestUserApiBase {
@Test(enabled=true)
public void testCreateSubscriptionBadCatalog() {
// WRONG PRODUTCS
- tCreateSubscriptionInternal(bundle.getId(), null, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BAD_CATALOG);
- tCreateSubscriptionInternal(bundle.getId(), "Whatever", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BAD_CATALOG);
+ tCreateSubscriptionInternal(bundle.getId(), null, BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BAD_CATALOG);
+ tCreateSubscriptionInternal(bundle.getId(), "Whatever", BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BAD_CATALOG);
// WRONG BILLING PERIOD
- tCreateSubscriptionInternal(bundle.getId(), "Shotgun", null, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BAD_CATALOG);
+ tCreateSubscriptionInternal(bundle.getId(), "Shotgun", null, IPriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BAD_CATALOG);
// WRONG PLAN SET
tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, null, ErrorCode.ENT_CREATE_BAD_CATALOG);
tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, "Whatever", ErrorCode.ENT_CREATE_BAD_CATALOG);
@@ -70,19 +71,19 @@ public class TestUserApiError extends TestUserApiBase {
@Test(enabled=true)
public void testCreateSubscriptionNoBundle() {
- tCreateSubscriptionInternal(null, "Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_NO_BUNDLE);
+ tCreateSubscriptionInternal(null, "Shotgun", BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_NO_BUNDLE);
}
@Test(enabled=false)
public void testCreateSubscriptionNoBP() {
- //tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_NO_BP);
+ //tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_NO_BP);
}
@Test(enabled=true)
public void testCreateSubscriptionBPExists() {
try {
- createSubscription("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME);
- tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BP_EXISTS);
+ createSubscription("Shotgun", BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME);
+ tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.ENT_CREATE_BP_EXISTS);
} catch (Exception e) {
e.printStackTrace();
Assert.assertFalse(true);
@@ -92,7 +93,7 @@ public class TestUserApiError extends TestUserApiBase {
private void tCreateSubscriptionInternal(UUID bundleId, String productName,
BillingPeriod term, String planSet, ErrorCode expected) {
try {
- entitlementApi.createSubscription(bundleId, productName, term, planSet);
+ entitlementApi.createSubscription(bundleId, productName, term, planSet,clock.getUTCNow());
assertFalse(true);
} catch (EntitlementUserApiException e) {
assertEquals(e.getCode(), expected.getCode());
@@ -108,12 +109,12 @@ public class TestUserApiError extends TestUserApiBase {
@Test(enabled=true)
public void testChangeSubscriptionNonActive() {
try {
- ISubscription subscription = createSubscription("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME);
+ ISubscription subscription = createSubscription("Shotgun", BillingPeriod.ANNUAL, IPriceListSet.DEFAULT_PRICELIST_NAME);
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
try {
- subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
+ subscription.changePlan("Pistol", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow());
} catch (EntitlementUserApiException e) {
assertEquals(e.getCode(), ErrorCode.ENT_CHANGE_NON_ACTIVE.getCode());
try {
@@ -132,7 +133,7 @@ public class TestUserApiError extends TestUserApiBase {
@Test(enabled=true)
public void testChangeSubscriptionFutureCancelled() {
try {
- ISubscription subscription = createSubscription("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
+ ISubscription subscription = createSubscription("Shotgun", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME);
// SET CTD TO CANCEL IN FUTURE
IPlanPhase trialPhase = subscription.getCurrentPhase();
@@ -142,9 +143,9 @@ public class TestUserApiError extends TestUserApiBase {
billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
subscription = entitlementApi.getSubscriptionFromId(subscription.getId());
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
try {
- subscription.changePlan("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
+ subscription.changePlan("Pistol", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow());
} catch (EntitlementUserApiException e) {
assertEquals(e.getCode(), ErrorCode.ENT_CHANGE_FUTURE_CANCELLED.getCode());
try {
@@ -167,7 +168,7 @@ public class TestUserApiError extends TestUserApiBase {
@Test(enabled=true)
public void testUncancelBadState() {
try {
- ISubscription subscription = createSubscription("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
+ ISubscription subscription = createSubscription("Shotgun", BillingPeriod.MONTHLY, IPriceListSet.DEFAULT_PRICELIST_NAME);
try {
subscription.uncancel();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
index 7f3dbba..78e7cb3 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
@@ -53,7 +53,7 @@ public class TestUserApiScenarios extends TestUserApiBase {
assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount");
+ subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount", clock.getUTCNow());
testListener.isCompleted(3000);
// MOVE TO NEXT PHASE
@@ -70,7 +70,7 @@ public class TestUserApiScenarios extends TestUserApiBase {
// CANCEL EOT
testListener.pushExpectedEvent(NextEvent.CANCEL);
- subscription.cancel();
+ subscription.cancel(clock.getUTCNow(), false);
assertFalse(testListener.isCompleted(2000));
testListener.reset();
@@ -79,7 +79,7 @@ public class TestUserApiScenarios extends TestUserApiBase {
// CHANGE EOT
testListener.pushExpectedEvent(NextEvent.CHANGE);
- subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount");
+ subscription.changePlan("Pistol", BillingPeriod.MONTHLY, "gunclubDiscount", clock.getUTCNow());
assertFalse(testListener.isCompleted(2000));
clock.addDeltaFromReality(ctd);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java
index 38aed83..79aef55 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java
@@ -34,9 +34,12 @@ public class ApiEventProcessorMemoryMock extends ApiEventProcessorBase {
@Override
- protected void doProcessEvents(int sequenceId) {
+ protected boolean doProcessEvents(int sequenceId) {
List<IEvent> events = dao.getEventsReady(apiProcessorId, sequenceId);
+ if (events.size() == 0) {
+ return false;
+ }
log.info(String.format("doProcessEvents : Got %d event(s)", events.size() ));
for (IEvent cur : events) {
log.info(String.format("doProcessEvents : (clock = %s) CALLING Engine with event %s", clock.getUTCNow(), cur));
@@ -46,5 +49,6 @@ public class ApiEventProcessorMemoryMock extends ApiEventProcessorBase {
}
dao.clearEventsReady(apiProcessorId, events);
log.info(String.format("doProcessEvents : clearEvents"));
+ return true;
}
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java
index cd6da83..b2dee60 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java
@@ -30,6 +30,7 @@ import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.IPlan;
+import com.ning.billing.catalog.api.IPriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.TestUserApiBase;
@@ -102,7 +103,7 @@ public class TestEntitlementDao extends TestUserApiBase {
String productName = "Shotgun";
BillingPeriod term = BillingPeriod.MONTHLY;
- String planSetName = "standard";
+ String planSetName = IPriceListSet.DEFAULT_PRICELIST_NAME;
IPlan plan = catalog.getPlan(productName, term, planSetName);
final IEvent event = new ApiEventCreate(UUID.randomUUID(), now, now, plan.getName(), "evergreen", planSetName, now, now, 1);
diff --git a/entitlement/src/test/resources/testInput.xml b/entitlement/src/test/resources/testInput.xml
index e9c041b..cfd445b 100644
--- a/entitlement/src/test/resources/testInput.xml
+++ b/entitlement/src/test/resources/testInput.xml
@@ -152,6 +152,10 @@ Use Cases to do:
<productCategory>ADD_ON</productCategory>
<alignment>BUNDLE</alignment>
</billingAlignmentCase>
+ <priceListCase>
+ <fromPriceList>rescue</fromPriceList>
+ <toPriceList>DEFAULT</toPriceList>
+ </priceListCase>
</rules>
<plans>
@@ -549,7 +553,7 @@ Use Cases to do:
</plan>
</plans>
<priceLists>
- <defaultPriceList>
+ <defaultPriceList name="DEFAULT">
<plans>
<plan>pistol-monthly</plan>
<plan>shotgun-monthly</plan>
invoice/pom.xml 2(+1 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 6840bf4..3e589ad 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-invoice</artifactId>
payment/pom.xml 2(+1 -1)
diff --git a/payment/pom.xml b/payment/pom.xml
index 84ff329..b902c81 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 83ec479..bf8e215 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
<packaging>pom</packaging>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-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 8d1fd74..ba9caa9 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.10-SNAPSHOT</version>
+ <version>0.0.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>
diff --git a/util/src/main/java/com/ning/billing/util/config/XMLWriter.java b/util/src/main/java/com/ning/billing/util/config/XMLWriter.java
index 3f16e90..58e42dd 100644
--- a/util/src/main/java/com/ning/billing/util/config/XMLWriter.java
+++ b/util/src/main/java/com/ning/billing/util/config/XMLWriter.java
@@ -27,6 +27,7 @@ public class XMLWriter<T> {
public static <T> String writeXML(T object, Class<T> type) throws Exception {
JAXBContext context =JAXBContext.newInstance(type);
Marshaller marshaller = context.createMarshaller();
+ marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
ByteArrayOutputStream output = new ByteArrayOutputStream(MAX_XML_SIZE_IN_BYTES);
marshaller.marshal(object, output);
diff --git a/util/src/test/java/com/ning/billing/util/config/TestXMLWriter.java b/util/src/test/java/com/ning/billing/util/config/TestXMLWriter.java
index f9115a0..007c16b 100644
--- a/util/src/test/java/com/ning/billing/util/config/TestXMLWriter.java
+++ b/util/src/test/java/com/ning/billing/util/config/TestXMLWriter.java
@@ -45,7 +45,7 @@ public class TestXMLWriter {
String output = XMLWriter.writeXML(test, XmlTestClass.class);
System.out.println(output);
- assertEquals(output, TEST_XML);
+ assertEquals(output.replaceAll("\\s", ""), TEST_XML.replaceAll("\\s", ""));
}