killbill-memoizeit
Changes
account/pom.xml 2(+1 -1)
analytics/pom.xml 2(+1 -1)
analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java 17(+13 -4)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java 5(+5 -0)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java 59(+31 -28)
analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg 9(+9 -0)
analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java 26(+13 -13)
api/pom.xml 2(+1 -1)
beatrix/pom.xml 2(+1 -1)
catalog/pom.xml 2(+1 -1)
entitlement/pom.xml 2(+1 -1)
entitlement/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java 16(+4 -12)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBuilder.java 124(+124 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java 35(+22 -13)
entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java 88(+79 -9)
entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/ISubscriptionSqlDao.java 15(+12 -3)
entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.java 41(+41 -0)
entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.sql.stg 13(+13 -0)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java 5(+5 -0)
entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java 9(+9 -0)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java 22(+19 -3)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java 148(+0 -148)
invoice/pom.xml 2(+1 -1)
payment/pom.xml 2(+1 -1)
pom.xml 40(+24 -16)
util/pom.xml 2(+1 -1)
Details
account/pom.xml 2(+1 -1)
diff --git a/account/pom.xml b/account/pom.xml
index d388d5e..3443aac 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.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
diff --git a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
index 24ca0a3..b4583ec 100644
--- a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
+++ b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
@@ -25,6 +25,7 @@ import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.FieldStoreDao;
import com.ning.billing.account.dao.IAccountDao;
import com.ning.billing.account.dao.IFieldStoreDao;
+
import org.skife.config.ConfigurationObjectFactory;
public class AccountModule extends AbstractModule {
@@ -51,6 +52,11 @@ public class AccountModule extends AbstractModule {
bind(IFieldStoreDao.class).to(FieldStoreDao.class).asEagerSingleton();
}
+ protected void installInjectorMagic() {
+ bind(InjectorMagic.class).asEagerSingleton();
+ }
+
+
@Override
protected void configure() {
installConfig();
@@ -58,6 +64,7 @@ public class AccountModule extends AbstractModule {
installAccountUserApi();
installAccountService();
installFieldStore();
+ installInjectorMagic();
}
}
analytics/pom.xml 2(+1 -1)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index 0ead039..498b3c0 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.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-analytics</artifactId>
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 558d7f4..5602fe8 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
@@ -54,6 +54,7 @@ public class BusinessSubscription
private final String phase;
private final String billingPeriod;
private final BigDecimal price;
+ private final String priceList;
private final BigDecimal mrr;
private final String currency;
private final DateTime startDate;
@@ -61,7 +62,7 @@ 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 String billingPeriod, 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 String priceList, final BigDecimal mrr, final String currency, final DateTime startDate, final SubscriptionState state, final UUID subscriptionId, final UUID bundleId)
{
this.productName = productName;
this.productType = productType;
@@ -70,6 +71,7 @@ public class BusinessSubscription
this.phase = phase;
this.billingPeriod = billingPeriod;
this.price = price;
+ this.priceList = priceList;
this.mrr = mrr;
this.currency = currency;
this.startDate = startDate;
@@ -89,11 +91,13 @@ public class BusinessSubscription
*/
BusinessSubscription(final ISubscription subscription, final Currency currency)
{
- this(subscription.getCurrentPlan(), subscription.getCurrentPhase(), currency, subscription.getStartDate(), subscription.getState(), subscription.getId(), subscription.getBundleId());
+ this(subscription.getCurrentPriceList(), subscription.getCurrentPlan(), subscription.getCurrentPhase(), currency, subscription.getStartDate(), subscription.getState(), subscription.getId(), subscription.getBundleId());
}
- public BusinessSubscription(final IPlan currentPlan, final IPlanPhase currentPhase, final Currency currency, final DateTime startDate, final SubscriptionState state, final UUID subscriptionId, final UUID bundleId)
+ public BusinessSubscription(final String priceList, final IPlan currentPlan, final IPlanPhase currentPhase, final Currency currency, final DateTime startDate, final SubscriptionState state, final UUID subscriptionId, final UUID bundleId)
{
+ this.priceList = priceList;
+
// Record plan information
if (currentPlan != null && currentPlan.getProduct() != null) {
final IProduct product = currentPlan.getProduct();
@@ -114,10 +118,15 @@ public class BusinessSubscription
if (currentPhase.getPhaseType() != null) {
phase = currentPhase.getPhaseType().toString();
- billingPeriod = currentPhase.getBillingPeriod().toString();
}
else {
phase = null;
+ }
+
+ if (currentPhase.getBillingPeriod() != null) {
+ billingPeriod = currentPhase.getBillingPeriod().toString();
+ }
+ else {
billingPeriod = null;
}
@@ -193,6 +202,11 @@ public class BusinessSubscription
return price;
}
+ public String getPriceList()
+ {
+ return priceList;
+ }
+
public double getRoundedPrice()
{
return Rounder.round(price);
@@ -269,6 +283,7 @@ public class BusinessSubscription
sb.append(", slug='").append(slug).append('\'');
sb.append(", phase='").append(phase).append('\'');
sb.append(", price=").append(price);
+ sb.append(", priceList=").append(priceList);
sb.append(", mrr=").append(mrr);
sb.append(", currency='").append(currency).append('\'');
sb.append(", startDate=").append(startDate);
@@ -309,6 +324,9 @@ public class BusinessSubscription
if (price != null ? !(Rounder.round(price) == Rounder.round(that.price)) : that.price != null) {
return false;
}
+ if (priceList != null ? !priceList.equals(that.priceList) : that.priceList != null) {
+ return false;
+ }
if (productCategory != null ? !productCategory.equals(that.productCategory) : that.productCategory != null) {
return false;
}
@@ -343,6 +361,7 @@ public class BusinessSubscription
result = 31 * result + (slug != null ? slug.hashCode() : 0);
result = 31 * result + (phase != null ? phase.hashCode() : 0);
result = 31 * result + (price != null ? price.hashCode() : 0);
+ result = 31 * result + (priceList != null ? priceList.hashCode() : 0);
result = 31 * result + (mrr != null ? mrr.hashCode() : 0);
result = 31 * result + (currency != null ? currency.hashCode() : 0);
result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java
index b37e45a..8da7ff0 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java
@@ -26,16 +26,20 @@ import org.joda.time.DateTime;
public class BusinessSubscriptionTransition
{
private final String key;
+ private final String accountKey;
private final DateTime requestedTimestamp;
private final BusinessSubscriptionEvent event;
private final BusinessSubscription previousSubscription;
private final BusinessSubscription nextSubscription;
- public BusinessSubscriptionTransition(final String key, final DateTime requestedTimestamp, final BusinessSubscriptionEvent event, final BusinessSubscription previousSubscription, final BusinessSubscription nextsubscription)
+ public BusinessSubscriptionTransition(final String key, final String accountKey, final DateTime requestedTimestamp, final BusinessSubscriptionEvent event, final BusinessSubscription previousSubscription, final BusinessSubscription nextsubscription)
{
if (key == null) {
throw new IllegalArgumentException("An event must have an key");
}
+ if (accountKey == null) {
+ throw new IllegalArgumentException("An event must have an account key");
+ }
if (requestedTimestamp == null) {
throw new IllegalArgumentException("An event must have a requestedTimestamp");
}
@@ -44,6 +48,7 @@ public class BusinessSubscriptionTransition
}
this.key = key;
+ this.accountKey = accountKey;
this.requestedTimestamp = requestedTimestamp;
this.event = event;
this.previousSubscription = previousSubscription;
@@ -60,6 +65,11 @@ public class BusinessSubscriptionTransition
return key;
}
+ public String getAccountKey()
+ {
+ return accountKey;
+ }
+
public BusinessSubscription getNextSubscription()
{
return nextSubscription;
@@ -82,6 +92,7 @@ public class BusinessSubscriptionTransition
sb.append("BusinessSubscriptionTransition");
sb.append("{event=").append(event);
sb.append(", key='").append(key).append('\'');
+ sb.append(", accountKey='").append(accountKey).append('\'');
sb.append(", requestedTimestamp=").append(requestedTimestamp);
sb.append(", previousSubscription=").append(previousSubscription);
sb.append(", nextSubscription=").append(nextSubscription);
@@ -107,6 +118,9 @@ public class BusinessSubscriptionTransition
if (key != null ? !key.equals(that.key) : that.key != null) {
return false;
}
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
if (nextSubscription != null ? !nextSubscription.equals(that.nextSubscription) : that.nextSubscription != null) {
return false;
}
@@ -124,6 +138,7 @@ public class BusinessSubscriptionTransition
public int hashCode()
{
int result = key != null ? key.hashCode() : 0;
+ result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
result = 31 * result + (requestedTimestamp != null ? requestedTimestamp.hashCode() : 0);
result = 31 * result + (event != null ? event.hashCode() : 0);
result = 31 * result + (previousSubscription != null ? previousSubscription.hashCode() : 0);
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
index c3ecc70..fd57a06 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
@@ -86,6 +86,7 @@ public class BusinessSubscriptionTransitionRecorder
{
Currency currency = null;
String transitionKey = null;
+ String accountKey = null;
// Retrieve key and currency via the bundle
final ISubscriptionBundle bundle = entitlementApi.getBundleFromId(transition.getBundleId());
@@ -94,6 +95,7 @@ public class BusinessSubscriptionTransitionRecorder
final IAccount account = accountApi.getAccountFromId(bundle.getAccountId());
if (account != null) {
+ accountKey = account.getKey();
currency = account.getCurrency();
}
}
@@ -110,17 +112,24 @@ public class BusinessSubscriptionTransitionRecorder
}
// TODO Support currency changes
- final BusinessSubscription prevSubscription = new BusinessSubscription(transition.getPreviousPlan(), transition.getPreviousPhase(), currency, previousEffectiveTransitionTime, transition.getPreviousState(), transition.getSubscriptionId(), transition.getBundleId());
- final BusinessSubscription nextSubscription = new BusinessSubscription(transition.getNextPlan(), transition.getNextPhase(), currency, transition.getEffectiveTransitionTime(), transition.getNextState(), transition.getSubscriptionId(), transition.getBundleId());
+ final BusinessSubscription prevSubscription;
+ if (previousEffectiveTransitionTime == null) {
+ prevSubscription = null;
+ }
+ else {
+ prevSubscription = new BusinessSubscription(transition.getPreviousPriceList(), transition.getPreviousPlan(), transition.getPreviousPhase(), currency, previousEffectiveTransitionTime, transition.getPreviousState(), transition.getSubscriptionId(), transition.getBundleId());
+ }
+ final BusinessSubscription nextSubscription = new BusinessSubscription(transition.getNextPriceList(), transition.getNextPlan(), transition.getNextPhase(), currency, transition.getEffectiveTransitionTime(), transition.getNextState(), transition.getSubscriptionId(), transition.getBundleId());
- record(transitionKey, transition.getRequestedTransitionTime(), event, prevSubscription, nextSubscription);
+ record(transitionKey, accountKey, transition.getRequestedTransitionTime(), event, prevSubscription, nextSubscription);
}
// Public for internal reasons
- public void record(final String key, final DateTime requestedDateTime, final BusinessSubscriptionEvent event, final BusinessSubscription prevSubscription, final BusinessSubscription nextSubscription)
+ public void record(final String key, final String accountKey, final DateTime requestedDateTime, final BusinessSubscriptionEvent event, final BusinessSubscription prevSubscription, final BusinessSubscription nextSubscription)
{
final BusinessSubscriptionTransition transition = new BusinessSubscriptionTransition(
key,
+ accountKey,
requestedDateTime,
event,
prevSubscription,
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 ccf2a2b..374f296 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
@@ -44,6 +44,7 @@ public @interface BusinessSubscriptionTransitionBinder
public void bind(final SQLStatement q, final BusinessSubscriptionTransitionBinder bind, final BusinessSubscriptionTransition arg)
{
q.bind("event_key", arg.getKey());
+ q.bind("account_key", arg.getAccountKey());
q.bind("requested_timestamp", arg.getRequestedTimestamp().getMillis());
q.bind("event", arg.getEvent().toString());
@@ -56,6 +57,7 @@ public @interface BusinessSubscriptionTransitionBinder
q.bindNull("prev_phase", Types.VARCHAR);
q.bindNull("prev_billing_period", Types.VARCHAR);
q.bindNull("prev_price", Types.NUMERIC);
+ q.bindNull("prev_price_list", Types.VARCHAR);
q.bindNull("prev_mrr", Types.NUMERIC);
q.bindNull("prev_currency", Types.VARCHAR);
q.bindNull("prev_start_date", Types.BIGINT);
@@ -76,6 +78,7 @@ public @interface BusinessSubscriptionTransitionBinder
q.bind("prev_phase", previousSubscription.getPhase());
q.bind("prev_billing_period", previousSubscription.getBillingPeriod());
q.bind("prev_price", previousSubscription.getRoundedPrice());
+ q.bind("prev_price_list", previousSubscription.getPriceList());
q.bind("prev_mrr", previousSubscription.getRoundedMrr());
q.bind("prev_currency", previousSubscription.getCurrency());
if (previousSubscription.getStartDate() == null) {
@@ -113,6 +116,7 @@ public @interface BusinessSubscriptionTransitionBinder
q.bindNull("next_phase", Types.VARCHAR);
q.bindNull("next_billing_period", Types.VARCHAR);
q.bindNull("next_price", Types.NUMERIC);
+ q.bindNull("next_price_list", Types.VARCHAR);
q.bindNull("next_mrr", Types.NUMERIC);
q.bindNull("next_currency", Types.VARCHAR);
q.bindNull("next_start_date", Types.BIGINT);
@@ -133,6 +137,7 @@ public @interface BusinessSubscriptionTransitionBinder
q.bind("next_phase", nextSubscription.getPhase());
q.bind("next_billing_period", nextSubscription.getBillingPeriod());
q.bind("next_price", nextSubscription.getRoundedPrice());
+ q.bind("next_price_list", nextSubscription.getPriceList());
q.bind("next_mrr", nextSubscription.getRoundedMrr());
q.bind("next_currency", nextSubscription.getCurrency());
if (nextSubscription.getStartDate() == null) {
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 55aedb9..fb5e641 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
@@ -38,19 +38,20 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
public BusinessSubscriptionTransition map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException
{
BusinessSubscription prev = new BusinessSubscription(
- r.getString(4), // productName
- r.getString(5), // productType
- r.getString(6) == null ? null : ProductCategory.valueOf(r.getString(6)), // productCategory
- r.getString(7), // slug
- r.getString(8), // phase
- 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
+ r.getString(5), // productName
+ r.getString(6), // productType
+ r.getString(7) == null ? null : ProductCategory.valueOf(r.getString(7)), // productCategory
+ r.getString(8), // slug
+ r.getString(9), // phase
+ r.getString(10), // billing period
+ BigDecimal.valueOf(r.getDouble(11)), // price
+ r.getString(12), // priceList
+ BigDecimal.valueOf(r.getDouble(13)), // mrr
+ r.getString(14), // currency
+ r.getLong(15) == 0 ? null : new DateTime(r.getLong(15), DateTimeZone.UTC), // startDate
+ r.getString(16) == null ? null : SubscriptionState.valueOf(r.getString(16)), // state
+ r.getString(17) == null ? null : UUID.fromString(r.getString(17)), // subscriptionId
+ r.getString(18) == null ? null : UUID.fromString(r.getString(18)) //bundleId
);
// Avoid creating a dummy subscriptions with all null fields
@@ -59,19 +60,20 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
}
BusinessSubscription next = new BusinessSubscription(
- 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
+ r.getString(19), // productName
+ r.getString(20), // productType
+ r.getString(21) == null ? null : ProductCategory.valueOf(r.getString(21)), // productCategory
+ r.getString(22), // slug8
+ r.getString(23), // phase
+ r.getString(24), // billing period
+ BigDecimal.valueOf(r.getDouble(25)), // price
+ r.getString(26), // priceList
+ BigDecimal.valueOf(r.getDouble(27)), // mrr
+ r.getString(28), // currency
+ r.getLong(29) == 0 ? null : new DateTime(r.getLong(29), DateTimeZone.UTC), // startDate
+ r.getString(30) == null ? null : SubscriptionState.valueOf(r.getString(30)), // state
+ r.getString(31) == null ? null : UUID.fromString(r.getString(31)), // subscriptionId
+ r.getString(32) == null ? null : UUID.fromString(r.getString(32)) //bundleId
);
// Avoid creating a dummy subscriptions with all null fields
@@ -79,11 +81,12 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
next = null;
}
- final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf(r.getString(3));
+ final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf(r.getString(4));
return new BusinessSubscriptionTransition(
r.getString(1),
- new DateTime(r.getLong(2), DateTimeZone.UTC),
+ r.getString(2),
+ new DateTime(r.getLong(3), DateTimeZone.UTC),
event,
prev,
next
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg
index 11e160a..1654b5b 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg
+++ b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg
@@ -3,6 +3,7 @@ group BusinessSubscriptionTransition;
getTransitions(event_key) ::= <<
select
event_key
+ , account_key
, requested_timestamp
, event
, prev_product_name
@@ -12,6 +13,7 @@ getTransitions(event_key) ::= <<
, prev_phase
, prev_billing_period
, prev_price
+ , prev_price_list
, prev_mrr
, prev_currency
, prev_start_date
@@ -25,6 +27,7 @@ getTransitions(event_key) ::= <<
, next_phase
, next_billing_period
, next_price
+ , next_price_list
, next_mrr
, next_currency
, next_start_date
@@ -40,6 +43,7 @@ getTransitions(event_key) ::= <<
createTransition() ::= <<
insert into bst(
event_key
+ , account_key
, requested_timestamp
, event
, prev_product_name
@@ -49,6 +53,7 @@ createTransition() ::= <<
, prev_phase
, prev_billing_period
, prev_price
+ , prev_price_list
, prev_mrr
, prev_currency
, prev_start_date
@@ -62,6 +67,7 @@ createTransition() ::= <<
, next_phase
, next_billing_period
, next_price
+ , next_price_list
, next_mrr
, next_currency
, next_start_date
@@ -70,6 +76,7 @@ createTransition() ::= <<
, next_bundle_id
) values (
:event_key
+ , :account_key
, :requested_timestamp
, :event
, :prev_product_name
@@ -79,6 +86,7 @@ createTransition() ::= <<
, :prev_phase
, :prev_billing_period
, :prev_price
+ , :prev_price_list
, :prev_mrr
, :prev_currency
, :prev_start_date
@@ -92,6 +100,7 @@ createTransition() ::= <<
, :next_phase
, :next_billing_period
, :next_price
+ , :next_price_list
, :next_mrr
, :next_currency
, :next_start_date
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 908715a..49e48f0 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
+++ b/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
@@ -1,6 +1,7 @@
drop table if exists bst;
create table bst (
event_key varchar(50) not null
+, account_key varchar(50) not null
, requested_timestamp bigint not null
, event varchar(50) not null
, prev_product_name varchar(32) default null
@@ -10,6 +11,7 @@ create table bst (
, prev_phase varchar(32) default null
, prev_billing_period varchar(32) default null
, prev_price numeric(10, 4) default 0
+, prev_price_list varchar(32) default null
, prev_mrr numeric(10, 4) default 0
, prev_currency varchar(32) default null
, prev_start_date bigint default null
@@ -23,6 +25,7 @@ create table bst (
, next_phase varchar(32) default null
, next_billing_period varchar(32) default null
, next_price numeric(10, 4) default 0
+, next_price_list varchar(32) default null
, next_mrr numeric(10, 4) default 0
, next_currency varchar(32) default null
, next_start_date bigint default null
diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index aae04e7..faaf2b2 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -17,6 +17,8 @@
package com.ning.billing.analytics.api;
import com.google.inject.Inject;
+import com.ning.billing.account.api.IAccount;
+import com.ning.billing.account.api.IAccountUserApi;
import com.ning.billing.analytics.AnalyticsTestModule;
import com.ning.billing.analytics.BusinessSubscription;
import com.ning.billing.analytics.BusinessSubscriptionEvent;
@@ -27,6 +29,7 @@ import com.ning.billing.analytics.MockPhase;
import com.ning.billing.analytics.MockPlan;
import com.ning.billing.analytics.MockProduct;
import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDao;
+import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
import com.ning.billing.catalog.api.IProduct;
@@ -59,6 +62,10 @@ import java.util.UUID;
public class TestAnalyticsService
{
private static final String KEY = "1234";
+ private static final String ACCOUNT_KEY = "pierre-1234";
+
+ @Inject
+ private IAccountUserApi accountApi;
@Inject
private IEntitlementUserApi entitlementApi;
@@ -92,7 +99,9 @@ public class TestAnalyticsService
helper.initDb(entitlementDdl);
// We need a bundle to retrieve the event key
- final ISubscriptionBundle bundle = entitlementApi.createBundleForAccount(new MockAccount(KEY), KEY);
+ final MockAccount account = new MockAccount(UUID.randomUUID(), ACCOUNT_KEY, Currency.USD);
+ final IAccount storedAccount = accountApi.createAccount(account);
+ final ISubscriptionBundle bundle = entitlementApi.createBundleForAccount(storedAccount, KEY);
// Verify we correctly initialized the account subsystem
Assert.assertNotNull(bundle);
@@ -105,7 +114,9 @@ public class TestAnalyticsService
final UUID subscriptionId = UUID.randomUUID();
final DateTime effectiveTransitionTime = new DateTime(DateTimeZone.UTC);
final DateTime requestedTransitionTime = new DateTime(DateTimeZone.UTC);
+ final String priceList = "something";
transition = new SubscriptionTransition(
+ UUID.randomUUID(),
subscriptionId,
bundle.getId(),
IEvent.EventType.API_USER,
@@ -119,14 +130,15 @@ public class TestAnalyticsService
ISubscription.SubscriptionState.ACTIVE,
plan,
phase,
- "something"
+ priceList
);
expectedTransition = new BusinessSubscriptionTransition(
KEY,
+ ACCOUNT_KEY,
requestedTransitionTime,
BusinessSubscriptionEvent.subscriptionCreated(plan),
null,
- new BusinessSubscription(plan, phase, null, effectiveTransitionTime, ISubscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
+ new BusinessSubscription(priceList, plan, phase, null, effectiveTransitionTime, ISubscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
);
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
index defdcef..81c71c5 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
@@ -79,12 +79,12 @@ public class TestAnalyticsDao
private void setupBusinessSubscriptionTransition()
{
- final BusinessSubscription prevSubscription = new BusinessSubscription(plan, phase, Currency.USD, new DateTime(DateTimeZone.UTC), ISubscription.SubscriptionState.ACTIVE, UUID.randomUUID(), UUID.randomUUID());
- final BusinessSubscription nextSubscription = new BusinessSubscription(plan, phase, Currency.USD, new DateTime(DateTimeZone.UTC), ISubscription.SubscriptionState.CANCELLED, UUID.randomUUID(), UUID.randomUUID());
+ final BusinessSubscription prevSubscription = new BusinessSubscription(null, plan, phase, Currency.USD, new DateTime(DateTimeZone.UTC), ISubscription.SubscriptionState.ACTIVE, UUID.randomUUID(), UUID.randomUUID());
+ final BusinessSubscription nextSubscription = new BusinessSubscription(null, plan, phase, Currency.USD, new DateTime(DateTimeZone.UTC), ISubscription.SubscriptionState.CANCELLED, UUID.randomUUID(), UUID.randomUUID());
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(plan);
final DateTime requestedTimestamp = new DateTime(DateTimeZone.UTC);
- transition = new BusinessSubscriptionTransition(EVENT_KEY, requestedTimestamp, event, prevSubscription, nextSubscription);
+ transition = new BusinessSubscriptionTransition(EVENT_KEY, ACCOUNT_KEY, requestedTimestamp, event, prevSubscription, nextSubscription);
final IDBI dbi = helper.getDBI();
businessSubscriptionTransitionDao = dbi.onDemand(BusinessSubscriptionTransitionDao.class);
@@ -134,6 +134,7 @@ public class TestAnalyticsDao
{
final BusinessSubscriptionTransition transitionWithNullPrev = new BusinessSubscriptionTransition(
transition.getKey(),
+ transition.getAccountKey(),
transition.getRequestedTimestamp(),
transition.getEvent(),
null,
@@ -151,6 +152,7 @@ public class TestAnalyticsDao
{
final BusinessSubscriptionTransition transitionWithNullNext = new BusinessSubscriptionTransition(
transition.getKey(),
+ transition.getAccountKey(),
transition.getRequestedTimestamp(),
transition.getEvent(),
transition.getPreviousSubscription(),
@@ -166,9 +168,10 @@ public class TestAnalyticsDao
@Test(groups = "slow")
public void testTransitionsWithNullFieldsInSubscription()
{
- final BusinessSubscription subscriptionWithNullFields = new BusinessSubscription(plan, phase, Currency.USD, null, null, null, null);
+ final BusinessSubscription subscriptionWithNullFields = new BusinessSubscription(null, plan, phase, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullFields = new BusinessSubscriptionTransition(
transition.getKey(),
+ transition.getAccountKey(),
transition.getRequestedTimestamp(),
transition.getEvent(),
subscriptionWithNullFields,
@@ -184,9 +187,10 @@ public class TestAnalyticsDao
@Test(groups = "slow")
public void testTransitionsWithNullPlanAndPhase() throws Exception
{
- final BusinessSubscription subscriptionWithNullPlanAndPhase = new BusinessSubscription(null, null, Currency.USD, null, null, null, null);
+ final BusinessSubscription subscriptionWithNullPlanAndPhase = new BusinessSubscription(null, null, null, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullPlanAndPhase = new BusinessSubscriptionTransition(
transition.getKey(),
+ transition.getAccountKey(),
transition.getRequestedTimestamp(),
transition.getEvent(),
subscriptionWithNullPlanAndPhase,
@@ -207,9 +211,10 @@ public class TestAnalyticsDao
@Test(groups = "slow")
public void testTransitionsWithNullPlan() throws Exception
{
- final BusinessSubscription subscriptionWithNullPlan = new BusinessSubscription(null, phase, Currency.USD, null, null, null, null);
+ final BusinessSubscription subscriptionWithNullPlan = new BusinessSubscription(null, null, phase, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullPlan = new BusinessSubscriptionTransition(
transition.getKey(),
+ transition.getAccountKey(),
transition.getRequestedTimestamp(),
transition.getEvent(),
subscriptionWithNullPlan,
@@ -226,9 +231,10 @@ public class TestAnalyticsDao
@Test(groups = "slow")
public void testTransitionsWithNullPhase() throws Exception
{
- final BusinessSubscription subscriptionWithNullPhase = new BusinessSubscription(plan, null, Currency.USD, null, null, null, null);
+ final BusinessSubscription subscriptionWithNullPhase = new BusinessSubscription(null, plan, null, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullPhase = new BusinessSubscriptionTransition(
transition.getKey(),
+ transition.getAccountKey(),
transition.getRequestedTimestamp(),
transition.getEvent(),
subscriptionWithNullPhase,
@@ -243,7 +249,7 @@ public class TestAnalyticsDao
Assert.assertEquals(transitions.get(0).getEvent(), transition.getEvent());
// Null Phase but Plan - we don't turn the subscription into a null, however price and mrr are both set to 0 (not null)
- final BusinessSubscription blankSubscription = new BusinessSubscription(plan, new MockPhase(null, null, null, 0.0), Currency.USD, null, null, null, null);
+ final BusinessSubscription blankSubscription = new BusinessSubscription(null, plan, new MockPhase(null, null, null, 0.0), Currency.USD, null, null, null, null);
Assert.assertEquals(transitions.get(0).getPreviousSubscription(), blankSubscription);
Assert.assertEquals(transitions.get(0).getNextSubscription(), blankSubscription);
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
index c2ab5fd..f22f7b9 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
@@ -23,73 +23,80 @@ import java.util.UUID;
public class MockAccount implements IAccount
{
- private final String key;
+ private final UUID id;
+ private final String accountKey;
+ private final Currency currency;
- public MockAccount(final String key)
+ public MockAccount(final UUID id, final String accountKey, final Currency currency)
{
- this.key = key;
+ this.id = id;
+ this.accountKey = accountKey;
+ this.currency = currency;
}
@Override
public String getName()
{
- return "accountName";
+ throw new UnsupportedOperationException();
}
@Override
public String getEmail()
{
- return "accountName@yahoo.com";
+ throw new UnsupportedOperationException();
}
@Override
public String getPhone()
{
- return "4152876341";
+ throw new UnsupportedOperationException();
}
@Override
public String getKey()
{
- return key;
+ return accountKey;
}
@Override
public int getBillCycleDay()
{
- return 1;
+ throw new UnsupportedOperationException();
}
@Override
public Currency getCurrency()
{
- return Currency.USD;
+ return currency;
}
@Override
public UUID getId()
{
- return UUID.randomUUID();
+ return id;
}
@Override
public void load()
{
+ throw new UnsupportedOperationException();
}
@Override
public void save()
{
+ throw new UnsupportedOperationException();
}
@Override
public String getFieldValue(final String fieldName)
{
- return null;
+ throw new UnsupportedOperationException();
}
@Override
public void setFieldValue(final String fieldName, final String fieldValue)
{
+ throw new UnsupportedOperationException();
}
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
index 64fe29f..ccd67af 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
@@ -19,12 +19,20 @@ package com.ning.billing.analytics;
import com.ning.billing.account.api.IAccount;
import com.ning.billing.account.api.IAccountData;
import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.catalog.api.Currency;
import java.util.List;
import java.util.UUID;
public class MockIAccountUserApi implements IAccountUserApi
{
+ private final MockAccount account;
+
+ public MockIAccountUserApi(final String accountKey, final Currency currency)
+ {
+ account = new MockAccount(UUID.randomUUID(), accountKey, currency);
+ }
+
@Override
public IAccount createAccount(final IAccountData data)
{
@@ -40,7 +48,7 @@ public class MockIAccountUserApi implements IAccountUserApi
@Override
public IAccount getAccountFromId(final UUID uid)
{
- return null;
+ return account;
}
@Override
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
index 4ed2e8c..1aabb67 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
@@ -115,4 +115,9 @@ public class MockIEntitlementUserApi implements IEntitlementUserApi
{
throw new UnsupportedOperationException();
}
+
+ @Override
+ public List<ISubscription> getSubscriptionsForKey(String bundleKey) {
+ throw new UnsupportedOperationException();
+ }
}
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 2303e1d..bf71b41 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
@@ -96,7 +96,7 @@ public class MockPhase implements IPlanPhase
@Override
public BillingPeriod getBillingPeriod()
{
- return BillingPeriod.MONTHLY;
+ return null;
}
@Override
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java b/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
index 958de9a..57e0b5b 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
@@ -50,15 +50,15 @@ public class MockProduct implements IProduct
return category;
}
- @Override
- public IProduct[] getAvailable() {
- // TODO Auto-generated method stub
- return null;
- }
+ @Override
+ public IProduct[] getAvailable()
+ {
+ return null;
+ }
- @Override
- public IProduct[] getIncluded() {
- // TODO Auto-generated method stub
- return null;
- }
+ @Override
+ public IProduct[] getIncluded()
+ {
+ return null;
+ }
}
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 e208852..a756447 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -124,6 +124,11 @@ public class MockSubscription implements ISubscription
@Override
public String getCurrentPriceList()
{
- throw new UnsupportedOperationException();
+ return null;
+ }
+
+ @Override
+ public DateTime getEndDate() {
+ return null;
}
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
index 9f13e2e..c0c93aa 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -16,6 +16,7 @@
package com.ning.billing.analytics;
+import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
import com.ning.billing.catalog.api.IProduct;
@@ -36,6 +37,8 @@ import java.util.UUID;
public class TestAnalyticsListener
{
private static final String KEY = "1234";
+ private static final String ACCOUNT_KEY = "pierre-1234";
+ private final Currency CURRENCY = Currency.BRL;
private final MockBusinessSubscriptionTransitionDao dao = new MockBusinessSubscriptionTransitionDao();
private final UUID subscriptionId = UUID.randomUUID();
@@ -43,14 +46,14 @@ public class TestAnalyticsListener
private final IProduct product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
private final IPlan plan = new MockPlan("platinum-monthly", product);
private final IPlanPhase phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
- private final String priceList = "something";
+ private final String priceList = null;
private AnalyticsListener listener;
@BeforeMethod(alwaysRun = true)
public void setUp() throws Exception
{
- final BusinessSubscriptionTransitionRecorder recorder = new BusinessSubscriptionTransitionRecorder(dao, new MockIEntitlementUserApi(bundleUUID, KEY), new MockIAccountUserApi());
+ final BusinessSubscriptionTransitionRecorder recorder = new BusinessSubscriptionTransitionRecorder(dao, new MockIEntitlementUserApi(bundleUUID, KEY), new MockIAccountUserApi(ACCOUNT_KEY, CURRENCY));
listener = new AnalyticsListener(recorder, null);
}
@@ -97,8 +100,7 @@ public class TestAnalyticsListener
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCreated(plan);
final ISubscription.SubscriptionState subscriptionState = ISubscription.SubscriptionState.ACTIVE;
- final BusinessSubscription emptyBST = new BusinessSubscription(null, null, null, null, null, subscriptionId, bundleUUID);
- return createExpectedBST(event, requestedTransitionTime, effectiveTransitionTime, emptyBST, subscriptionState);
+ return createExpectedBST(event, requestedTransitionTime, effectiveTransitionTime, null, subscriptionState);
}
private BusinessSubscriptionTransition createExpectedPausedBST(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
@@ -132,13 +134,15 @@ public class TestAnalyticsListener
{
return new BusinessSubscriptionTransition(
KEY,
+ ACCOUNT_KEY,
requestedTransitionTime,
eventType,
previousSubscription,
new BusinessSubscription(
+ null,
plan,
phase,
- null,
+ CURRENCY,
effectiveTransitionTime,
nextState,
subscriptionId,
@@ -152,6 +156,7 @@ public class TestAnalyticsListener
final ApiEventType eventType = ApiEventType.CREATE;
final ISubscription.SubscriptionState nextState = ISubscription.SubscriptionState.ACTIVE;
return new SubscriptionTransition(
+ UUID.randomUUID(),
subscriptionId,
bundleUUID,
IEvent.EventType.API_USER,
@@ -199,6 +204,7 @@ public class TestAnalyticsListener
)
{
return new SubscriptionTransition(
+ UUID.randomUUID(),
subscriptionId,
bundleUUID,
IEvent.EventType.API_USER,
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 f185a2a..aea2c99 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
@@ -84,7 +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.getBillingPeriod(), phase.getBillingPeriod());
Assert.assertEquals(subscription.getPrice(), phase.getRecurringPrice().getPrice(null));
Assert.assertEquals(subscription.getProductCategory(), product.getCategory());
Assert.assertEquals(subscription.getProductName(), product.getName());
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
index d45a6d4..9cc4c72 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
@@ -28,9 +28,7 @@ import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import java.util.Currency;
-
-import static com.ning.billing.catalog.api.Currency.*;
+import static com.ning.billing.catalog.api.Currency.USD;
public class TestBusinessSubscriptionTransition
{
@@ -39,6 +37,7 @@ public class TestBusinessSubscriptionTransition
private BusinessSubscriptionEvent event;
private DateTime requestedTimestamp;
private String key;
+ private String accountKey;
private BusinessSubscriptionTransition transition;
@BeforeMethod(alwaysRun = true)
@@ -55,7 +54,8 @@ public class TestBusinessSubscriptionTransition
event = BusinessSubscriptionEvent.subscriptionCancelled(prevISubscription.getCurrentPlan());
requestedTimestamp = new DateTime(DateTimeZone.UTC);
key = "1234";
- transition = new BusinessSubscriptionTransition(key, requestedTimestamp, event, prevSubscription, nextSubscription);
+ accountKey = "pierre-1234";
+ transition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
}
@Test(groups = "fast")
@@ -76,22 +76,22 @@ public class TestBusinessSubscriptionTransition
BusinessSubscriptionTransition otherTransition;
- otherTransition = new BusinessSubscriptionTransition(key, new DateTime(), event, prevSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition(key, accountKey, new DateTime(), event, prevSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition("12345", requestedTimestamp, event, prevSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition("12345", accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, requestedTimestamp, BusinessSubscriptionEvent.subscriptionPaused(null), prevSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, BusinessSubscriptionEvent.subscriptionPaused(null), prevSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, requestedTimestamp, event, prevSubscription, prevSubscription);
+ otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, prevSubscription, prevSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, requestedTimestamp, event, nextSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, nextSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, requestedTimestamp, event, nextSubscription, prevSubscription);
+ otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, nextSubscription, prevSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
}
@@ -99,7 +99,7 @@ public class TestBusinessSubscriptionTransition
public void testRejectInvalidTransitions() throws Exception
{
try {
- new BusinessSubscriptionTransition(null, requestedTimestamp, event, prevSubscription, nextSubscription);
+ new BusinessSubscriptionTransition(null, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
Assert.fail();
}
catch (IllegalArgumentException e) {
@@ -107,7 +107,7 @@ public class TestBusinessSubscriptionTransition
}
try {
- new BusinessSubscriptionTransition(key, null, event, prevSubscription, nextSubscription);
+ new BusinessSubscriptionTransition(key, accountKey, null, event, prevSubscription, nextSubscription);
Assert.fail();
}
catch (IllegalArgumentException e) {
@@ -115,7 +115,7 @@ public class TestBusinessSubscriptionTransition
}
try {
- new BusinessSubscriptionTransition(key, requestedTimestamp, null, prevSubscription, nextSubscription);
+ new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, null, prevSubscription, nextSubscription);
Assert.fail();
}
catch (IllegalArgumentException e) {
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index 5385aad..5a01c5b 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/test/IEntitlementTestApi.java b/api/src/main/java/com/ning/billing/entitlement/api/test/IEntitlementTestApi.java
index fbaa68e..0473cd9 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/test/IEntitlementTestApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/test/IEntitlementTestApi.java
@@ -16,8 +16,11 @@
package com.ning.billing.entitlement.api.test;
+import java.util.UUID;
+
+
public interface IEntitlementTestApi {
- public void doProcessReadyEvents();
+ public void doProcessReadyEvents(UUID [] subscriptionsIds, Boolean recursive, Boolean oneEventOnly);
}
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 f45f450..258e76d 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
@@ -35,6 +35,8 @@ public interface IEntitlementUserApi {
public List<ISubscription> getSubscriptionsForBundle(UUID bundleId);
+ public List<ISubscription> getSubscriptionsForKey(String bundleKey);
+
public ISubscriptionBundle createBundleForAccount(IAccount account, String bundleKey)
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 574de30..922e8f1 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
@@ -59,6 +59,8 @@ public interface ISubscription extends IPrivateFields {
public DateTime getStartDate();
+ public DateTime getEndDate();
+
public IPlan getCurrentPlan();
public String getCurrentPriceList();
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscriptionTransition.java b/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscriptionTransition.java
index 718c28a..e968aa4 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscriptionTransition.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/ISubscriptionTransition.java
@@ -37,6 +37,8 @@ public interface ISubscriptionTransition extends IEventBusType {
PHASE
}
+ UUID getId();
+
SubscriptionTransitionType getTransitionType();
UUID getBundleId();
beatrix/pom.xml 2(+1 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 3571e7d..3867975 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.14-SNAPSHOT</version>
+ <version>0.0.16-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 5643272..fb48f3d 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.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
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 5b0a926..3d69b29 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Plan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Plan.java
@@ -49,7 +49,7 @@ public class Plan extends ValidatingConfig<Catalog> implements IPlan {
@XmlElementWrapper(name="initialPhases", required=false)
@XmlElement(name="phase", required=true)
- private PlanPhase[] initialPhases;
+ private PlanPhase[] initialPhases = new PlanPhase[0];
@XmlElement(name="finalPhase", required=true)
private PlanPhase finalPhase;
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 7cd2986..10010a7 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
@@ -33,7 +33,7 @@ public class PriceListSet extends ValidatingConfig<Catalog> {
private PriceListDefault defaultPricelist;
@XmlElement(required=false, name="childPriceList")
- private PriceList[] childPriceLists;
+ private PriceList[] childPriceLists = new PriceList[0];
public PriceListSet() {
if(childPriceLists == null) {
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 fb2ffb5..c0fa749 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Product.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Product.java
@@ -33,6 +33,7 @@ import com.ning.billing.util.config.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
public class Product extends ValidatingConfig<Catalog> implements IProduct {
+ private static final Product[] EMPTY_PRODUCT_LIST = new Product[0];
@XmlAttribute (required=true)
@XmlID
@@ -43,11 +44,11 @@ public class Product extends ValidatingConfig<Catalog> implements IProduct {
@XmlElementWrapper(name="included", required=false)
@XmlIDREF @XmlElement(name="addonProduct", required=true)
- private Product[] included;
+ private Product[] included = EMPTY_PRODUCT_LIST;
@XmlElementWrapper(name="available", required=false)
@XmlIDREF @XmlElement(name="addonProduct", required=true)
- private Product[] available;
+ private Product[] available = EMPTY_PRODUCT_LIST;
//Not included in XML
private String catalogName;
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 7483255..618b0b8 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.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
index 2cc492f..5ba7076 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
@@ -16,6 +16,7 @@
package com.ning.billing.entitlement.alignment;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -170,6 +171,11 @@ public class PlanAligner implements IPlanAligner {
private List<TimedPhase> getPhaseAlignments(Subscription subscription, IPlan plan,
DateTime effectiveDate, DateTime planStartDate) {
+ // The plan can be null with the nasty endpoint from test API.
+ if (plan == null) {
+ return Collections.emptyList();
+ }
+
List<TimedPhase> result = new LinkedList<IPlanAligner.TimedPhase>();
DateTime curPhaseStart = planStartDate;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
index d3e3c6e..c37c79d 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
@@ -27,7 +27,7 @@ import com.ning.billing.account.api.IAccount;
import com.ning.billing.catalog.api.ICatalog;
import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.Subscription.SubscriptionBuilder;
+import com.ning.billing.entitlement.api.user.SubscriptionBuilder;
import com.ning.billing.entitlement.engine.core.Engine;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.util.clock.IClock;
@@ -62,18 +62,10 @@ public class EntitlementBillingApi implements IEntitlementBillingApi {
new EntitlementBillingApiException(String.format("Unknwon subscription %s", subscriptionId));
}
- Subscription updatedSubscription = new SubscriptionBuilder()
- .setId(subscription.getId())
- .setBundleId(subscription.getBundleId())
- .setStartDate(subscription.getStartDate())
- .setBundleStartDate(subscription.getBundleStartDate())
+ SubscriptionBuilder builder = new SubscriptionBuilder(subscription)
.setChargedThroughDate(ctd)
- .setPaidThroughDate(subscription.getPaidThroughDate())
- .setActiveVersion(subscription.getActiveVersion())
- .setCategory(subscription.getCategory())
- .build();
-
- dao.updateSubscription(updatedSubscription);
+ .setPaidThroughDate(subscription.getPaidThroughDate());
+ dao.updateSubscription(new Subscription(builder, false));
}
}
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
index 61cee03..703281b 100644
--- 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
@@ -16,11 +16,15 @@
package com.ning.billing.entitlement.api.test;
+import java.util.List;
+import java.util.UUID;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.config.IEntitlementConfig;
+import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.engine.core.IApiEventProcessor;
public class EntitlementTestApi implements IEntitlementTestApi {
@@ -37,10 +41,10 @@ public class EntitlementTestApi implements IEntitlementTestApi {
}
@Override
- public void doProcessReadyEvents() {
+ public void doProcessReadyEvents(UUID [] subscriptionsIds, Boolean recursive, Boolean oneEventOnly) {
if (config.isEventProcessingOff()) {
log.warn("Running event processing loop");
- apiEventProcessor.processAllReadyEvents();
+ apiEventProcessor.processAllReadyEvents(subscriptionsIds, recursive, oneEventOnly);
}
}
}
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 a795cf1..e0bb30f 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
@@ -31,6 +31,7 @@ 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.catalog.api.PlanAlignmentChange;
import com.ning.billing.entitlement.alignment.IPlanAligner;
import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
import com.ning.billing.entitlement.api.user.ISubscription;
@@ -40,8 +41,10 @@ import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
+import com.ning.billing.entitlement.events.user.ApiEventBuilder;
import com.ning.billing.entitlement.events.user.ApiEventCreate;
import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.IClock;
public class EntitlementUserApi implements IEntitlementUserApi {
@@ -77,6 +80,12 @@ public class EntitlementUserApi implements IEntitlementUserApi {
}
@Override
+ public List<ISubscription> getSubscriptionsForKey(String bundleKey) {
+ return dao.getSubscriptionsForKey(bundleKey);
+ }
+
+
+ @Override
public List<ISubscription> getSubscriptionsForBundle(UUID bundleId) {
return dao.getSubscriptions(bundleId);
}
@@ -93,8 +102,8 @@ public class EntitlementUserApi implements IEntitlementUserApi {
BillingPeriod term, String priceList, DateTime requestedDate) throws EntitlementUserApiException {
String realPriceList = (priceList == null) ? IPriceListSet.DEFAULT_PRICELIST_NAME : priceList;
-
DateTime now = clock.getUTCNow();
+ requestedDate = (requestedDate != null) ? Clock.truncateMs(requestedDate) : now;
if (requestedDate != null && requestedDate.isAfter(now)) {
throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
}
@@ -148,13 +157,24 @@ public class EntitlementUserApi implements IEntitlementUserApi {
}
DateTime effectiveDate = requestedDate;
- Subscription subscription = new Subscription(bundleId, plan.getProduct().getCategory(), bundleStartDate, effectiveDate);
+ Subscription subscription = new Subscription(new SubscriptionBuilder()
+ .setId(UUID.randomUUID())
+ .setBundleId(bundleId)
+ .setCategory(plan.getProduct().getCategory())
+ .setBundleStartDate(bundleStartDate)
+ .setStartDate(effectiveDate),
+ false);
TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnCreate(subscription, plan, realPriceList, effectiveDate);
- ApiEventCreate creationEvent =
- new ApiEventCreate(subscription.getId(), bundleStartDate, now, plan.getName(), currentTimedPhase.getPhase().getName(), realPriceList,
- requestedDate, effectiveDate, subscription.getActiveVersion());
-
+ ApiEventCreate creationEvent = new ApiEventCreate(new ApiEventBuilder()
+ .setSubscriptionId(subscription.getId())
+ .setEventPlan(plan.getName())
+ .setEventPlanPhase(currentTimedPhase.getPhase().getName())
+ .setEventPriceList(realPriceList)
+ .setActiveVersion(subscription.getActiveVersion())
+ .setProcessedDate(now)
+ .setEffectiveDate(effectiveDate)
+ .setRequestedDate(requestedDate));
TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnCreate(subscription, plan, realPriceList, effectiveDate);
IPhaseEvent nextPhaseEvent = PhaseEvent.getNextPhaseEvent(nextTimedPhase, subscription, now);
@@ -167,6 +187,4 @@ public class EntitlementUserApi implements IEntitlementUserApi {
// STEPH Also update startDate for bundle ?
return dao.createSubscription(subscription, events);
}
-
-
}
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 521c89b..ad0189e 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
@@ -16,17 +16,17 @@
package com.ning.billing.entitlement.api.user;
-import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
-import com.ning.billing.ErrorCode;
-import com.ning.billing.account.api.IAccount;
import org.joda.time.DateTime;
+import com.ning.billing.ErrorCode;
+
import com.ning.billing.catalog.api.ActionPolicy;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.CatalogApiException;
@@ -47,129 +47,69 @@ import com.ning.billing.entitlement.events.IEvent;
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.ApiEventBuilder;
import com.ning.billing.entitlement.events.user.ApiEventCancel;
import com.ning.billing.entitlement.events.user.ApiEventChange;
+import com.ning.billing.entitlement.events.user.ApiEventCreate;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.ApiEventUncancel;
import com.ning.billing.entitlement.events.user.IApiEvent;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.entitlement.glue.InjectorMagic;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.IClock;
public class Subscription extends PrivateFields implements ISubscription {
+ //
+ // Singletons used to perform API changes
+ private final IClock clock;
+ private final IEntitlementDao dao;
+ private final ICatalog catalog;
+ private final IPlanAligner planAligner;
+
+ //
+ // Final subscription fields
+ //
private final UUID id;
private final UUID bundleId;
private final DateTime startDate;
private final DateTime bundleStartDate;
- private final long activeVersion;
private final ProductCategory category;
- private final IClock clock;
- private final IEntitlementDao dao;
- private final ICatalog catalog;
- private final IPlanAligner planAligner;
-
- // STEPH interaction with billing /payment system
+ //
+ // Those can be modified through non User APIs, and a new Subscription object would be created
+ //
+ private final long activeVersion;
private final DateTime chargedThroughDate;
private final DateTime paidThroughDate;
- // STEPH non final because of change/ cancel API at the object level
+ //
+ // User APIs (createm chnage, cancel,...) will recompute those each time,
+ // so the user holding that subscription object get the correct state when
+ // the call completes
+ //
private List<SubscriptionTransition> transitions;
-
- public static class SubscriptionBuilder {
- private UUID id;
- private UUID bundleId;
- private DateTime startDate;
- private DateTime bundleStartDate;
- private Long activeVersion;
- private ProductCategory category;
- private DateTime chargedThroughDate;
- private DateTime paidThroughDate;
-
- public SubscriptionBuilder setId(UUID id) {
- this.id = id;
- return this;
- }
- public SubscriptionBuilder setBundleId(UUID bundleId) {
- this.bundleId = bundleId;
- return this;
- }
- public SubscriptionBuilder setStartDate(DateTime startDate) {
- this.startDate = startDate;
- return this;
- }
- public SubscriptionBuilder setBundleStartDate(DateTime bundleStartDate) {
- this.bundleStartDate = bundleStartDate;
- return this;
- }
- public SubscriptionBuilder setActiveVersion(long activeVersion) {
- this.activeVersion = activeVersion;
- return this;
- }
- public SubscriptionBuilder setChargedThroughDate(DateTime chargedThroughDate) {
- this.chargedThroughDate = chargedThroughDate;
- return this;
- }
- public SubscriptionBuilder setPaidThroughDate(DateTime paidThroughDate) {
- this.paidThroughDate = paidThroughDate;
- return this;
- }
- public SubscriptionBuilder setCategory(ProductCategory category) {
- this.category = category;
- return this;
- }
-
- private void checkAllFieldsSet() {
- for (Field cur : SubscriptionBuilder.class.getDeclaredFields()) {
- try {
- Object value = cur.get(this);
- if (value == null) {
- throw new EntitlementError(String.format("Field %s has not been set for Subscription",
- cur.getName()));
- }
- } catch (IllegalAccessException e) {
- throw new EntitlementError(String.format("Failed to access value for field %s for Subscription",
- cur.getName()), e);
- }
- }
- }
-
- public Subscription build() {
- //checkAllFieldsSet();
- return new Subscription(id, bundleId, category, bundleStartDate, startDate, chargedThroughDate, paidThroughDate, activeVersion);
- }
-
- }
-
- public Subscription(UUID bundleId, ProductCategory category, DateTime bundleStartDate, DateTime startDate) {
- this(UUID.randomUUID(), bundleId, category, bundleStartDate, startDate, null, null, SubscriptionEvents.INITIAL_VERSION);
- }
-
-
- public Subscription(UUID id, UUID bundleId, ProductCategory category, DateTime bundleStartDate, DateTime startDate, DateTime ctd, DateTime ptd, long activeVersion) {
-
+ public Subscription(SubscriptionBuilder builder, boolean rebuildTransition) {
super();
this.clock = InjectorMagic.getClock();
this.dao = InjectorMagic.getEntitlementDao();
this.catalog = InjectorMagic.getCatlog();
this.planAligner = InjectorMagic.getPlanAligner();
- this.id = id;
- this.bundleId = bundleId;
- this.startDate = startDate;
- this.bundleStartDate = bundleStartDate;
- this.category = category;
-
- this.activeVersion = activeVersion;
-
- this.chargedThroughDate = ctd;
- this.paidThroughDate = ptd;
-
- rebuildTransitions();
+ this.id = builder.getId();
+ this.bundleId = builder.getBundleId();
+ this.startDate = builder.getStartDate();
+ this.bundleStartDate = builder.getBundleStartDate();
+ this.category = builder.getCategory();
+ this.activeVersion = builder.getActiveVersion();
+ this.chargedThroughDate = builder.getChargedThroughDate();
+ this.paidThroughDate = builder.getPaidThroughDate();
+ if (rebuildTransition) {
+ rebuildTransitions();
+ }
}
-
@Override
public UUID getId() {
return id;
@@ -210,6 +150,16 @@ public class Subscription extends PrivateFields implements ISubscription {
@Override
+ public DateTime getEndDate() {
+ ISubscriptionTransition latestTransition = getLatestTranstion();
+ if (latestTransition.getNextState() == SubscriptionState.CANCELLED) {
+ return latestTransition.getEffectiveTransitionTime();
+ }
+ return null;
+ }
+
+
+ @Override
public void cancel(DateTime requestedDate, boolean eot) throws EntitlementUserApiException {
SubscriptionState currentState = getState();
@@ -218,6 +168,7 @@ public class Subscription extends PrivateFields implements ISubscription {
}
DateTime now = clock.getUTCNow();
+ requestedDate = (requestedDate != null) ? Clock.truncateMs(requestedDate) : null;
if (requestedDate != null && requestedDate.isAfter(now)) {
throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
}
@@ -239,7 +190,14 @@ public class Subscription extends PrivateFields implements ISubscription {
}
DateTime effectiveDate = getPlanChangeEffectiveDate(policy, now);
- IEvent cancelEvent = new ApiEventCancel(id, bundleStartDate, now, now, effectiveDate, activeVersion);
+
+ IEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
+ .setSubscriptionId(id)
+ .setActiveVersion(activeVersion)
+ .setProcessedDate(now)
+ .setEffectiveDate(effectiveDate)
+ .setRequestedDate(now));
+
dao.cancelSubscription(id, cancelEvent);
rebuildTransitions();
}
@@ -250,7 +208,13 @@ public class Subscription extends PrivateFields implements ISubscription {
throw new EntitlementUserApiException(ErrorCode.ENT_UNCANCEL_BAD_STATE, id.toString());
}
DateTime now = clock.getUTCNow();
- IEvent uncancelEvent = new ApiEventUncancel(id, bundleStartDate, now, now, now, activeVersion);
+ IEvent uncancelEvent = new ApiEventUncancel(new ApiEventBuilder()
+ .setSubscriptionId(id)
+ .setActiveVersion(activeVersion)
+ .setProcessedDate(now)
+ .setRequestedDate(now)
+ .setEffectiveDate(now));
+
List<IEvent> uncancelEvents = new ArrayList<IEvent>();
uncancelEvents.add(uncancelEvent);
@@ -268,6 +232,7 @@ public class Subscription extends PrivateFields implements ISubscription {
public void changePlan(String productName, BillingPeriod term,
String priceList, DateTime requestedDate) throws EntitlementUserApiException {
+ requestedDate = (requestedDate != null) ? Clock.truncateMs(requestedDate) : null;
String currentPriceList = getCurrentPriceList();
SubscriptionState currentState = getState();
@@ -325,8 +290,16 @@ public class Subscription extends PrivateFields implements ISubscription {
DateTime effectiveDate = getPlanChangeEffectiveDate(policy, now);
TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(this, newPlan, newPriceList.getName(), effectiveDate);
- IEvent changeEvent = new ApiEventChange(id, bundleStartDate, now, newPlan.getName(), currentTimedPhase.getPhase().getName(),
- newPriceList.getName(), now, effectiveDate, activeVersion);
+
+ IEvent changeEvent = new ApiEventChange(new ApiEventBuilder()
+ .setSubscriptionId(id)
+ .setEventPlan(newPlan.getName())
+ .setEventPlanPhase(currentTimedPhase.getPhase().getName())
+ .setEventPriceList(newPriceList.getName())
+ .setActiveVersion(activeVersion)
+ .setProcessedDate(now)
+ .setEffectiveDate(effectiveDate)
+ .setRequestedDate(now));
TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(this, newPlan, newPriceList.getName(), effectiveDate);
IPhaseEvent nextPhaseEvent = PhaseEvent.getNextPhaseEvent(nextTimedPhase, this, now);
@@ -366,6 +339,19 @@ public class Subscription extends PrivateFields implements ISubscription {
return latestSubscription;
}
+ public ISubscriptionTransition getTransitionFromEvent(IEvent event) {
+ if (transitions == null || event == null) {
+ return null;
+ }
+
+ for (ISubscriptionTransition cur : transitions) {
+ if (cur.getId().equals(event.getId())) {
+ return cur;
+ }
+ }
+ return null;
+ }
+
public long getActiveVersion() {
return activeVersion;
}
@@ -410,7 +396,7 @@ public class Subscription extends PrivateFields implements ISubscription {
public List<ISubscriptionTransition> getActiveTransitions() {
if (transitions == null) {
- return null;
+ return Collections.emptyList();
}
List<ISubscriptionTransition> activeTransitions = new ArrayList<ISubscriptionTransition>();
@@ -580,7 +566,7 @@ public class Subscription extends PrivateFields implements ISubscription {
}
SubscriptionTransition transition =
- new SubscriptionTransition(id, bundleId, cur.getType(), apiEventType,
+ new SubscriptionTransition(cur.getId(), id, bundleId, cur.getType(), apiEventType,
cur.getRequestedDate(), cur.getEffectiveDate(),
previousState, previousPlan, previousPhase, previousPriceList,
nextState, nextPlan, nextPhase, nextPriceList);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBuilder.java
new file mode 100644
index 0000000..d14b754
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBuilder.java
@@ -0,0 +1,124 @@
+/*
+ * 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.user;
+
+import java.lang.reflect.Field;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
+
+public class SubscriptionBuilder {
+
+ private UUID id;
+ private UUID bundleId;
+ private DateTime startDate;
+ private DateTime bundleStartDate;
+ private Long activeVersion;
+ private ProductCategory category;
+ private DateTime chargedThroughDate;
+ private DateTime paidThroughDate;
+
+ public SubscriptionBuilder() {
+ this.activeVersion = SubscriptionEvents.INITIAL_VERSION;
+ }
+
+ public SubscriptionBuilder(Subscription original) {
+ this.id = original.getId();
+ this.bundleId = original.getBundleId();
+ this.startDate = original.getStartDate();
+ this.bundleStartDate = original.getBundleStartDate();
+ this.category = original.getCategory();
+ this.activeVersion = original.getActiveVersion();
+ this.chargedThroughDate = original.getChargedThroughDate();
+ this.paidThroughDate = original.getPaidThroughDate();
+ }
+
+ public SubscriptionBuilder setId(UUID id) {
+ this.id = id;
+ return this;
+ }
+ public SubscriptionBuilder setBundleId(UUID bundleId) {
+ this.bundleId = bundleId;
+ return this;
+ }
+ public SubscriptionBuilder setStartDate(DateTime startDate) {
+ this.startDate = startDate;
+ return this;
+ }
+ public SubscriptionBuilder setBundleStartDate(DateTime bundleStartDate) {
+ this.bundleStartDate = bundleStartDate;
+ return this;
+ }
+ public SubscriptionBuilder setActiveVersion(long activeVersion) {
+ this.activeVersion = activeVersion;
+ return this;
+ }
+ public SubscriptionBuilder setChargedThroughDate(DateTime chargedThroughDate) {
+ this.chargedThroughDate = chargedThroughDate;
+ return this;
+ }
+ public SubscriptionBuilder setPaidThroughDate(DateTime paidThroughDate) {
+ this.paidThroughDate = paidThroughDate;
+ return this;
+ }
+ public SubscriptionBuilder setCategory(ProductCategory category) {
+ this.category = category;
+ return this;
+ }
+
+ public UUID getId() {
+ return id;
+ }
+ public UUID getBundleId() {
+ return bundleId;
+ }
+ public DateTime getStartDate() {
+ return startDate;
+ }
+ public DateTime getBundleStartDate() {
+ return bundleStartDate;
+ }
+ public Long getActiveVersion() {
+ return activeVersion;
+ }
+ public ProductCategory getCategory() {
+ return category;
+ }
+ public DateTime getChargedThroughDate() {
+ return chargedThroughDate;
+ }
+ public DateTime getPaidThroughDate() {
+ return paidThroughDate;
+ }
+ private void checkAllFieldsSet() {
+ for (Field cur : SubscriptionBuilder.class.getDeclaredFields()) {
+ try {
+ Object value = cur.get(this);
+ if (value == null) {
+ throw new EntitlementError(String.format("Field %s has not been set for Subscription",
+ cur.getName()));
+ }
+ } catch (IllegalAccessException e) {
+ throw new EntitlementError(String.format("Failed to access value for field %s for Subscription",
+ cur.getName()), e);
+ }
+ }
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
index 616e871..7f8bc8c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
@@ -32,6 +32,7 @@ public class SubscriptionTransition implements ISubscriptionTransition {
private final UUID subscriptionId;
private final UUID bundleId;
+ private final UUID eventId;
private final EventType eventType;
private final ApiEventType apiEventType;
private final DateTime requestedTransitionTime;
@@ -45,11 +46,12 @@ public class SubscriptionTransition implements ISubscriptionTransition {
private final IPlan nextPlan;
private final IPlanPhase nextPhase;
- public SubscriptionTransition(UUID subscriptionId, UUID bundleId, EventType eventType,
+ public SubscriptionTransition(UUID eventId, UUID subscriptionId, UUID bundleId, EventType eventType,
ApiEventType apiEventType, DateTime requestedTransitionTime, DateTime effectiveTransitionTime,
SubscriptionState previousState, IPlan previousPlan, IPlanPhase previousPhase, String previousPriceList,
SubscriptionState nextState, IPlan nextPlan, IPlanPhase nextPhase, String nextPriceList) {
super();
+ this.eventId = eventId;
this.subscriptionId = subscriptionId;
this.bundleId = bundleId;
this.eventType = eventType;
@@ -67,6 +69,11 @@ public class SubscriptionTransition implements ISubscriptionTransition {
}
@Override
+ public UUID getId() {
+ return eventId;
+ }
+
+ @Override
public UUID getSubscriptionId() {
return subscriptionId;
}
@@ -151,17 +158,19 @@ public class SubscriptionTransition implements ISubscriptionTransition {
@Override
public String toString() {
- return "SubscriptionTransition [subscriptionId=" + subscriptionId
- + ", eventType=" + eventType + ", apiEventType="
- + apiEventType + ", requestedTransitionTime=" + requestedTransitionTime
- + ", effectiveTransitionTime=" + effectiveTransitionTime
- + ", previousState=" + previousState + ", previousPlan="
- + ((previousPlan != null) ? previousPlan.getName() : null)
- + ", previousPhase=" + ((previousPhase != null) ? previousPhase.getName() : null)
- + ", previousPriceList " + previousPriceList
- + ", nextState=" + nextState
- + ", nextPlan=" + ((nextPlan != null) ? nextPlan.getName() : null)
- + ", nextPriceList " + nextPriceList
- + ", nextPhase=" + ((nextPhase != null) ? nextPhase.getName() : null) + "]";
+ return "SubscriptionTransition [eventId=" + eventId
+ + ", subscriptionId=" + subscriptionId
+ + ", eventType=" + eventType + ", apiEventType="
+ + apiEventType + ", requestedTransitionTime=" + requestedTransitionTime
+ + ", effectiveTransitionTime=" + effectiveTransitionTime
+ + ", previousState=" + previousState + ", previousPlan="
+ + ((previousPlan != null) ? previousPlan.getName() : null)
+ + ", previousPhase=" + ((previousPhase != null) ? previousPhase.getName() : null)
+ + ", previousPriceList " + previousPriceList
+ + ", nextState=" + nextState
+ + ", nextPlan=" + ((nextPlan != null) ? nextPlan.getName() : null)
+ + ", nextPriceList " + nextPriceList
+ + ", nextPhase=" + ((nextPhase != null) ? nextPhase.getName() : null) + "]";
}
+
}
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 541de37..73eb863 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
@@ -16,6 +16,7 @@
package com.ning.billing.entitlement.engine.core;
+import java.util.Collection;
import java.util.List;
import com.google.inject.Inject;
@@ -34,13 +35,17 @@ public class ApiEventProcessor extends ApiEventProcessorBase {
@Override
protected boolean doProcessEvents(int sequenceId) {
- long prev = nbProcessedEvents;
List<IEvent> claimedEvents = dao.getEventsReady(apiProcessorId, sequenceId);
if (claimedEvents.size() == 0) {
return false;
}
log.debug(String.format("ApiEventProcessor got %d events", claimedEvents.size()));
+ return doProcessEventsFromList(sequenceId, claimedEvents);
+ }
+
+ protected boolean doProcessEventsFromList(int sequenceId, Collection<IEvent> claimedEvents) {
+ long prev = nbProcessedEvents;
for (IEvent cur : claimedEvents) {
log.debug(String.format("ApiEventProcessor seq = %d got event %s", sequenceId, cur.getId()));
listener.processEventReady(cur);
@@ -52,6 +57,6 @@ public class ApiEventProcessor extends ApiEventProcessorBase {
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 f3faf8e..acaa7ad 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
@@ -17,6 +17,10 @@
package com.ning.billing.entitlement.engine.core;
import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
@@ -28,8 +32,11 @@ import org.skife.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
import com.google.inject.Inject;
import com.ning.billing.config.IEntitlementConfig;
+import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.util.clock.IClock;
@@ -71,7 +78,7 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
@Override
- public void startNotifications(IEventListener listener) {
+ public void startNotifications(final IEventListener listener) {
this.listener = listener;
this.isProcessingEvents = true;
@@ -80,6 +87,7 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
if (config.isEventProcessingOff()) {
log.warn("KILLBILL ENTITLEMENT EVENT PROCESSING IS OFF !!!");
+ listener.completedNotificationStart();
return;
}
final ApiEventProcessorBase apiEventProcessor = this;
@@ -88,6 +96,7 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
if (executor != null) {
log.warn("There is already an executor thread running, return");
+ listener.completedNotificationStart();
return;
}
@@ -115,6 +124,10 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
log.info(String.format("ApiEventProcessor thread %s [%d] started", API_EVENT_THREAD_NAME,
Thread.currentThread().getId()));
+
+ // Thread is now started, notify the listener
+ listener.completedNotificationStart();
+
try {
while (true) {
synchronized (apiEventProcessor) {
@@ -158,6 +171,11 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
@Override
public void stopNotifications() {
+
+ if (config.isEventProcessingOff()) {
+ return;
+ }
+
synchronized(this) {
isProcessingEvents = false;
try {
@@ -172,20 +190,72 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
}
+ //
// Used for system test purpose only when event processing has been disabled.
+ // This is not necessarily pretty
+ //
@Override
- public void processAllReadyEvents() {
+ public void processAllReadyEvents(final UUID [] subscriptionsIds, final Boolean recursive, final Boolean oneEventOnly) {
+ processAllReadyEventsRecursively(subscriptionsIds, recursive, oneEventOnly);
+ }
+
+ private boolean processAllReadyEventsRecursively(final UUID [] subscriptionsIds,
+ final Boolean recursive,
+ final Boolean oneEventOnly) {
+ int curSequenceId = sequenceId.getAndIncrement();
- boolean keepProcessing = false;
- /*
+ //Get all current ready events
+ List<IEvent> claimedEvents = new LinkedList<IEvent>();
do {
- */
- keepProcessing = doProcessEvents(sequenceId.incrementAndGet());
- /*
- } while (keepProcessing);
- */
+ List<IEvent> tmpEvents = dao.getEventsReady(apiProcessorId, curSequenceId);
+ if (tmpEvents.size() == 0) {
+ break;
+ }
+ claimedEvents.addAll(tmpEvents);
+ } while(true);
+ if (claimedEvents.size() == 0) {
+ return false;
+ }
+
+ // Filter for specific subscriptions if needed
+ Collection<IEvent> claimedEventsFiltered = null;
+ if (subscriptionsIds.length == 0) {
+ claimedEventsFiltered = claimedEvents;
+ } else {
+
+ claimedEventsFiltered = Collections2.filter(claimedEvents, new Predicate<IEvent>() {
+ @Override
+ public boolean apply(IEvent input) {
+ for (UUID cur : subscriptionsIds) {
+ if (cur.equals(input.getSubscriptionId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+ }
+ if (claimedEventsFiltered.size() == 0) {
+ return false;
+ }
+
+ // If only one event is requested extract it
+ if (oneEventOnly) {
+ List<IEvent> oneEventList = new ArrayList<IEvent>(1);
+ oneEventList.add(claimedEventsFiltered.iterator().next());
+ claimedEventsFiltered = oneEventList;
+ }
+
+ // Call processing method
+ doProcessEventsFromList(curSequenceId, claimedEventsFiltered);
+ // Keep going is recursive
+ if (recursive && !oneEventOnly) {
+ processAllReadyEventsRecursively(subscriptionsIds, recursive, oneEventOnly);
+ }
+ return true;
}
protected abstract boolean doProcessEvents(int sequenceId);
+ protected abstract boolean doProcessEventsFromList(int sequenceId, Collection<IEvent> events);
}
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 622fa12..2b47f9c 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
@@ -38,8 +38,7 @@ import com.ning.billing.entitlement.events.IEvent;
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.IApiEvent;
-import com.ning.billing.lifecycle.IService;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.lifecycle.LyfecycleHandlerType;
import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel;
import com.ning.billing.util.clock.IClock;
@@ -50,6 +49,10 @@ public class Engine implements IEventListener, IEntitlementService {
private static final String ENTITLEMENT_SERVICE_NAME = "entitlement-service";
+ private final long MAX_NOTIFICATION_THREAD_WAIT_MS = 10000; // 10 secs
+ private final long NOTIFICATION_THREAD_WAIT_INCREMENT_MS = 1000; // 1 sec
+ private final long NANO_TO_MS = (1000 * 1000);
+
private final static Logger log = LoggerFactory.getLogger(Engine.class);
private final IClock clock;
@@ -61,6 +64,8 @@ public class Engine implements IEventListener, IEntitlementService {
private final IEntitlementTestApi testApi;
private final IEventBus eventBus;
+ private boolean startedNotificationThread;
+
@Inject
public Engine(IClock clock, IEntitlementDao dao, IApiEventProcessor apiEventProcessor,
IPlanAligner planAligner, IEntitlementConfig config, EntitlementUserApi userApi,
@@ -74,6 +79,8 @@ public class Engine implements IEventListener, IEntitlementService {
this.testApi = testApi;
this.billingApi = billingApi;
this.eventBus = eventBus;
+
+ this.startedNotificationThread = false;
}
@Override
@@ -89,11 +96,13 @@ public class Engine implements IEventListener, IEntitlementService {
@LyfecycleHandlerType(LyfecycleLevel.START_SERVICE)
public void start() {
apiEventProcessor.startNotifications(this);
+ waitForNotificationStartCompletion();
}
@LyfecycleHandlerType(LyfecycleLevel.STOP_SERVICE)
public void stop() {
apiEventProcessor.stopNotifications();
+ startedNotificationThread = false;
}
@Override
@@ -123,11 +132,46 @@ public class Engine implements IEventListener, IEntitlementService {
insertNextPhaseEvent(subscription);
}
try {
- eventBus.post(subscription.getLatestTranstion());
+ eventBus.post(subscription.getTransitionFromEvent(event));
} catch (EventBusException e) {
log.warn("Failed to post entitlement event " + event, e);
}
+ }
+ //
+ // We want to ensure the notification thread is indeed started when we return from start()
+ //
+ @Override
+ public void completedNotificationStart() {
+ synchronized (this) {
+ startedNotificationThread = true;
+ this.notifyAll();
+ }
+ }
+
+ private void waitForNotificationStartCompletion() {
+
+ long ini = System.nanoTime();
+ synchronized(this) {
+ do {
+ if (startedNotificationThread) {
+ break;
+ }
+ try {
+ this.wait(NOTIFICATION_THREAD_WAIT_INCREMENT_MS);
+ } catch (InterruptedException e ) {
+ Thread.currentThread().interrupt();
+ throw new EntitlementError(e);
+ }
+ } while (!startedNotificationThread &&
+ (System.nanoTime() - ini) / NANO_TO_MS < MAX_NOTIFICATION_THREAD_WAIT_MS);
+
+ if (!startedNotificationThread) {
+ log.error("Could not start notification thread in {} msec !!!", MAX_NOTIFICATION_THREAD_WAIT_MS);
+ throw new EntitlementError("Failed to start service!!");
+ }
+ log.info("Notification thread has been started in {} ms", (System.nanoTime() - ini) / NANO_TO_MS);
+ }
}
private void insertNextPhaseEvent(Subscription subscription) {
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 f51ae7e..dc04996 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
@@ -16,9 +16,11 @@
package com.ning.billing.entitlement.engine.core;
+import java.util.UUID;
+
public interface IApiEventProcessor extends IEventNotifier {
- public void processAllReadyEvents();
+ public void processAllReadyEvents(UUID [] subscriptionsIds, Boolean recursive, Boolean oneEventOnly);
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IEventListener.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IEventListener.java
index f973279..651f8a9 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IEventListener.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/IEventListener.java
@@ -21,5 +21,8 @@ import com.ning.billing.entitlement.events.IEvent;
public interface IEventListener {
+
public void processEventReady(IEvent event);
+
+ public void completedNotificationStart();
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
index 197e4bd..943a0dc 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
@@ -37,6 +37,7 @@ import com.ning.billing.config.IEntitlementConfig;
import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.api.user.ISubscriptionBundle;
import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBuilder;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.entitlement.events.IEvent.EventType;
@@ -107,6 +108,15 @@ public class EntitlementDao implements IEntitlementDao {
}
@Override
+ public List<ISubscription> getSubscriptionsForKey(String bundleKey) {
+ ISubscriptionBundle bundle = bundlesDao.getBundleFromKey(bundleKey);
+ if (bundle == null) {
+ return Collections.emptyList();
+ }
+ return subscriptionsDao.getSubscriptionsFromBundleId(bundle.getId().toString());
+ }
+
+ @Override
public void updateSubscription(Subscription subscription) {
Date ctd = (subscription.getChargedThroughDate() != null) ? subscription.getChargedThroughDate().toDate() : null;
Date ptd = (subscription.getPaidThroughDate() != null) ? subscription.getPaidThroughDate().toDate() : null;
@@ -178,7 +188,7 @@ public class EntitlementDao implements IEntitlementDao {
}
@Override
- public void clearEventsReady(final UUID ownerId, final List<IEvent> cleared) {
+ public void clearEventsReady(final UUID ownerId, final Collection<IEvent> cleared) {
log.debug(String.format("EntitlementDao clearEventsReady START cleared size = %d", cleared.size()));
@@ -216,8 +226,7 @@ public class EntitlementDao implements IEntitlementDao {
return null;
}
});
- return new Subscription(subscription.getId(), subscription.getBundleId(),subscription.getCategory(), subscription.getBundleStartDate(),
- subscription.getStartDate(), subscription.getChargedThroughDate(), subscription.getPaidThroughDate(), subscription.getActiveVersion());
+ return new Subscription(new SubscriptionBuilder(subscription), true);
}
@Override
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.java
index 737bf52..e77c83c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.java
@@ -53,8 +53,13 @@ public interface IBundleSqlDao extends Transactional<IEventSqlDao>, CloseMe, Tra
@SqlQuery
@Mapper(ISubscriptionBundleSqlMapper.class)
+ public ISubscriptionBundle getBundleFromKey(@Bind("name") String name);
+
+ @SqlQuery
+ @Mapper(ISubscriptionBundleSqlMapper.class)
public List<ISubscriptionBundle> getBundleFromAccount(@Bind("account_id") String accountId);
+
public static class SubscriptionBundleBinder implements Binder<Bind, SubscriptionBundle> {
private Date getDate(DateTime dateTime) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEntitlementDao.java
index 1f35fa0..2d46439 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEntitlementDao.java
@@ -16,6 +16,7 @@
package com.ning.billing.entitlement.engine.dao;
+import java.util.Collection;
import java.util.List;
import java.util.UUID;
@@ -43,6 +44,8 @@ public interface IEntitlementDao {
public List<ISubscription> getSubscriptions(UUID bundleId);
+ public List<ISubscription> getSubscriptionsForKey(String bundleKey);
+
// Update
public void updateSubscription(Subscription subscription);
@@ -55,7 +58,7 @@ public interface IEntitlementDao {
public List<IEvent> getEventsReady(UUID ownerId, int sequenceId);
- public void clearEventsReady(UUID ownerId, List<IEvent> cleared);
+ public void clearEventsReady(UUID ownerId, Collection<IEvent> cleared);
// Subscription creation, cancellation, changePlan apis
public ISubscription createSubscription(Subscription subscription, List<IEvent> initialEvents);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEventSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEventSqlDao.java
index 3c2180d..ff53ef2 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEventSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/IEventSqlDao.java
@@ -38,11 +38,14 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
+import com.ning.billing.entitlement.events.EventBaseBuilder;
import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.entitlement.events.IEvent.EventType;
import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
+import com.ning.billing.entitlement.events.phase.PhaseEventBuilder;
+import com.ning.billing.entitlement.events.user.ApiEventBuilder;
import com.ning.billing.entitlement.events.user.ApiEventCancel;
import com.ning.billing.entitlement.events.user.ApiEventChange;
import com.ning.billing.entitlement.events.user.ApiEventCreate;
@@ -125,7 +128,7 @@ public interface IEventSqlDao extends Transactional<IEventSqlDao>, CloseMe, Tran
@Override
public IEvent map(int index, ResultSet r, StatementContext ctx)
- throws SQLException {
+ throws SQLException {
UUID id = UUID.fromString(r.getString("event_id"));
EventType eventType = EventType.valueOf(r.getString("event_type"));
@@ -143,28 +146,47 @@ public interface IEventSqlDao extends Transactional<IEventSqlDao>, CloseMe, Tran
UUID processingOwner = (r.getString("processing_owner") != null) ? UUID.fromString(r.getString("processing_owner")) : null;
IEventLyfecycleState processingState = IEventLyfecycleState.valueOf(r.getString("processing_state"));
+ EventBaseBuilder<?> base = ((eventType == EventType.PHASE) ?
+ new PhaseEventBuilder() :
+ new ApiEventBuilder())
+ .setUuid(id)
+ .setSubscriptionId(subscriptionId)
+ .setRequestedDate(requestedDate)
+ .setEffectiveDate(effectiveDate)
+ .setProcessedDate(createdDate)
+ .setActiveVersion(currentVersion)
+ .setActive(isActive)
+ .setProcessingOwner(processingOwner)
+ .setNextAvailableProcessingTime(nextAvailableDate)
+ .setProcessingState(processingState);
+
+
IEvent result = null;
if (eventType == EventType.PHASE) {
- result = new PhaseEvent(id, subscriptionId, phaseName, requestedDate, effectiveDate, createdDate,
- currentVersion, isActive, processingOwner, nextAvailableDate, processingState);
- } else if (userType == ApiEventType.CREATE) {
- result = new ApiEventCreate(id, subscriptionId, createdDate, planName, phaseName, priceListName, requestedDate, effectiveDate,
- currentVersion, isActive, processingOwner, nextAvailableDate, processingState);
- } else if (userType == ApiEventType.CHANGE) {
- result = new ApiEventChange(id, subscriptionId, createdDate, planName, phaseName, priceListName, requestedDate, effectiveDate,
- currentVersion, isActive, processingOwner, nextAvailableDate, processingState);
- } else if (userType == ApiEventType.CANCEL) {
- result = new ApiEventCancel(id, subscriptionId, createdDate, planName, phaseName, priceListName, requestedDate, effectiveDate,
- currentVersion, isActive, processingOwner, nextAvailableDate, processingState);
- } else if (userType == ApiEventType.PAUSE) {
- result = new ApiEventPause(id, subscriptionId, createdDate, planName, phaseName, priceListName, requestedDate, effectiveDate,
- currentVersion, isActive, processingOwner, nextAvailableDate, processingState);
- } else if (userType == ApiEventType.RESUME) {
- result = new ApiEventResume(id, subscriptionId, createdDate, planName, phaseName, priceListName, requestedDate, effectiveDate,
- currentVersion, isActive, processingOwner, nextAvailableDate, processingState);
- } else if (userType == ApiEventType.UNCANCEL) {
- result = new ApiEventUncancel(id, subscriptionId, createdDate, planName, phaseName, priceListName, requestedDate, effectiveDate,
- currentVersion, isActive, processingOwner, nextAvailableDate, processingState);
+ EventBaseBuilder<PhaseEventBuilder> realBase = (EventBaseBuilder<PhaseEventBuilder>) base;
+ result = new PhaseEvent(new PhaseEventBuilder(realBase).setPhaseName(phaseName));
+ } else if (eventType == EventType.API_USER) {
+
+ EventBaseBuilder<ApiEventBuilder> realBase = (EventBaseBuilder<ApiEventBuilder>) base;
+ ApiEventBuilder builder = new ApiEventBuilder(realBase)
+ .setEventPlan(planName)
+ .setEventPlanPhase(phaseName)
+ .setEventPriceList(priceListName)
+ .setEventType(userType);
+
+ if (userType == ApiEventType.CREATE) {
+ result = new ApiEventCreate(builder);
+ } else if (userType == ApiEventType.CHANGE) {
+ result = new ApiEventChange(builder);
+ } else if (userType == ApiEventType.CANCEL) {
+ result = new ApiEventCancel(builder);
+ } else if (userType == ApiEventType.PAUSE) {
+ result = new ApiEventPause(builder);
+ } else if (userType == ApiEventType.RESUME) {
+ result = new ApiEventResume(builder);
+ } else if (userType == ApiEventType.UNCANCEL) {
+ result = new ApiEventUncancel(builder);
+ }
} else {
throw new EntitlementError(String.format("Can't deserialize event %s", eventType));
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/ISubscriptionSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/ISubscriptionSqlDao.java
index e1af556..f3c5c7d 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/ISubscriptionSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/ISubscriptionSqlDao.java
@@ -41,6 +41,8 @@ import org.skife.jdbi.v2.tweak.ResultSetMapper;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBuilder;
+
@ExternalizedSqlViaStringTemplate3()
public interface ISubscriptionSqlDao extends Transactional<ISubscriptionSqlDao>, CloseMe, Transmogrifier {
@@ -98,10 +100,17 @@ public interface ISubscriptionSqlDao extends Transactional<ISubscriptionSqlDao>,
DateTime ptd = getDate(r, "ptd_dt");
long activeVersion = r.getLong("active_version");
- Subscription subscription = new Subscription(id, bundleId, category, bundleStartDate, startDate, ctd, ptd, activeVersion);
+ Subscription subscription = new Subscription(new SubscriptionBuilder()
+ .setId(id)
+ .setBundleId(bundleId)
+ .setCategory(category)
+ .setBundleStartDate(bundleStartDate)
+ .setStartDate(startDate)
+ .setActiveVersion(activeVersion)
+ .setChargedThroughDate(ctd)
+ .setPaidThroughDate(ptd),
+ true);
return subscription;
}
}
-
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
index b1e9f02..84e0b50 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
@@ -40,6 +40,20 @@ public abstract class EventBase implements IEvent {
private DateTime nextAvailableProcessingTime;
private IEventLyfecycleState processingState;
+ public EventBase(EventBaseBuilder builder) {
+ this.uuid = builder.getUuid();
+ this.subscriptionId = builder.getSubscriptionId();
+ this.requestedDate = builder.getRequestedDate();
+ this.effectiveDate = builder.getEffectiveDate();
+ this.processedDate = builder.getProcessedDate();
+
+ this.activeVersion = builder.getActiveVersion();
+ this.isActive = builder.isActive();
+ this.processingOwner = builder.getProcessingOwner();
+ this.nextAvailableProcessingTime = builder.getNextAvailableProcessingTime();
+ this.processingState = builder.getProcessingState();
+ }
+
public EventBase(UUID subscriptionId, DateTime requestedDate,
DateTime effectiveDate, DateTime processedDate,
long activeVersion, boolean isActive) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
new file mode 100644
index 0000000..69980a3
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
@@ -0,0 +1,150 @@
+/*
+ * 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.events;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
+
+@SuppressWarnings("unchecked")
+public class EventBaseBuilder<T extends EventBaseBuilder<T>> {
+
+ private UUID uuid;
+ private UUID subscriptionId;
+ private DateTime requestedDate;
+ private DateTime effectiveDate;
+ private DateTime processedDate;
+
+ private long activeVersion;
+ private boolean isActive;
+ private UUID processingOwner;
+ private DateTime nextAvailableProcessingTime;
+ private IEventLyfecycleState processingState;
+
+
+ public EventBaseBuilder() {
+ this.uuid = UUID.randomUUID();
+ this.isActive = true;
+ this.processingState = IEventLyfecycleState.AVAILABLE;
+ }
+
+ public EventBaseBuilder(EventBaseBuilder<?> copy) {
+ this.uuid = copy.uuid;
+ this.subscriptionId = copy.subscriptionId;
+ this.requestedDate = copy.requestedDate;
+ this.effectiveDate = copy.effectiveDate;
+ this.processedDate = copy.processedDate;
+
+ this.activeVersion = copy.activeVersion;
+ this.isActive = copy.isActive;
+ this.processingOwner = copy.processingOwner;
+ this.nextAvailableProcessingTime = copy.nextAvailableProcessingTime;
+ this.processingState = copy.processingState;
+ }
+
+ public T setUuid(UUID uuid) {
+ this.uuid = uuid;
+ return (T) this;
+ }
+
+ public T setSubscriptionId(UUID subscriptionId) {
+ this.subscriptionId = subscriptionId;
+ return (T) this;
+ }
+
+ public T setRequestedDate(DateTime requestedDate) {
+ this.requestedDate = requestedDate;
+ return (T) this;
+ }
+
+ public T setEffectiveDate(DateTime effectiveDate) {
+ this.effectiveDate = effectiveDate;
+ return (T) this;
+ }
+
+ public T setProcessedDate(DateTime processedDate) {
+ this.processedDate = processedDate;
+ return (T) this;
+ }
+
+ public T setActiveVersion(long activeVersion) {
+ this.activeVersion = activeVersion;
+ return (T) this;
+ }
+
+ public T setActive(boolean isActive) {
+ this.isActive = isActive;
+ return (T) this;
+ }
+
+ public T setProcessingOwner(UUID processingOwner) {
+ this.processingOwner = processingOwner;
+ return (T) this;
+ }
+
+ public T setNextAvailableProcessingTime(DateTime nextAvailableProcessingTime) {
+ this.nextAvailableProcessingTime = nextAvailableProcessingTime;
+ return (T) this;
+ }
+
+ public T setProcessingState(IEventLyfecycleState processingState) {
+ this.processingState = processingState;
+ return (T) this;
+ }
+
+ public UUID getUuid() {
+ return uuid;
+ }
+
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ public DateTime getRequestedDate() {
+ return requestedDate;
+ }
+
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
+ }
+
+ public DateTime getProcessedDate() {
+ return processedDate;
+ }
+
+ public long getActiveVersion() {
+ return activeVersion;
+ }
+
+ public boolean isActive() {
+ return isActive;
+ }
+
+ public UUID getProcessingOwner() {
+ return processingOwner;
+ }
+
+ public DateTime getNextAvailableProcessingTime() {
+ return nextAvailableProcessingTime;
+ }
+
+ public IEventLyfecycleState getProcessingState() {
+ return processingState;
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java
index 9c6bbba..7c2d228 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java
@@ -16,39 +16,23 @@
package com.ning.billing.entitlement.events.phase;
-import java.util.UUID;
import org.joda.time.DateTime;
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.catalog.api.IPlanPhase;
import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.events.EventBase;
-import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class PhaseEvent extends EventBase implements IPhaseEvent {
private final String phaseName;
- public PhaseEvent(UUID subscriptionId, IPlanPhase phase, DateTime requestedDate,
- DateTime effectiveDate, DateTime processedDate, long activeVersion) {
- super(subscriptionId, requestedDate, effectiveDate, processedDate, activeVersion, true);
- this.phaseName = phase.getName();
+ public PhaseEvent(PhaseEventBuilder builder) {
+ super(builder);
+ this.phaseName = builder.getPhaseName();
}
-
- public PhaseEvent(UUID id, UUID subscriptionId, String phaseName, DateTime requestedDate,
- DateTime effectiveDate, DateTime processedDate,
- long activeVersion, boolean isActiveVersion,
- UUID processingOwner, DateTime nextAvailableProcessingTime,
- IEventLyfecycleState processingState) {
- super(id, subscriptionId, requestedDate, effectiveDate, processedDate, activeVersion, isActiveVersion, processingOwner, nextAvailableProcessingTime, processingState);
- this.phaseName = phaseName;
- }
-
-
@Override
public EventType getType() {
return EventType.PHASE;
@@ -76,9 +60,12 @@ public class PhaseEvent extends EventBase implements IPhaseEvent {
public static final IPhaseEvent getNextPhaseEvent(TimedPhase nextTimedPhase, Subscription subscription, DateTime now) {
return (nextTimedPhase == null) ?
null :
- new PhaseEvent(subscription.getId(), nextTimedPhase.getPhase(), now, nextTimedPhase.getStartPhase(),
- now, subscription.getActiveVersion());
-
+ new PhaseEvent(new PhaseEventBuilder()
+ .setSubscriptionId(subscription.getId())
+ .setRequestedDate(now)
+ .setEffectiveDate(nextTimedPhase.getStartPhase())
+ .setProcessedDate(now)
+ .setActiveVersion(subscription.getActiveVersion())
+ .setPhaseName(nextTimedPhase.getPhase().getName()));
}
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.java
new file mode 100644
index 0000000..00ac8e2
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.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.entitlement.events.phase;
+
+import com.ning.billing.entitlement.events.EventBaseBuilder;
+
+public class PhaseEventBuilder extends EventBaseBuilder<PhaseEventBuilder> {
+
+ private String phaseName;
+
+ public PhaseEventBuilder() {
+ super();
+ }
+
+ public PhaseEventBuilder(EventBaseBuilder<PhaseEventBuilder> base) {
+ super(base);
+ }
+
+ public PhaseEventBuilder setPhaseName(String phaseName) {
+ this.phaseName = phaseName;
+ return this;
+ }
+
+ public String getPhaseName() {
+ return phaseName;
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
index e1b9177..d4012dd 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
@@ -36,6 +36,15 @@ public class ApiEventBase extends EventBase implements IApiEvent {
private final String eventPriceList;
+ public ApiEventBase(ApiEventBuilder builder) {
+ super(builder);
+ this.eventType = builder.getEventType();
+ this.eventPriceList = builder.getEventPriceList();
+ this.eventPlan = builder.getEventPlan();
+ this.eventPlanPhase = builder.getEventPlanPhase();
+ }
+
+
public ApiEventBase(UUID subscriptionId, DateTime bundleStartDate, DateTime processed, String planName, String phaseName,
String priceList, DateTime requestedDate, ApiEventType eventType, DateTime effectiveDate, long activeVersion) {
super(subscriptionId, requestedDate, effectiveDate, processed, activeVersion, true);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBuilder.java
new file mode 100644
index 0000000..cd3857e
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBuilder.java
@@ -0,0 +1,71 @@
+/*
+ * 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.events.user;
+
+import com.ning.billing.entitlement.events.EventBaseBuilder;
+
+public class ApiEventBuilder extends EventBaseBuilder<ApiEventBuilder> {
+
+ private ApiEventType eventType;
+ private String eventPlan;
+ private String eventPlanPhase;
+ private String eventPriceList;
+
+ public ApiEventBuilder() {
+ super();
+ }
+
+ public ApiEventBuilder(EventBaseBuilder<ApiEventBuilder> base) {
+ super(base);
+ }
+
+ public ApiEventType getEventType() {
+ return eventType;
+ }
+
+ public String getEventPlan() {
+ return eventPlan;
+ }
+
+ public String getEventPlanPhase() {
+ return eventPlanPhase;
+ }
+
+ public String getEventPriceList() {
+ return eventPriceList;
+ }
+
+ public ApiEventBuilder setEventType(ApiEventType eventType) {
+ this.eventType = eventType;
+ return this;
+ }
+
+ public ApiEventBuilder setEventPlan(String eventPlan) {
+ this.eventPlan = eventPlan;
+ return this;
+ }
+
+ public ApiEventBuilder setEventPlanPhase(String eventPlanPhase) {
+ this.eventPlanPhase = eventPlanPhase;
+ return this;
+ }
+
+ public ApiEventBuilder setEventPriceList(String eventPriceList) {
+ this.eventPriceList = eventPriceList;
+ return this;
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java
index a3806d2..5df11ba 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java
@@ -16,23 +16,10 @@
package com.ning.billing.entitlement.events.user;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
-
public class ApiEventCancel extends ApiEventBase {
- public ApiEventCancel(UUID subscriptionId, DateTime bundleStartDate, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, requestedDate, ApiEventType.CANCEL, effectiveDate, version);
- }
- public ApiEventCancel(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
- String priceList, DateTime requestedDate, DateTime effectiveDate, long activeVersion,
- boolean isActive, UUID processingOwner, DateTime nextAvailableProcessingTime,IEventLyfecycleState processingState) {
- super(id, subscriptionId, processed, eventPlan, eventPhase, priceList, requestedDate, ApiEventType.CANCEL, effectiveDate,
- activeVersion, isActive, processingOwner, nextAvailableProcessingTime, processingState);
+ public ApiEventCancel(ApiEventBuilder builder) {
+ super(builder.setEventType(ApiEventType.CANCEL));
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java
index 40584f5..3770a2f 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java
@@ -17,25 +17,10 @@
package com.ning.billing.entitlement.events.user;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
-
public class ApiEventChange extends ApiEventBase {
- public ApiEventChange(UUID subscriptionId, DateTime bundleStartDate, DateTime now, String planName, String phaseName, String priceList,
- DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, planName, phaseName, priceList, requestedDate, ApiEventType.CHANGE, effectiveDate, version);
- }
-
- public ApiEventChange(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase, String priceList,
- DateTime requestedDate, DateTime effectiveDate, long activeVersion,
- boolean isActive, UUID processingOwner, DateTime nextAvailableProcessingTime,IEventLyfecycleState processingState) {
- super(id, subscriptionId, processed, eventPlan, eventPhase, priceList, requestedDate, ApiEventType.CHANGE, effectiveDate,
- activeVersion, isActive, processingOwner, nextAvailableProcessingTime, processingState);
+ public ApiEventChange(ApiEventBuilder builder) {
+ super(builder.setEventType(ApiEventType.CHANGE));
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java
index 2b12e7e..df1879d 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java
@@ -17,26 +17,10 @@
package com.ning.billing.entitlement.events.user;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class ApiEventCreate extends ApiEventBase {
-
- public ApiEventCreate(UUID subscriptionId, DateTime bundleStartDate, DateTime now, String planName, String phaseName, String priceList,
- DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, planName, phaseName, priceList, requestedDate, ApiEventType.CREATE, effectiveDate, version);
- }
-
-
- public ApiEventCreate(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase, String priceList,
- DateTime requestedDate, DateTime effectiveDate, long activeVersion,
- boolean isActive, UUID processingOwner, DateTime nextAvailableProcessingTime,IEventLyfecycleState processingState) {
- super(id, subscriptionId, processed, eventPlan, eventPhase, priceList, requestedDate, ApiEventType.CREATE, effectiveDate,
- activeVersion, isActive, processingOwner, nextAvailableProcessingTime, processingState);
+ public ApiEventCreate(ApiEventBuilder builder) {
+ super(builder.setEventType(ApiEventType.CREATE));
}
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java
index a6ff4b4..8574cfc 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java
@@ -17,23 +17,11 @@
package com.ning.billing.entitlement.events.user;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class ApiEventPause extends ApiEventBase {
- public ApiEventPause(UUID subscriptionId, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, null, now, requestedDate, ApiEventType.PAUSE, effectiveDate, version);
- }
- public ApiEventPause(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
- String priceList, DateTime requestedDate, DateTime effectiveDate, long activeVersion,
- boolean isActive, UUID processingOwner, DateTime nextAvailableProcessingTime,IEventLyfecycleState processingState) {
- super(id, subscriptionId, processed, eventPlan, eventPhase, priceList, requestedDate, ApiEventType.PAUSE, effectiveDate,
- activeVersion, isActive, processingOwner, nextAvailableProcessingTime, processingState);
+ public ApiEventPause(ApiEventBuilder builder) {
+ super(builder.setEventType(ApiEventType.PAUSE));
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java
index f8bf26f..34f8f87 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java
@@ -17,25 +17,9 @@
package com.ning.billing.entitlement.events.user;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
-import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
-
-
public class ApiEventResume extends ApiEventBase {
- public ApiEventResume(UUID subscriptionId, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, null, now, requestedDate, ApiEventType.RESUME, effectiveDate, version);
+ public ApiEventResume(ApiEventBuilder builder) {
+ super(builder.setEventType(ApiEventType.RESUME));
}
-
- public ApiEventResume(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
- String priceList, DateTime requestedDate, DateTime effectiveDate, long activeVersion,
- boolean isActive, UUID processingOwner, DateTime nextAvailableProcessingTime,IEventLyfecycleState processingState) {
- super(id, subscriptionId, processed, eventPlan, eventPhase, priceList, requestedDate, ApiEventType.RESUME, effectiveDate,
- activeVersion, isActive, processingOwner, nextAvailableProcessingTime, processingState);
- }
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java
index b5433f1..93d8029 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java
@@ -16,21 +16,9 @@
package com.ning.billing.entitlement.events.user;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
-
public class ApiEventUncancel extends ApiEventBase {
- public ApiEventUncancel(UUID subscriptionId, DateTime bundleStartDate, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, requestedDate, ApiEventType.UNCANCEL, effectiveDate, version);
- }
-
- public ApiEventUncancel(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
- String priceList, DateTime requestedDate, DateTime effectiveDate, long activeVersion,
- boolean isActive, UUID processingOwner, DateTime nextAvailableProcessingTime,IEventLyfecycleState processingState) {
- super(id, subscriptionId, processed, eventPlan, eventPhase, priceList, requestedDate, ApiEventType.UNCANCEL, effectiveDate,
- activeVersion, isActive, processingOwner, nextAvailableProcessingTime, processingState);
+ public ApiEventUncancel(ApiEventBuilder builder) {
+ super(builder.setEventType(ApiEventType.UNCANCEL));
}
}
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.sql.stg
index 22a85f8..045a241 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/IBundleSqlDao.sql.stg
@@ -27,6 +27,18 @@ getBundleFromId(id) ::= <<
;
>>
+getBundleFromKey(name) ::= <<
+ select
+ id
+ , start_dt
+ , name
+ , account_id
+ from bundles
+ where
+ name = :name
+ ;
+>>
+
getBundleFromAccount(account_id) ::= <<
select
@@ -39,3 +51,4 @@ getBundleFromAccount(account_id) ::= <<
account_id = :account_id
;
>>
+
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
index 5b5100b..1ba79af 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
@@ -17,11 +17,16 @@
package com.ning.billing.entitlement.api;
import java.util.EmptyStackException;
+import java.util.Iterator;
+import java.util.List;
import java.util.Stack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
import com.google.common.eventbus.Subscribe;
import com.ning.billing.entitlement.api.user.ISubscriptionTransition;
import com.ning.billing.util.eventbus.IEventBus;
@@ -30,7 +35,7 @@ public class ApiTestListener {
private static final Logger log = LoggerFactory.getLogger(ApiTestListener.class);
- private final Stack<NextEvent> nextExpectedEvent;
+ private final List<NextEvent> nextExpectedEvent;
private volatile boolean completed;
@@ -79,7 +84,7 @@ public class ApiTestListener {
public void pushExpectedEvent(NextEvent next) {
synchronized (this) {
- nextExpectedEvent.push(next);
+ nextExpectedEvent.add(next);
completed = false;
}
}
@@ -113,17 +118,22 @@ public class ApiTestListener {
log.debug("notifyIfStackEmpty EXIT");
}
- private void assertEqualsNicely(NextEvent expected, NextEvent real) {
- if (expected != real) {
- System.err.println("Expected event " + expected + " got " + real);
- try {
- NextEvent next = nextExpectedEvent.pop();
- while (next != null) {
- System.err.println("Also got event " + next);
- next = nextExpectedEvent.pop();
- }
- } catch (EmptyStackException ignore) {
+ private void assertEqualsNicely(NextEvent expected) {
+
+ boolean foundIt = false;
+ Iterator<NextEvent> it = nextExpectedEvent.iterator();
+ while (it.hasNext()) {
+ NextEvent ev = it.next();
+ if (ev == expected) {
+ it.remove();
+ foundIt = true;
+ break;
}
+ }
+
+ if (!foundIt) {
+ Joiner joiner = Joiner.on(" ");
+ System.err.println("Expected event " + expected + " got " + joiner.join(nextExpectedEvent));
System.exit(1);
}
}
@@ -131,35 +141,35 @@ public class ApiTestListener {
public void subscriptionCreated(ISubscriptionTransition created) {
log.debug("-> Got event CREATED");
- assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.CREATE);
+ assertEqualsNicely(NextEvent.CREATE);
notifyIfStackEmpty();
}
public void subscriptionCancelled(ISubscriptionTransition cancelled) {
log.debug("-> Got event CANCEL");
- assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.CANCEL);
+ assertEqualsNicely(NextEvent.CANCEL);
notifyIfStackEmpty();
}
public void subscriptionChanged(ISubscriptionTransition changed) {
log.debug("-> Got event CHANGE");
- assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.CHANGE);
+ assertEqualsNicely(NextEvent.CHANGE);
notifyIfStackEmpty();
}
public void subscriptionPaused(ISubscriptionTransition paused) {
log.debug("-> Got event PAUSE");
- assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.PAUSE);
+ assertEqualsNicely(NextEvent.PAUSE);
notifyIfStackEmpty();
}
public void subscriptionResumed(ISubscriptionTransition resumed) {
log.debug("-> Got event RESUME");
- assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.RESUME);
+ assertEqualsNicely(NextEvent.RESUME);
notifyIfStackEmpty();
}
@@ -167,7 +177,7 @@ public class ApiTestListener {
public void subscriptionPhaseChanged(
ISubscriptionTransition phaseChanged) {
log.debug("-> Got event PHASE");
- assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.PHASE);
+ assertEqualsNicely(NextEvent.PHASE);
notifyIfStackEmpty();
}
}
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 64f69c3..538d5dd 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
@@ -39,6 +39,38 @@ import com.ning.billing.util.clock.Clock;
public abstract class TestUserApiCreate extends TestUserApiBase {
+
+ protected void testCreateWithRequestedDateReal() {
+ log.info("Starting testCreateWithRequestedDate");
+ try {
+
+ DateTime init = clock.getUTCNow();
+ DateTime requestedDate = init.minusYears(1);
+
+ String productName = "Shotgun";
+ BillingPeriod term = BillingPeriod.MONTHLY;
+ String planSetName = IPriceListSet.DEFAULT_PRICELIST_NAME;
+
+
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ testListener.pushExpectedEvent(NextEvent.CREATE);
+
+
+ Subscription subscription = (Subscription) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, requestedDate);
+ assertNotNull(subscription);
+
+ assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
+ //assertEquals(subscription.getAccount(), account.getId());
+ assertEquals(subscription.getBundleId(), bundle.getId());
+ assertEquals(subscription.getStartDate(), requestedDate);
+
+ assertTrue(testListener.isCompleted(5000));
+
+ } catch (EntitlementUserApiException e) {
+ Assert.fail(e.getMessage());
+ }
+ }
+
protected void testSimpleCreateSubscriptionReal() {
log.info("Starting testSimpleCreateSubscription");
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
index 429652c..8c1fa63 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
@@ -33,6 +33,11 @@ public class TestUserApiCreateMemory extends TestUserApiCreate {
}
@Test(enabled=true, groups={"fast"})
+ public void testCreateWithRequestedDate() {
+ invokeRealMethod(this);
+ }
+
+ @Test(enabled=true, groups={"fast"})
public void testSimpleCreateSubscription() {
invokeRealMethod(this);
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java
index 328976f..77ee57d 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java
@@ -32,6 +32,11 @@ public class TestUserApiCreateSql extends TestUserApiCreate {
}
@Test(enabled=true, groups={"sql"})
+ public void testCreateWithRequestedDate() {
+ invokeRealMethod(this);
+ }
+
+ @Test(enabled=true, groups={"sql"})
public void testSimpleCreateSubscription() {
invokeRealMethod(this);
}
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 79aef55..b5848ce 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
@@ -16,12 +16,14 @@
package com.ning.billing.entitlement.engine.core;
+import java.util.Collection;
import java.util.List;
import com.google.inject.Inject;
import com.ning.billing.config.IEntitlementConfig;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.entitlement.events.IEvent;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.clock.IClock;
public class ApiEventProcessorMemoryMock extends ApiEventProcessorBase {
@@ -51,4 +53,11 @@ public class ApiEventProcessorMemoryMock extends ApiEventProcessorBase {
log.info(String.format("doProcessEvents : clearEvents"));
return true;
}
+
+
+ @Override
+ protected boolean doProcessEventsFromList(int sequenceId,
+ Collection<IEvent> events) {
+ throw new EntitlementError("Method not implemented");
+ }
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java
index 1e043eb..e4d2559 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java
@@ -17,6 +17,7 @@
package com.ning.billing.entitlement.engine.dao;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
@@ -35,6 +36,7 @@ import com.ning.billing.config.IEntitlementConfig;
import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.api.user.ISubscriptionBundle;
import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBuilder;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.entitlement.events.IEvent.EventType;
@@ -53,6 +55,8 @@ public class EntitlementDaoMemoryMock implements IEntitlementDao, IEntitlementDa
private final IClock clock;
private final IEntitlementConfig config;
+
+
@Inject
public EntitlementDaoMemoryMock(IClock clock, IEntitlementConfig config) {
super();
@@ -108,6 +112,18 @@ public class EntitlementDaoMemoryMock implements IEntitlementDao, IEntitlementDa
}
@Override
+ public List<ISubscription> getSubscriptionsForKey(String bundleKey) {
+
+ for (ISubscriptionBundle cur : bundles) {
+ if (cur.getKey().equals(bundleKey)) {
+ return getSubscriptions(cur.getId());
+ }
+ }
+ return Collections.emptyList();
+ }
+
+
+ @Override
public ISubscription createSubscription(Subscription subscription, List<IEvent> initalEvents) {
synchronized(events) {
@@ -199,7 +215,7 @@ public class EntitlementDaoMemoryMock implements IEntitlementDao, IEntitlementDa
}
@Override
- public void clearEventsReady(UUID ownerId, List<IEvent> cleared) {
+ public void clearEventsReady(UUID ownerId, Collection<IEvent> cleared) {
synchronized(events) {
for (IEvent cur : cleared) {
if (cur.getOwner().equals(ownerId)) {
@@ -212,8 +228,7 @@ public class EntitlementDaoMemoryMock implements IEntitlementDao, IEntitlementDa
}
private ISubscription buildSubscription(Subscription in) {
- return new Subscription(in.getId(), in.getBundleId(), in.getCategory(), in.getBundleStartDate(),
- in.getStartDate(), in.getChargedThroughDate(), in.getPaidThroughDate(), in.getActiveVersion());
+ return new Subscription(new SubscriptionBuilder(in), true);
}
@Override
@@ -328,4 +343,5 @@ public class EntitlementDaoMemoryMock implements IEntitlementDao, IEntitlementDa
}
}
}
+
}
invoice/pom.xml 2(+1 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 0958498..771b2c5 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.14-SNAPSHOT</version>
+ <version>0.0.16-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 e69d221..3592a7b 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.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
pom.xml 40(+24 -16)
diff --git a/pom.xml b/pom.xml
index 4ed2b26..58ab9d3 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.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<name>killbill</name>
<description>Library for managing recurring subscriptions and the associated billing</description>
<url>http://github.com/ning/killbill</url>
@@ -332,21 +332,6 @@
</execution>
</executions>
</plugin>
- <!-- Add plugins bound to verify phase before gpg plugin -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-gpg-plugin</artifactId>
- <version>1.4</version>
- <executions>
- <execution>
- <id>sign-artifacts</id>
- <phase>verify</phase>
- <goals>
- <goal>sign</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
@@ -394,6 +379,29 @@
</plugin>
</plugins>
</build>
+ <profiles>
+ <profile>
+ <id>sonatype-oss-release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.4</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
<reporting>
<plugins>
<plugin>
util/pom.xml 2(+1 -1)
diff --git a/util/pom.xml b/util/pom.xml
index 3f3a40e..e77c581 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.14-SNAPSHOT</version>
+ <version>0.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>
diff --git a/util/src/main/java/com/ning/billing/util/clock/Clock.java b/util/src/main/java/com/ning/billing/util/clock/Clock.java
index 43819ba..a60b393 100644
--- a/util/src/main/java/com/ning/billing/util/clock/Clock.java
+++ b/util/src/main/java/com/ning/billing/util/clock/Clock.java
@@ -29,7 +29,7 @@ public class Clock implements IClock {
@Override
public DateTime getNow(DateTimeZone tz) {
DateTime result = new DateTime(tz);
- return result.minus(result.getMillisOfSecond());
+ return truncateMs(result);
}
@Override
@@ -38,6 +38,10 @@ public class Clock implements IClock {
}
+ public static DateTime truncateMs(DateTime input) {
+ return input.minus(input.getMillisOfSecond());
+ }
+
public static DateTime addDuration(DateTime input, List<IDuration> durations) {
DateTime result = input;