killbill-aplcache
Changes
analytics/pom.xml 23(+23 -0)
analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java 4(+2 -2)
beatrix/pom.xml 10(+10 -0)
bin/cleanAndInstall 23(+23 -0)
bin/db-helper 3(+1 -2)
catalog/pom.xml 6(+6 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java 87(+87 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java 222(+0 -222)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java 45(+26 -19)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java 49(+38 -11)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java 24(+18 -6)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java 22(+11 -11)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java 3(+2 -1)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java 3(+2 -1)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java 5(+3 -2)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java 3(+2 -1)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java 18(+9 -9)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java 2(+1 -1)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java 4(+2 -2)
invoice/pom.xml 12(+12 -0)
invoice/src/main/resources/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.sql.stg 5(+3 -2)
invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java 20(+11 -9)
invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java 33(+19 -14)
invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java 29(+22 -7)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java 7(+4 -3)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java 5(+3 -2)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java 7(+4 -3)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java 3(+2 -1)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java 7(+4 -3)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java 9(+5 -4)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java 13(+7 -6)
junction/pom.xml 131(+131 -0)
junction/src/main/java/com/ning/billing/junction/api/billing/BlockingEventCalculator.java 290(+290 -0)
junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java 89(+89 -0)
junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java 98(+98 -0)
junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java 118(+118 -0)
junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEvent.java 28(+19 -9)
junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultBillingEvent.java 10(+8 -2)
junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultEntitlementBillingApi.java 124(+66 -58)
junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestOverdueEventCalculator.java 722(+722 -0)
junction/src/test/resources/log4j.xml 40(+40 -0)
overdue/pom.xml 138(+138 -0)
overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java 112(+112 -0)
overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java 73(+73 -0)
overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java 107(+107 -0)
overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculator.java 102(+102 -0)
overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java 143(+143 -0)
overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckNotifier.java 36(+36 -0)
overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java 222(+222 -0)
overdue/src/test/resources/log4j.xml 40(+40 -0)
overdue/src/test/resources/OverdueConfig.xml 20(+20 -0)
overdue/src/test/resources/OverdueConfigSchema.xsd 106(+106 -0)
payment/pom.xml 5(+5 -0)
pom.xml 17(+17 -0)
Details
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index d6752e9..efeb07d 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -256,7 +256,7 @@ public class DefaultAccount extends ExtendedEntityBase implements Account {
@Override
public MutableAccountData toMutableAccountData() {
- return new MutableAccountData(this);
+ return new DefaultMutableAccountData(this);
}
@Override
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccountService.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccountService.java
index ca2e213..af3d2a7 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccountService.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccountService.java
@@ -16,32 +16,17 @@
package com.ning.billing.account.api;
-import com.google.inject.Inject;
-import com.ning.billing.lifecycle.LifecycleHandlerType;
-import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
public class DefaultAccountService implements AccountService {
private static final String ACCOUNT_SERVICE_NAME = "account-service";
- private final AccountUserApi accountApi;
-
- @Inject
- public DefaultAccountService(AccountUserApi api) {
- this.accountApi = api;
- }
-
- @Override
+ @Override
public String getName() {
return ACCOUNT_SERVICE_NAME;
}
- @Override
- public AccountUserApi getAccountUserApi() {
- return accountApi;
- }
-
- @LifecycleHandlerType(LifecycleLevel.INIT_SERVICE)
- public void initialize() {
- }
+// @LifecycleHandlerType(LifecycleLevel.INIT_SERVICE)
+// public void initialize() {
+// }
}
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultMutableAccountData.java b/account/src/main/java/com/ning/billing/account/api/DefaultMutableAccountData.java
new file mode 100644
index 0000000..4476130
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultMutableAccountData.java
@@ -0,0 +1,333 @@
+/*
+ * 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.account.api;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.tag.TagStore;
+
+public class DefaultMutableAccountData implements AccountData, MutableAccountData {
+ private String externalKey;
+ private String email;
+ private String name;
+ private int firstNameLength;
+ private Currency currency;
+ private int billCycleDay;
+ private String paymentProviderName;
+ private DateTimeZone timeZone;
+ private String locale;
+ private String address1;
+ private String address2;
+ private String companyName;
+ private String city;
+ private String stateOrProvince;
+ private String country;
+ private String postalCode;
+ private String phone;
+
+ public DefaultMutableAccountData(String externalKey, String email, String name,
+ int firstNameLength, Currency currency, int billCycleDay,
+ String paymentProviderName, TagStore tags, DateTimeZone timeZone,
+ String locale, String address1, String address2,
+ String companyName, String city, String stateOrProvince,
+ String country, String postalCode, String phone,
+ DateTime createdDate, DateTime updatedDate) {
+ super();
+ this.externalKey = externalKey;
+ this.email = email;
+ this.name = name;
+ this.firstNameLength = firstNameLength;
+ this.currency = currency;
+ this.billCycleDay = billCycleDay;
+ this.paymentProviderName = paymentProviderName;
+ this.timeZone = timeZone;
+ this.locale = locale;
+ this.address1 = address1;
+ this.address2 = address2;
+ this.companyName = companyName;
+ this.city = city;
+ this.stateOrProvince = stateOrProvince;
+ this.country = country;
+ this.postalCode = postalCode;
+ this.phone = phone;
+ }
+
+ public DefaultMutableAccountData(AccountData accountData) {
+ super();
+ this.externalKey = accountData.getExternalKey();
+ this.email = accountData.getEmail();
+ this.name = accountData.getName();
+ this.firstNameLength = accountData.getFirstNameLength();
+ this.currency = accountData.getCurrency();
+ this.billCycleDay = accountData.getBillCycleDay();
+ this.paymentProviderName = accountData.getPaymentProviderName();
+ this.timeZone = accountData.getTimeZone();
+ this.locale = accountData.getLocale();
+ this.address1 = accountData.getAddress1();
+ this.address2 = accountData.getAddress2();
+ this.companyName = accountData.getCompanyName();
+ this.city = accountData.getCity();
+ this.stateOrProvince = accountData.getStateOrProvince();
+ this.country = accountData.getCountry();
+ this.postalCode = accountData.getPostalCode();
+ this.phone = accountData.getPhone();
+ }
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getExternalKey()
+ */
+ @Override
+ public String getExternalKey() {
+ return externalKey;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getEmail()
+ */
+ @Override
+ public String getEmail() {
+ return email;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getName()
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getFirstNameLength()
+ */
+ @Override
+ public int getFirstNameLength() {
+ return firstNameLength;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getCurrency()
+ */
+ @Override
+ public Currency getCurrency() {
+ return currency;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getBillCycleDay()
+ */
+ @Override
+ public int getBillCycleDay() {
+ return billCycleDay;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getPaymentProviderName()
+ */
+ @Override
+ public String getPaymentProviderName() {
+ return paymentProviderName;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getTimeZone()
+ */
+ @Override
+ public DateTimeZone getTimeZone() {
+ return timeZone;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getLocale()
+ */
+ @Override
+ public String getLocale() {
+ return locale;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getAddress1()
+ */
+ @Override
+ public String getAddress1() {
+ return address1;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getAddress2()
+ */
+ @Override
+ public String getAddress2() {
+ return address2;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getCompanyName()
+ */
+ @Override
+ public String getCompanyName() {
+ return companyName;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getCity()
+ */
+ @Override
+ public String getCity() {
+ return city;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getStateOrProvince()
+ */
+ @Override
+ public String getStateOrProvince() {
+ return stateOrProvince;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getCountry()
+ */
+ @Override
+ public String getCountry() {
+ return country;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getPostalCode()
+ */
+ @Override
+ public String getPostalCode() {
+ return postalCode;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#getPhone()
+ */
+ @Override
+ public String getPhone() {
+ return phone;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setExternalKey(java.lang.String)
+ */
+ @Override
+ public void setExternalKey(String externalKey) {
+ this.externalKey = externalKey;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setEmail(java.lang.String)
+ */
+ @Override
+ public void setEmail(String email) {
+ this.email = email;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setName(java.lang.String)
+ */
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setFirstNameLength(int)
+ */
+ @Override
+ public void setFirstNameLength(int firstNameLength) {
+ this.firstNameLength = firstNameLength;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setCurrency(com.ning.billing.catalog.api.Currency)
+ */
+ @Override
+ public void setCurrency(Currency currency) {
+ this.currency = currency;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setBillCycleDay(int)
+ */
+ @Override
+ public void setBillCycleDay(int billCycleDay) {
+ this.billCycleDay = billCycleDay;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setPaymentProviderName(java.lang.String)
+ */
+ @Override
+ public void setPaymentProviderName(String paymentProviderName) {
+ this.paymentProviderName = paymentProviderName;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setTimeZone(org.joda.time.DateTimeZone)
+ */
+ @Override
+ public void setTimeZone(DateTimeZone timeZone) {
+ this.timeZone = timeZone;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setLocale(java.lang.String)
+ */
+ @Override
+ public void setLocale(String locale) {
+ this.locale = locale;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setAddress1(java.lang.String)
+ */
+ @Override
+ public void setAddress1(String address1) {
+ this.address1 = address1;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setAddress2(java.lang.String)
+ */
+ @Override
+ public void setAddress2(String address2) {
+ this.address2 = address2;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setCompanyName(java.lang.String)
+ */
+ @Override
+ public void setCompanyName(String companyName) {
+ this.companyName = companyName;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setCity(java.lang.String)
+ */
+ @Override
+ public void setCity(String city) {
+ this.city = city;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setStateOrProvince(java.lang.String)
+ */
+ @Override
+ public void setStateOrProvince(String stateOrProvince) {
+ this.stateOrProvince = stateOrProvince;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setCountry(java.lang.String)
+ */
+ @Override
+ public void setCountry(String country) {
+ this.country = country;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setPostalCode(java.lang.String)
+ */
+ @Override
+ public void setPostalCode(String postalCode) {
+ this.postalCode = postalCode;
+ }
+ /* (non-Javadoc)
+ * @see com.ning.billing.account.api.MutableAccountData#setPhone(java.lang.String)
+ */
+ @Override
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
index 37f5322..6f8d856 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
@@ -26,7 +26,7 @@ import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.account.api.AccountData;
import com.ning.billing.account.api.DefaultAccount;
import com.ning.billing.account.api.MigrationAccountData;
-import com.ning.billing.account.api.MutableAccountData;
+import com.ning.billing.account.api.DefaultMutableAccountData;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallContextFactory;
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 70beb4c..e3009e8 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
@@ -24,6 +24,7 @@ import com.ning.billing.account.api.DefaultAccountService;
import com.ning.billing.account.api.user.DefaultAccountUserApi;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.AuditedAccountDao;
+import com.ning.billing.util.glue.RealImplementation;
public class AccountModule extends AbstractModule {
@@ -35,7 +36,7 @@ public class AccountModule extends AbstractModule {
}
protected void installAccountUserApi() {
- bind(AccountUserApi.class).to(DefaultAccountUserApi.class).asEagerSingleton();
+ bind(AccountUserApi.class).annotatedWith(RealImplementation.class).to(DefaultAccountUserApi.class).asEagerSingleton();
}
private void installAccountService() {
analytics/pom.xml 23(+23 -0)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index a92d088..d560cc6 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -65,11 +65,34 @@
<dependency>
<groupId>com.ning.billing</groupId>
<artifactId>killbill-catalog</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-entitlement</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
<artifactId>killbill-entitlement</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
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 71e3402..ddcc9c7 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
@@ -91,7 +91,7 @@ public class BusinessSubscription
*/
BusinessSubscription(final Subscription subscription, final Currency currency)
{
- this(subscription.getCurrentPriceList(), subscription.getCurrentPlan(), subscription.getCurrentPhase(), currency, subscription.getStartDate(), subscription.getState(), subscription.getId(), subscription.getBundleId());
+ this(subscription.getCurrentPriceList() == null ? null : subscription.getCurrentPriceList().getName(), subscription.getCurrentPlan(), subscription.getCurrentPhase(), currency, subscription.getStartDate(), subscription.getState(), subscription.getId(), subscription.getBundleId());
}
public BusinessSubscription(final String priceList, final Plan currentPlan, final PlanPhase currentPhase, final Currency currency, final DateTime startDate, final SubscriptionState state, final UUID subscriptionId, final UUID bundleId)
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 2bb02ea..82457ef 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
@@ -115,7 +115,7 @@ public class BusinessSubscriptionTransitionRecorder
prevSubscription = null;
}
else {
- prevSubscription = new BusinessSubscription(transition.getPreviousPriceList(), transition.getPreviousPlan(), transition.getPreviousPhase(), currency, previousEffectiveTransitionTime, transition.getPreviousState(), transition.getSubscriptionId(), transition.getBundleId());
+ prevSubscription = new BusinessSubscription(transition.getPreviousPriceList() == null ? null : transition.getPreviousPriceList().getName(), transition.getPreviousPlan(), transition.getPreviousPhase(), currency, previousEffectiveTransitionTime, transition.getPreviousState(), transition.getSubscriptionId(), transition.getBundleId());
}
final BusinessSubscription nextSubscription;
@@ -124,7 +124,7 @@ public class BusinessSubscriptionTransitionRecorder
nextSubscription = null;
}
else {
- nextSubscription = new BusinessSubscription(transition.getNextPriceList(), transition.getNextPlan(), transition.getNextPhase(), currency, transition.getEffectiveTransitionTime(), transition.getNextState(), transition.getSubscriptionId(), transition.getBundleId());
+ nextSubscription = new BusinessSubscription(transition.getNextPriceList() == null ? null : transition.getNextPriceList().getName(), transition.getNextPlan(), transition.getNextPhase(), currency, transition.getEffectiveTransitionTime(), transition.getNextState(), transition.getSubscriptionId(), transition.getBundleId());
}
record(transition.getId(), transitionKey, accountKey, transition.getRequestedTransitionTime(), event, prevSubscription, nextSubscription);
diff --git a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
index 1aafa7c..ca58034 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
@@ -16,25 +16,23 @@
package com.ning.billing.analytics;
-import com.ning.billing.invoice.glue.InvoiceModule;
-import com.ning.billing.payment.setup.PaymentModule;
-import com.ning.billing.util.glue.CallContextModule;
-import com.ning.billing.util.glue.FieldStoreModule;
-import com.ning.billing.util.tag.dao.TagDefinitionSqlDao;
import org.skife.jdbi.v2.IDBI;
+
import com.ning.billing.account.glue.AccountModule;
import com.ning.billing.analytics.setup.AnalyticsModule;
-import com.ning.billing.catalog.glue.CatalogModule;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.glue.EntitlementModule;
-
+import com.ning.billing.invoice.glue.InvoiceModule;
+import com.ning.billing.junction.MockBlockingModule;
+import com.ning.billing.junction.glue.JunctionModule;
+import com.ning.billing.payment.setup.PaymentModule;
import com.ning.billing.util.glue.BusModule;
-
+import com.ning.billing.util.glue.CallContextModule;
import com.ning.billing.util.glue.ClockModule;
+import com.ning.billing.util.glue.FieldStoreModule;
import com.ning.billing.util.glue.NotificationQueueModule;
import com.ning.billing.util.glue.TagStoreModule;
-
-import java.lang.reflect.Field;
+import com.ning.billing.util.tag.dao.TagDefinitionSqlDao;
public class AnalyticsTestModule extends AnalyticsModule
{
@@ -49,13 +47,13 @@ public class AnalyticsTestModule extends AnalyticsModule
install(new FieldStoreModule());
install(new TagStoreModule());
install(new AccountModule());
- install(new CatalogModule());
install(new BusModule());
install(new EntitlementModule());
install(new InvoiceModule());
install(new PaymentModule());
install(new TagStoreModule());
install(new NotificationQueueModule());
+ install(new JunctionModule());
// Install the Dao layer
final MysqlTestingHelper helper = new MysqlTestingHelper();
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 ac25c74..71cbeb1 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
@@ -26,11 +26,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.UUID;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.testng.Assert;
@@ -56,10 +51,13 @@ import com.ning.billing.analytics.MockPlan;
import com.ning.billing.analytics.MockProduct;
import com.ning.billing.analytics.dao.BusinessAccountDao;
import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDao;
+import com.ning.billing.catalog.MockCatalogModule;
+import com.ning.billing.catalog.MockPriceList;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.dbi.MysqlTestingHelper;
@@ -71,6 +69,7 @@ import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceCreationEvent;
import com.ning.billing.invoice.api.user.DefaultInvoiceCreationNotification;
import com.ning.billing.invoice.dao.InvoiceDao;
@@ -81,6 +80,10 @@ import com.ning.billing.payment.api.PaymentAttempt;
import com.ning.billing.payment.api.PaymentInfoEvent;
import com.ning.billing.payment.dao.PaymentDao;
import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.DefaultClock;
import com.ning.billing.util.tag.DefaultTagDefinition;
@@ -88,7 +91,7 @@ import com.ning.billing.util.tag.DescriptiveTag;
import com.ning.billing.util.tag.Tag;
import com.ning.billing.util.tag.dao.TagDefinitionSqlDao;
-@Guice(modules = AnalyticsTestModule.class)
+@Guice(modules = {AnalyticsTestModule.class, MockCatalogModule.class})
public class TestAnalyticsService {
private static final UUID ID = UUID.randomUUID();
private static final String KEY = "12345";
@@ -208,7 +211,7 @@ public class TestAnalyticsService {
final UUID subscriptionId = UUID.randomUUID();
final DateTime effectiveTransitionTime = clock.getUTCNow();
final DateTime requestedTransitionTime = clock.getUTCNow();
- final String priceList = "something";
+ final PriceList priceList = new MockPriceList().setName("something");
transition = new SubscriptionTransitionData(
ID,
@@ -237,7 +240,7 @@ public class TestAnalyticsService {
requestedTransitionTime,
BusinessSubscriptionEvent.subscriptionCreated(plan),
null,
- new BusinessSubscription(priceList, plan, phase, ACCOUNT_CURRENCY, effectiveTransitionTime, Subscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
+ new BusinessSubscription(priceList.getName(), plan, phase, ACCOUNT_CURRENCY, effectiveTransitionTime, Subscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
);
}
@@ -248,7 +251,7 @@ public class TestAnalyticsService {
private void createInvoiceAndPaymentCreationEvents(final Account account) {
final DefaultInvoice invoice = new DefaultInvoice(account.getId(), clock.getUTCNow(), clock.getUTCNow(), ACCOUNT_CURRENCY);
final FixedPriceInvoiceItem invoiceItem = new FixedPriceInvoiceItem(
- UUID.randomUUID(), invoice.getId(), account.getId(), UUID.randomUUID(), "somePlan", "somePhase", clock.getUTCNow(), clock.getUTCNow().plusDays(1),
+ UUID.randomUUID(), invoice.getId(), account.getId(), UUID.randomUUID(), UUID.randomUUID(), "somePlan", "somePhase", clock.getUTCNow(), clock.getUTCNow().plusDays(1),
INVOICE_AMOUNT, ACCOUNT_CURRENCY, context.getUserName(), clock.getUTCNow());
invoice.addInvoiceItem(invoiceItem);
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 4942118..5e94f15 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
@@ -19,13 +19,13 @@ package com.ning.billing.analytics;
import java.util.List;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.MutableAccountData;
import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.customfield.CustomField;
import com.ning.billing.util.tag.Tag;
import com.ning.billing.util.tag.TagDefinition;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java
index 06e3d79..f9989af 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java
@@ -21,14 +21,15 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
import org.joda.time.DateTime;
+
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
-
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.util.callcontext.CallContext;
public class MockEntitlementUserApi implements EntitlementUserApi
{
@@ -72,6 +73,11 @@ public class MockEntitlementUserApi implements EntitlementUserApi
{
return key;
}
+
+ @Override
+ public OverdueState<SubscriptionBundle> getOverdueState() {
+ throw new UnsupportedOperationException();
+ }
};
}
@@ -119,4 +125,9 @@ public class MockEntitlementUserApi implements EntitlementUserApi
public DateTime getNextBillingDate(UUID account) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public Subscription getBaseSubscription(UUID bundleId) {
+ throw new UnsupportedOperationException();
+ }
}
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 6a83560..7144edb 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -16,24 +16,26 @@
package com.ning.billing.analytics;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.customfield.CustomField;
-
import com.ning.billing.util.tag.Tag;
import com.ning.billing.util.tag.TagDefinition;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-import java.util.List;
-import java.util.UUID;
public class MockSubscription implements Subscription
{
@@ -118,7 +120,7 @@ public class MockSubscription implements Subscription
}
@Override
- public String getCurrentPriceList()
+ public PriceList getCurrentPriceList()
{
return null;
}
@@ -243,4 +245,9 @@ public class MockSubscription implements Subscription
public boolean processPayment() {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public List<SubscriptionEventTransition> getBillingTransitions() {
+ throw new UnsupportedOperationException();
+ }
}
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 be061f9..e1c9e9d 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -16,24 +16,27 @@
package com.ning.billing.analytics;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import javax.annotation.Nullable;
-import java.util.UUID;
public class TestAnalyticsListener
{
@@ -47,7 +50,7 @@ public class TestAnalyticsListener
private final Product product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
private final Plan plan = new MockPlan("platinum-monthly", product);
private final PlanPhase phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
- private final String priceList = null;
+ private final PriceList priceList = null;
private AnalyticsListener listener;
diff --git a/api/src/main/java/com/ning/billing/account/api/Account.java b/api/src/main/java/com/ning/billing/account/api/Account.java
index 3f1e383..65b97b5 100644
--- a/api/src/main/java/com/ning/billing/account/api/Account.java
+++ b/api/src/main/java/com/ning/billing/account/api/Account.java
@@ -16,12 +16,12 @@
package com.ning.billing.account.api;
-import com.ning.billing.util.entity.UpdatableEntity;
-
+import com.ning.billing.junction.api.Blockable;
import com.ning.billing.util.customfield.Customizable;
+import com.ning.billing.util.entity.UpdatableEntity;
import com.ning.billing.util.tag.Taggable;
-public interface Account extends AccountData, Customizable, UpdatableEntity, Taggable {
+public interface Account extends AccountData, Customizable, UpdatableEntity, Taggable, Blockable{
public static String ObjectType = "account";
public MutableAccountData toMutableAccountData();
diff --git a/api/src/main/java/com/ning/billing/account/api/AccountService.java b/api/src/main/java/com/ning/billing/account/api/AccountService.java
index 43175da..febe8dd 100644
--- a/api/src/main/java/com/ning/billing/account/api/AccountService.java
+++ b/api/src/main/java/com/ning/billing/account/api/AccountService.java
@@ -20,5 +20,4 @@ import com.ning.billing.lifecycle.KillbillService;
public interface AccountService extends KillbillService {
- public AccountUserApi getAccountUserApi();
}
diff --git a/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java b/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java
index 2909b2d..78dad92 100644
--- a/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java
+++ b/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java
@@ -16,182 +16,78 @@
package com.ning.billing.account.api;
-import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.util.tag.TagStore;
-
-public class MutableAccountData implements AccountData {
- private String externalKey;
- private String email;
- private String name;
- private int firstNameLength;
- private Currency currency;
- private int billCycleDay;
- private String paymentProviderName;
- private DateTimeZone timeZone;
- private String locale;
- private String address1;
- private String address2;
- private String companyName;
- private String city;
- private String stateOrProvince;
- private String country;
- private String postalCode;
- private String phone;
-
- public MutableAccountData(String externalKey, String email, String name,
- int firstNameLength, Currency currency, int billCycleDay,
- String paymentProviderName, TagStore tags, DateTimeZone timeZone,
- String locale, String address1, String address2,
- String companyName, String city, String stateOrProvince,
- String country, String postalCode, String phone,
- DateTime createdDate, DateTime updatedDate) {
- super();
- this.externalKey = externalKey;
- this.email = email;
- this.name = name;
- this.firstNameLength = firstNameLength;
- this.currency = currency;
- this.billCycleDay = billCycleDay;
- this.paymentProviderName = paymentProviderName;
- this.timeZone = timeZone;
- this.locale = locale;
- this.address1 = address1;
- this.address2 = address2;
- this.companyName = companyName;
- this.city = city;
- this.stateOrProvince = stateOrProvince;
- this.country = country;
- this.postalCode = postalCode;
- this.phone = phone;
- }
-
- public MutableAccountData(AccountData accountData) {
- super();
- this.externalKey = accountData.getExternalKey();
- this.email = accountData.getEmail();
- this.name = accountData.getName();
- this.firstNameLength = accountData.getFirstNameLength();
- this.currency = accountData.getCurrency();
- this.billCycleDay = accountData.getBillCycleDay();
- this.paymentProviderName = accountData.getPaymentProviderName();
- this.timeZone = accountData.getTimeZone();
- this.locale = accountData.getLocale();
- this.address1 = accountData.getAddress1();
- this.address2 = accountData.getAddress2();
- this.companyName = accountData.getCompanyName();
- this.city = accountData.getCity();
- this.stateOrProvince = accountData.getStateOrProvince();
- this.country = accountData.getCountry();
- this.postalCode = accountData.getPostalCode();
- this.phone = accountData.getPhone();
- }
-
- public String getExternalKey() {
- return externalKey;
- }
- public String getEmail() {
- return email;
- }
- public String getName() {
- return name;
- }
- public int getFirstNameLength() {
- return firstNameLength;
- }
- public Currency getCurrency() {
- return currency;
- }
- public int getBillCycleDay() {
- return billCycleDay;
- }
- public String getPaymentProviderName() {
- return paymentProviderName;
- }
- public DateTimeZone getTimeZone() {
- return timeZone;
- }
- public String getLocale() {
- return locale;
- }
- public String getAddress1() {
- return address1;
- }
- public String getAddress2() {
- return address2;
- }
- public String getCompanyName() {
- return companyName;
- }
- public String getCity() {
- return city;
- }
- public String getStateOrProvince() {
- return stateOrProvince;
- }
- public String getCountry() {
- return country;
- }
- public String getPostalCode() {
- return postalCode;
- }
- public String getPhone() {
- return phone;
- }
-
- public void setExternalKey(String externalKey) {
- this.externalKey = externalKey;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public void setName(String name) {
- this.name = name;
- }
- public void setFirstNameLength(int firstNameLength) {
- this.firstNameLength = firstNameLength;
- }
- public void setCurrency(Currency currency) {
- this.currency = currency;
- }
- public void setBillCycleDay(int billCycleDay) {
- this.billCycleDay = billCycleDay;
- }
- public void setPaymentProviderName(String paymentProviderName) {
- this.paymentProviderName = paymentProviderName;
- }
- public void setTimeZone(DateTimeZone timeZone) {
- this.timeZone = timeZone;
- }
- public void setLocale(String locale) {
- this.locale = locale;
- }
- public void setAddress1(String address1) {
- this.address1 = address1;
- }
- public void setAddress2(String address2) {
- this.address2 = address2;
- }
- public void setCompanyName(String companyName) {
- this.companyName = companyName;
- }
- public void setCity(String city) {
- this.city = city;
- }
- public void setStateOrProvince(String stateOrProvince) {
- this.stateOrProvince = stateOrProvince;
- }
- public void setCountry(String country) {
- this.country = country;
- }
- public void setPostalCode(String postalCode) {
- this.postalCode = postalCode;
- }
- public void setPhone(String phone) {
- this.phone = phone;
- }
-
-
-}
+
+public interface MutableAccountData extends AccountData {
+
+ public String getExternalKey();
+
+ public String getEmail();
+
+ public String getName();
+
+ public int getFirstNameLength();
+
+ public Currency getCurrency();
+
+ public int getBillCycleDay();
+
+ public String getPaymentProviderName();
+
+ public DateTimeZone getTimeZone();
+
+ public String getLocale();
+
+ public String getAddress1();
+
+ public String getAddress2();
+
+ public String getCompanyName();
+
+ public String getCity();
+
+ public String getStateOrProvince();
+
+ public String getCountry();
+
+ public String getPostalCode();
+
+ public String getPhone();
+
+ public void setExternalKey(String externalKey);
+
+ public void setEmail(String email);
+
+ public void setName(String name);
+
+ public void setFirstNameLength(int firstNameLength);
+
+ public void setCurrency(Currency currency);
+
+ public void setBillCycleDay(int billCycleDay);
+
+ public void setPaymentProviderName(String paymentProviderName);
+
+ public void setTimeZone(DateTimeZone timeZone);
+
+ public void setLocale(String locale);
+
+ public void setAddress1(String address1);
+
+ public void setAddress2(String address2);
+
+ public void setCompanyName(String companyName);
+
+ public void setCity(String city);
+
+ public void setStateOrProvince(String stateOrProvince);
+
+ public void setCountry(String country);
+
+ public void setPostalCode(String postalCode);
+
+ public void setPhone(String phone);
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/Catalog.java b/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
index 2b3609a..924a5e4 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
@@ -56,6 +56,11 @@ public interface Catalog {
public abstract PlanPhase findPhase(String name, DateTime requestedDate, DateTime subscriptionStartDate) throws CatalogApiException;
//
+ // Find a priceList
+ //
+ public abstract PriceList findPriceList(String name, DateTime requestedDate) throws CatalogApiException;
+
+ //
// Rules
//
public abstract ActionPolicy planChangePolicy(PlanPhaseSpecifier from,
@@ -74,7 +79,5 @@ public interface Catalog {
PlanSpecifier to, DateTime requestedDate) throws CatalogApiException;
public abstract boolean canCreatePlan(PlanSpecifier specifier, DateTime requestedDate) throws CatalogApiException;
-
-
-
+
}
diff --git a/api/src/main/java/com/ning/billing/catalog/api/OverdueActions.java b/api/src/main/java/com/ning/billing/catalog/api/OverdueActions.java
new file mode 100644
index 0000000..8525d91
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/catalog/api/OverdueActions.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog.api;
+
+public enum OverdueActions {
+ CANCEL,
+ PAYMENT_RETRY
+}
diff --git a/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java b/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
index c93fde8..d9b0053 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
@@ -18,6 +18,10 @@ package com.ning.billing.catalog.api;
import java.util.Date;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.overdue.config.api.OverdueStateSet;
+
public interface StaticCatalog {
//
@@ -48,10 +52,15 @@ public interface StaticCatalog {
//
// Find a phase
//
- public abstract PlanPhase findCurrentPhase(String name) throws CatalogApiException;
+ public abstract PlanPhase findCurrentPhase(String name) throws CatalogApiException;
+
+ //
+ // Find a pricelist
+ //
+ public abstract PriceList findCurrentPricelist(String name) throws CatalogApiException;
//
- // Rules
+ //
//
public abstract ActionPolicy planChangePolicy(PlanPhaseSpecifier from,
PlanSpecifier to) throws CatalogApiException;
@@ -71,6 +80,4 @@ public interface StaticCatalog {
public abstract boolean canCreatePlan(PlanSpecifier specifier) throws CatalogApiException;
-
-
}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/config/CatalogConfig.java b/api/src/main/java/com/ning/billing/config/CatalogConfig.java
index 97f4957..73ffd9a 100644
--- a/api/src/main/java/com/ning/billing/config/CatalogConfig.java
+++ b/api/src/main/java/com/ning/billing/config/CatalogConfig.java
@@ -22,7 +22,7 @@ import org.skife.config.Default;
public interface CatalogConfig extends KillbillConfig {
@Config("killbill.catalog.uri")
- @Default("jar:///com/ning/billing/irs/catalog/NingCatalog.xml")
+ @Default("jar:///com/ning/billing/irs/catalog/Catalog.xml")
String getCatalogURI();
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
index 4c33dac..8681d59 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
@@ -16,21 +16,26 @@
package com.ning.billing.entitlement.api.billing;
-import com.ning.billing.catalog.api.Currency;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
+import com.ning.billing.account.api.Account;
import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.InternationalPrice;
+import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
import com.ning.billing.entitlement.api.user.Subscription;
-import java.math.BigDecimal;
-
public interface BillingEvent extends Comparable<BillingEvent> {
/**
+ * @return the account that this billing event is associated with
+ */
+ public Account getAccount();
+
+ /**
*
* @return the billCycleDay as seen for that subscription at that time
*
@@ -109,4 +114,4 @@ public interface BillingEvent extends Comparable<BillingEvent> {
*/
public Long getTotalOrdering();
-}
+ }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java
new file mode 100644
index 0000000..0dec9b9
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java
@@ -0,0 +1,54 @@
+/*
+ * 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.billing;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+
+import com.ning.billing.util.callcontext.CallContext;
+
+public interface ChargeThruApi {
+
+ /**
+ * @param subscriptionId
+ * @return UUID of
+ */
+ public UUID getAccountIdFromSubscriptionId(UUID subscriptionId);
+
+ /**
+ * Sets the charged through date for the subscription with that Id.
+ *
+ * @param subscriptionId
+ * @param ctd
+ * @param context
+ */
+ public void setChargedThroughDate(UUID subscriptionId, DateTime ctd, CallContext context);
+
+ /**
+ * Sets the charged through date for the subscription with that Id. Within the context of a SQL Transaction
+ *
+ * @param transactionalDao
+ * @param subscriptionId
+ * @param ctd
+ * @param context
+ */
+ public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId,
+ DateTime ctd, CallContext context);
+
+}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java b/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
index 9f284a1..50d45a1 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
@@ -16,22 +16,7 @@
package com.ning.billing.entitlement.api;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
-import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.repair.EntitlementRepairApi;
-import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.lifecycle.KillbillService;
public interface EntitlementService extends KillbillService {
-
- @Override
- public String getName();
-
- public EntitlementUserApi getUserApi();
-
- public EntitlementBillingApi getBillingApi();
-
- public EntitlementMigrationApi getMigrationApi();
-
- public EntitlementRepairApi getRepairApi();
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
index 205f256..66091e2 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
@@ -37,6 +37,8 @@ public interface EntitlementUserApi {
public List<Subscription> getSubscriptionsForBundle(UUID bundleId);
public List<Subscription> getSubscriptionsForKey(String bundleKey);
+
+ public Subscription getBaseSubscription(UUID bundleId);
public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleKey, CallContext context)
throws EntitlementUserApiException;
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index 5515898..b47414b 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -16,20 +16,23 @@
package com.ning.billing.entitlement.api.user;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.ProductCategory;
-
+import com.ning.billing.junction.api.Blockable;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.entity.ExtendedEntity;
-import org.joda.time.DateTime;
-
-import java.util.UUID;
-public interface Subscription extends ExtendedEntity {
+public interface Subscription extends ExtendedEntity, Blockable {
public boolean cancel(DateTime requestedDate, boolean eot, CallContext context)
throws EntitlementUserApiException;
@@ -58,7 +61,7 @@ public interface Subscription extends ExtendedEntity {
public Plan getCurrentPlan();
- public String getCurrentPriceList();
+ public PriceList getCurrentPriceList();
public PlanPhase getCurrentPhase();
@@ -71,4 +74,6 @@ public interface Subscription extends ExtendedEntity {
public SubscriptionEventTransition getPendingTransition();
public SubscriptionEventTransition getPreviousTransition();
+
+ public List<SubscriptionEventTransition> getBillingTransitions();
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
index f7c2e84..717561e 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
@@ -16,11 +16,14 @@
package com.ning.billing.entitlement.api.user;
+import java.util.UUID;
+
import org.joda.time.DateTime;
-import java.util.UUID;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.OverdueState;
-public interface SubscriptionBundle {
+public interface SubscriptionBundle extends Blockable {
public UUID getAccountId();
@@ -29,4 +32,6 @@ public interface SubscriptionBundle {
public DateTime getStartDate();
public String getKey();
+
+ public OverdueState<SubscriptionBundle> getOverdueState();
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java
index 7521f92..eae5701 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java
@@ -16,14 +16,19 @@
package com.ning.billing.entitlement.api.user;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
+
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+
+import com.ning.billing.catalog.api.PriceList;
+
import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.util.bus.BusEvent;
-import org.joda.time.DateTime;
-
-import java.util.UUID;
public interface SubscriptionEventTransition extends BusEvent {
@@ -43,7 +48,7 @@ public interface SubscriptionEventTransition extends BusEvent {
Plan getPreviousPlan();
- String getPreviousPriceList();
+ PriceList getPreviousPriceList();
PlanPhase getPreviousPhase();
@@ -53,7 +58,9 @@ public interface SubscriptionEventTransition extends BusEvent {
SubscriptionState getNextState();
- String getNextPriceList();
+ PriceList getNextPriceList();
Integer getRemainingEventsForUserOperation();
+
+ long getTotalOrdering();
}
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 28ef5d4..0a33bca 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -76,6 +76,9 @@ public enum ErrorCode {
ENT_REPAIR_BP_RECREATE_MISSING_AO_CREATE(1104, "BP recreation for bundle %s implies that all AO should be start also with a CREATE"),
ENT_REPAIR_AO_CREATE_BEFORE_BP_START(1105, "Can't recreate AO %s for bundle %s before BP starts"),
+
+ ENT_BUNDLE_IS_OVERDUE_BLOCKED(1090, "Changes to this bundle are blocked by overdue enforcement (%s : %s)"),
+ ENT_ACCOUNT_IS_OVERDUE_BLOCKED(1091, "Changes to this account are blocked by overdue enforcement (%s)"),
/*
*
* Range 2000 : CATALOG
@@ -127,7 +130,12 @@ public enum ErrorCode {
* Billing Alignment
*/
CAT_INVALID_BILLING_ALIGNMENT(2060, "Invalid billing alignment '%s'"),
-
+ /*
+ * Overdue
+ */
+ CAT_NO_SUCH_OVEDUE_STATE(2070, "No such overdue state '%s'"),
+ CAT_MISSING_CLEAR_STATE(2071, "Missing a clear state"),
+ CAT_NO_OVERDUEABLE_TYPE(2072, "No such overdueable type: "),
/*
*
* Range 3000 : ACCOUNT
@@ -170,7 +178,24 @@ public enum ErrorCode {
INVOICE_INVALID_TRANSITION(4002, "Transition did not contain a subscription id."),
INVOICE_NO_ACCOUNT_ID_FOR_SUBSCRIPTION_ID(4003, "No account id was retrieved for subscription id %s"),
INVOICE_INVALID_DATE_SEQUENCE(4004, "Date sequence was invalid. Start Date: %s; End Date: %s; Target Date: %s"),
- INVOICE_TARGET_DATE_TOO_FAR_IN_THE_FUTURE(4005, "The target date was too far in the future. Target Date: %s")
+ INVOICE_TARGET_DATE_TOO_FAR_IN_THE_FUTURE(4005, "The target date was too far in the future. Target Date: %s"),
+
+ /*
+ *
+ * Range 5000: Overdue system
+ *
+ */
+ OVERDUE_CAT_ERROR_ENCOUNTERED(5001,"Catalog error encountered on Overdueable: id='%s', type='%s'"),
+ OVERDUE_TYPE_NOT_SUPPORTED(5002,"Overdue of this type is not supported: id='%s', type='%s'"),
+ /*
+ *
+ * Range 6000: Blocking system
+ *
+ */
+ BLOCK_BLOCKED_ACTION(6000, "The action %s is block on this %s with id=%s"),
+ BLOCK_TYPE_NOT_SUPPORTED(6001, "The Blockable type '%s' is not supported")
+
+
;
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
index abbc3f1..b7ab8b1 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
@@ -28,6 +28,8 @@ public interface InvoiceItem extends Entity, Comparable<InvoiceItem> {
UUID getAccountId();
+ UUID getBundleId();
+
UUID getSubscriptionId();
String getPlanName();
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceService.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceService.java
index 7109223..c9f9f0e 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/InvoiceService.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceService.java
@@ -19,6 +19,5 @@ package com.ning.billing.invoice.api;
import com.ning.billing.lifecycle.KillbillService;
public interface InvoiceService extends KillbillService {
- public InvoiceUserApi getUserApi();
- public InvoicePaymentApi getPaymentApi();
+
}
diff --git a/api/src/main/java/com/ning/billing/junction/api/Blockable.java b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
new file mode 100644
index 0000000..6c0976e
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.junction.api;
+
+import java.util.UUID;
+
+import com.ning.billing.ErrorCode;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+
+public interface Blockable {
+
+ public enum Type {
+ ACCOUNT,
+ SUBSCRIPTION_BUNDLE,
+ SUBSCRIPTION;
+
+ public static Type get(Blockable o) throws BlockingApiException{
+ if (o instanceof Account){
+ return ACCOUNT;
+ } else if (o instanceof SubscriptionBundle){
+ return SUBSCRIPTION_BUNDLE;
+ } else if (o instanceof Subscription){
+ return SUBSCRIPTION;
+ }
+ throw new BlockingApiException(ErrorCode.BLOCK_TYPE_NOT_SUPPORTED , o.getClass().getName());
+ }
+
+ public static Type get(String type) throws BlockingApiException {
+ if (type.equalsIgnoreCase(ACCOUNT.name())) {
+ return ACCOUNT;
+ } else if (type.equalsIgnoreCase(SUBSCRIPTION_BUNDLE.name())) {
+ return SUBSCRIPTION_BUNDLE;
+ } else if (type.equalsIgnoreCase(SUBSCRIPTION.name())) {
+ return SUBSCRIPTION;
+ }
+ throw new BlockingApiException(ErrorCode.BLOCK_TYPE_NOT_SUPPORTED , type);
+ }
+
+ }
+
+ public UUID getId();
+}
diff --git a/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java b/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
new file mode 100644
index 0000000..e901d19
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
@@ -0,0 +1,36 @@
+/*
+ * 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.junction.api;
+
+import java.util.SortedSet;
+import java.util.UUID;
+
+
+public interface BlockingApi {
+ public static final String CLEAR_STATE_NAME = "__KILLBILL__CLEAR__OVERDUE_STATE__";
+
+ public BlockingState getBlockingStateFor(Blockable overdueable);
+
+ public BlockingState getBlockingStateFor(UUID overdueableId, Blockable.Type type);
+
+ public SortedSet<BlockingState> getBlockingHistory(Blockable overdueable);
+
+ public SortedSet<BlockingState> getBlockingHistory(UUID overdueableId, Blockable.Type type);
+
+ public <T extends Blockable> void setBlockingState(BlockingState state);
+
+}
diff --git a/api/src/main/java/com/ning/billing/junction/api/BlockingApiException.java b/api/src/main/java/com/ning/billing/junction/api/BlockingApiException.java
new file mode 100644
index 0000000..3a7a6c5
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/junction/api/BlockingApiException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.junction.api;
+
+import com.ning.billing.BillingExceptionBase;
+import com.ning.billing.ErrorCode;
+
+public class BlockingApiException extends BillingExceptionBase {
+ private static final long serialVersionUID = 1L;
+
+ public BlockingApiException(Throwable cause, ErrorCode code, Object... args) {
+ super(cause, code, args);
+ }
+
+ public BlockingApiException(ErrorCode code, Object... args) {
+ super(code, args);
+ }
+
+}
diff --git a/api/src/main/java/com/ning/billing/junction/api/BlockingState.java b/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
new file mode 100644
index 0000000..8c771d2
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
@@ -0,0 +1,189 @@
+/*
+ * 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.junction.api;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+public class BlockingState implements Comparable<BlockingState>{
+ private final UUID blockingId;
+ private final Blockable.Type type;
+ private final String stateName;
+ private final String service;
+ private final boolean blockChange;
+ private final boolean blockEntitlement;
+ private final boolean blockBilling;
+ private final DateTime timestamp;
+
+ public BlockingState(UUID blockingId,
+ String stateName,
+ Blockable.Type type,
+ String service,
+ boolean blockChange,
+ boolean blockEntitlement,
+ boolean blockBilling
+ ) {
+ this( blockingId,
+ stateName,
+ type,
+ service,
+ blockChange,
+ blockEntitlement,
+ blockBilling,
+ null);
+ }
+
+ public BlockingState(UUID blockingId,
+ String stateName,
+ Blockable.Type type,
+ String service,
+ boolean blockChange,
+ boolean blockEntitlement,
+ boolean blockBilling,
+ DateTime timestamp
+ ) {
+ super();
+ this.blockingId = blockingId;
+ this.stateName = stateName;
+ this.service = service;
+ this.blockChange = blockChange;
+ this.blockEntitlement = blockEntitlement;
+ this.blockBilling = blockBilling;
+ this.type = type;
+ this.timestamp = timestamp;
+ }
+
+ public UUID getBlockedId() {
+ return blockingId;
+ }
+ public String getStateName() {
+ return stateName;
+ }
+ public Blockable.Type getType() {
+ return type;
+ }
+ public DateTime getTimestamp() {
+ return timestamp;
+ }
+
+ public String getService() {
+ return service;
+ }
+
+ public boolean isBlockChange() {
+ return blockChange;
+ }
+
+ public boolean isBlockEntitlement() {
+ return blockEntitlement;
+ }
+
+ public boolean isBlockBilling() {
+ return blockBilling;
+ }
+
+ @Override
+ public int compareTo(BlockingState arg0) {
+ if (timestamp.compareTo(arg0.getTimestamp()) != 0) {
+ return timestamp.compareTo(arg0.getTimestamp());
+ } else {
+ return hashCode() - arg0.hashCode();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (blockBilling ? 1231 : 1237);
+ result = prime * result + (blockChange ? 1231 : 1237);
+ result = prime * result + (blockEntitlement ? 1231 : 1237);
+ result = prime * result + ((blockingId == null) ? 0 : blockingId.hashCode());
+ result = prime * result + ((service == null) ? 0 : service.hashCode());
+ result = prime * result + ((stateName == null) ? 0 : stateName.hashCode());
+ result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BlockingState other = (BlockingState) obj;
+ if (blockBilling != other.blockBilling)
+ return false;
+ if (blockChange != other.blockChange)
+ return false;
+ if (blockEntitlement != other.blockEntitlement)
+ return false;
+ if (blockingId == null) {
+ if (other.blockingId != null)
+ return false;
+ } else if (!blockingId.equals(other.blockingId))
+ return false;
+ if (service == null) {
+ if (other.service != null)
+ return false;
+ } else if (!service.equals(other.service))
+ return false;
+ if (stateName == null) {
+ if (other.stateName != null)
+ return false;
+ } else if (!stateName.equals(other.stateName))
+ return false;
+ if (timestamp == null) {
+ if (other.timestamp != null)
+ return false;
+ } else if (!timestamp.equals(other.timestamp))
+ return false;
+ if (type != other.type)
+ return false;
+ return true;
+ }
+
+ public String getDescription() {
+ String entitlement = onOff(isBlockEntitlement());
+ String billing = onOff(isBlockBilling());
+ String change = onOff(isBlockChange());
+
+ return String.format("(Change: %s, Entitlement: %s, Billing: %s)", change, entitlement, billing);
+ }
+
+ private String onOff(boolean val) {
+ if(val) {
+ return "Off";
+ } else {
+ return "On";
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "BlockingState [blockingId=" + blockingId + ", type=" + type + ", stateName=" + stateName + ", service="
+ + service + ", blockChange=" + blockChange + ", blockEntitlement=" + blockEntitlement
+ + ", blockBilling=" + blockBilling + ", timestamp=" + timestamp + "]";
+ }
+
+
+
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/config/api/BillingState.java b/api/src/main/java/com/ning/billing/overdue/config/api/BillingState.java
new file mode 100644
index 0000000..965e402
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/config/api/BillingState.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.config.api;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.util.tag.Tag;
+
+public class BillingState<T extends Blockable> {
+ private final UUID objectId;
+ private final int numberOfUnpaidInvoices;
+ private final BigDecimal balanceOfUnpaidInvoices;
+ private final DateTime dateOfEarliestUnpaidInvoice;
+ private final PaymentResponse responseForLastFailedPayment;
+ private final Tag[] tags;
+
+ public BillingState(UUID id, int numberOfUnpaidInvoices, BigDecimal balanceOfUnpaidInvoices,
+ DateTime dateOfEarliestUnpaidInvoice,
+ PaymentResponse responseForLastFailedPayment,
+ Tag[] tags) {
+ super();
+ this.objectId = id;
+ this.numberOfUnpaidInvoices = numberOfUnpaidInvoices;
+ this.balanceOfUnpaidInvoices = balanceOfUnpaidInvoices;
+ this.dateOfEarliestUnpaidInvoice = dateOfEarliestUnpaidInvoice;
+ this.responseForLastFailedPayment = responseForLastFailedPayment;
+ this.tags = tags;
+ }
+
+ public UUID getObjectId() {
+ return objectId;
+ }
+
+ public int getNumberOfUnpaidInvoices() {
+ return numberOfUnpaidInvoices;
+ }
+
+ public BigDecimal getBalanceOfUnpaidInvoices() {
+ return balanceOfUnpaidInvoices;
+ }
+
+ public DateTime getDateOfEarliestUnpaidInvoice() {
+ return dateOfEarliestUnpaidInvoice;
+ }
+
+ public PaymentResponse getResponseForLastFailedPayment() {
+ return responseForLastFailedPayment;
+ }
+
+ public Tag[] getTags() {
+ return tags;
+ }
+
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/config/api/BillingStateBundle.java b/api/src/main/java/com/ning/billing/overdue/config/api/BillingStateBundle.java
new file mode 100644
index 0000000..15eebc8
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/config/api/BillingStateBundle.java
@@ -0,0 +1,68 @@
+/*
+ * 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.overdue.config.api;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.util.tag.Tag;
+
+public class BillingStateBundle extends BillingState<SubscriptionBundle> {
+ private final Product basePlanProduct;
+ private final BillingPeriod basePlanBillingPeriod;
+ private final PriceList basePlanPriceList;
+ private final PhaseType basePlanPhaseType;
+
+ public BillingStateBundle(UUID id, int numberOfUnpaidInvoices, BigDecimal unpaidInvoiceBalance,
+ DateTime dateOfEarliestUnpaidInvoice,
+ PaymentResponse responseForLastFailedPayment,
+ Tag[] tags,
+ Product basePlanProduct,
+ BillingPeriod basePlanBillingPeriod,
+ PriceList basePlanPriceList, PhaseType basePlanPhaseType) {
+ super(id, numberOfUnpaidInvoices, unpaidInvoiceBalance,
+ dateOfEarliestUnpaidInvoice, responseForLastFailedPayment, tags);
+
+ this.basePlanProduct = basePlanProduct;
+ this.basePlanBillingPeriod = basePlanBillingPeriod;
+ this.basePlanPriceList = basePlanPriceList;
+ this.basePlanPhaseType = basePlanPhaseType;
+ }
+
+ public Product getBasePlanProduct() {
+ return basePlanProduct;
+ }
+
+ public BillingPeriod getBasePlanBillingPeriod() {
+ return basePlanBillingPeriod;
+ }
+
+ public PriceList getBasePlanPriceList() {
+ return basePlanPriceList;
+ }
+
+ public PhaseType getBasePlanPhaseType() {
+ return basePlanPhaseType;
+ }
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/config/api/OverdueError.java b/api/src/main/java/com/ning/billing/overdue/config/api/OverdueError.java
new file mode 100644
index 0000000..b71b299
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/config/api/OverdueError.java
@@ -0,0 +1,33 @@
+/*
+ * 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.overdue.config.api;
+
+import com.ning.billing.BillingExceptionBase;
+import com.ning.billing.ErrorCode;
+
+public class OverdueError extends BillingExceptionBase {
+ private static final long serialVersionUID = 1L;
+
+ public OverdueError(Throwable cause, ErrorCode code, Object... args) {
+ super(cause, code, args);
+ }
+
+ public OverdueError(ErrorCode code, Object... args) {
+ super(code, args);
+ }
+
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/config/api/OverdueStateSet.java b/api/src/main/java/com/ning/billing/overdue/config/api/OverdueStateSet.java
new file mode 100644
index 0000000..796e482
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/config/api/OverdueStateSet.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.config.api;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.OverdueState;
+
+public interface OverdueStateSet<T extends Blockable> {
+
+ public abstract OverdueState<T> findClearState() throws CatalogApiException;
+
+ public abstract OverdueState<T> findState(String stateName) throws CatalogApiException;
+
+ public abstract OverdueState<T> calculateOverdueState(BillingState<T> billingState, DateTime now) throws CatalogApiException;
+
+ public abstract DateTime dateOfNextCheck(BillingState<T> billingState, DateTime now);
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/overdue/config/api/PaymentResponse.java b/api/src/main/java/com/ning/billing/overdue/config/api/PaymentResponse.java
new file mode 100644
index 0000000..fb82d7c
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/config/api/PaymentResponse.java
@@ -0,0 +1,92 @@
+/*
+ * 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.overdue.config.api;
+
+public enum PaymentResponse {
+ // Card issues
+ INVALID_CARD("The card number, expiry date or cvc is invalid or incorrect"),
+ EXPIRED_CARD("The card has expired"),
+ LOST_OR_STOLEN_CARD("The card has been lost or stolen"),
+
+ // Account issues
+ DO_NOT_HONOR("Do not honor the card - usually a problem with account"),
+ INSUFFICIENT_FUNDS("The account had insufficient funds to fulfil the payment"),
+ DECLINE("Generic payment decline"),
+
+ //Transaction
+ PROCESSING_ERROR("Error processing card"),
+ INVALID_AMOUNT("An invalid amount was entered"),
+ DUPLICATE_TRANSACTION("A transaction with identical amount and credit card information was submitted very recently."),
+
+ //Other
+ OTHER("Some other error");
+
+ private String description;
+
+ private PaymentResponse(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+// 690118 | Approved
+// 136956 | Do Not Honor
+// 119640 | Insufficient Funds
+// 68514 | Invalid Account Number
+// 66824 | Declined: 10417-The transaction cannot complete successfully. Instruct the customer to use an alternative payment
+// 55473 | Declined: 10201-Agreement was canceled
+// 30930 | Pick Up Card
+// 29857 | Lost/Stolen Card
+// 28197 | Declined
+// 24830 | Declined: 10207-Transaction failed but user has alternate funding source
+// 18445 | Generic Decline
+// 18254 | Expired Card
+// 16521 | Cardholder transaction not permitted
+// 11576 | Restricted Card
+// 7410 | Account Number Does Not Match Payment Type
+// 7312 | Invalid merchant information: 10507-Payer's account is denied
+// 6425 | Invalid Transaction
+// 2825 | Declined: 10204-User's account is closed or restricted
+// 2730 | Invalid account number
+// 1331 |
+// 1240 | Field format error: 10561-There's an error with this transaction. Please enter a complete billing address.
+// 1125 | Cardholder requested that recurring or installment payment be stopped
+// 1060 | No such issuer
+// 1047 | Issuer Unavailable
+// 816 | Not signed up for this tender type
+// 749 | Transaction not allowed at terminal
+// 663 | Invalid expiration date: 0910
+// 548 | Invalid expiration date: 1010
+// 542 | Invalid expiration date:
+// 500 | Invalid expiration date: 0810
+// 492 | Invalid expiration date: 1110
+// 410 | Invalid expiration date: 0710
+// 388 | Exceeds Approval Amount Limit
+// 362 | Generic processor error: 10001-Internal Error
+// 313 | Exceeds per transaction limit: 10553-This transaction cannot be processed.
+// 310 | Decline CVV2/CID Fail
+// 309 | Generic processor error: 10201-Agreement was canceled
+// 278 | Generic processor error: 10417-The transaction cannot complete successfully. Instruct the customer to use an alte
+// 246 | Call Issuer
+// 237 | Generic processor error: 11091-The transaction was blocked as it would exceed the sending limit for this buyer.
+// 202 | Failed to connect to host Input Server Uri = https://payflowpro.paypal.com:443
+// 166 | Exceeds number of PIN entries
+// 150 | Invalid Amount
+
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueApiException.java b/api/src/main/java/com/ning/billing/overdue/OverdueApiException.java
new file mode 100644
index 0000000..7629abf
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueApiException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.overdue;
+
+import com.ning.billing.BillingExceptionBase;
+import com.ning.billing.ErrorCode;
+
+public class OverdueApiException extends BillingExceptionBase {
+ private static final long serialVersionUID = 1L;
+
+ public OverdueApiException(Throwable cause, ErrorCode code, Object... args) {
+ super(cause, code, args);
+ }
+
+ public OverdueApiException(ErrorCode code, Object... args) {
+ super(code, args);
+ }
+
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueService.java b/api/src/main/java/com/ning/billing/overdue/OverdueService.java
new file mode 100644
index 0000000..06c1f15
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueService.java
@@ -0,0 +1,28 @@
+/*
+ * 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.overdue;
+
+import com.ning.billing.lifecycle.KillbillService;
+
+public interface OverdueService extends KillbillService {
+ String OVERDUE_SERVICE_NAME = "overdue-service";
+
+ public String getName();
+
+ public OverdueUserApi getUserApi();
+
+}
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueState.java b/api/src/main/java/com/ning/billing/overdue/OverdueState.java
new file mode 100644
index 0000000..0679416
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueState.java
@@ -0,0 +1,36 @@
+/*
+ * 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.overdue;
+
+import com.ning.billing.junction.api.Blockable;
+
+
+
+public interface OverdueState<T extends Blockable> {
+
+ public String getName();
+
+ public String getExternalMessage();
+
+ public int getDaysBetweenPaymentRetries();
+
+ public boolean disableEntitlementAndChangesBlocked();
+
+ public boolean blockChanges();
+
+ public boolean isClearState();
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java b/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
new file mode 100644
index 0000000..4399176
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
@@ -0,0 +1,31 @@
+/*
+ * 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.overdue;
+
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.overdue.config.api.OverdueError;
+
+public interface OverdueUserApi {
+
+ public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueError, CatalogApiException;
+
+ public <T extends Blockable> void setOverrideBillingStateForAccount(T overdueable, BillingState<T> state) throws OverdueError;
+
+ public <T extends Blockable> OverdueState<T> getOverdueStateFor(T overdueable) throws OverdueError;
+}
diff --git a/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java b/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
index 406ec54..9f4bb38 100644
--- a/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
+++ b/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
@@ -18,7 +18,8 @@ package com.ning.billing.util.tag;
public enum ControlTagType {
AUTO_PAY_OFF("Suspends payments until removed.", true, false),
- AUTO_INVOICING_OFF("Suspends invoicing until removed.", false, true),
+ AUTO_INVOICING_OFF("Suspends invoicing until removed.", false, true),
+ OVERDUE_ENFORCEMENT_OFF("Suspends overdue enforcement behaviour until removed.", false, false),
WRITTEN_OFF("Indicated that an invoice is written off. No billing or payment effect.", false, false);
private final String description;
beatrix/pom.xml 10(+10 -0)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 64726c8..bed20c1 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -41,6 +41,10 @@
<artifactId>killbill-catalog</artifactId>
</dependency>
<dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
@@ -61,6 +65,12 @@
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>com.ning.billing</groupId>
<artifactId>killbill-payment</artifactId>
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
index 447b5b7..0a4a18a 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
@@ -22,9 +22,6 @@ import java.io.IOException;
import java.net.URL;
import java.util.Set;
-import com.ning.billing.util.glue.CallContextModule;
-import com.ning.billing.util.glue.FieldStoreModule;
-import com.ning.billing.util.glue.TagStoreModule;
import org.skife.config.ConfigurationObjectFactory;
import org.skife.jdbi.v2.IDBI;
@@ -45,16 +42,20 @@ import com.ning.billing.entitlement.api.EntitlementService;
import com.ning.billing.entitlement.glue.EntitlementModule;
import com.ning.billing.invoice.api.InvoiceService;
import com.ning.billing.invoice.glue.InvoiceModule;
+import com.ning.billing.junction.glue.JunctionModule;
import com.ning.billing.lifecycle.KillbillService;
import com.ning.billing.payment.api.PaymentService;
import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
import com.ning.billing.payment.setup.PaymentModule;
+import com.ning.billing.util.bus.BusService;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.bus.BusService;
import com.ning.billing.util.glue.BusModule;
+import com.ning.billing.util.glue.CallContextModule;
+import com.ning.billing.util.glue.FieldStoreModule;
import com.ning.billing.util.glue.GlobalLockerModule;
import com.ning.billing.util.glue.NotificationQueueModule;
+import com.ning.billing.util.glue.TagStoreModule;
public class MockModule extends AbstractModule {
@@ -93,6 +94,7 @@ public class MockModule extends AbstractModule {
install(new EntitlementModule());
install(new InvoiceModule());
install(new PaymentMockModule());
+ install(new JunctionModule());
}
private static final class PaymentMockModule extends PaymentModule {
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
index 61912fc..7378253 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.UUID;
import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.account.api.AccountData;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
@@ -49,6 +50,7 @@ import com.ning.billing.entitlement.api.user.SubscriptionData;
@Test(groups = "slow")
@Guice(modules = {MockModule.class})
public class TestIntegration extends TestIntegrationBase {
+
@Test(groups = "slow", enabled = true)
public void testBasePlanCompleteWithBillingDayInPast() throws Exception {
@@ -171,7 +173,8 @@ public class TestIntegration extends TestIntegrationBase {
boolean proRationExpected) throws Exception {
log.info("Beginning test with BCD of " + billingDay);
- Account account = accountUserApi.createAccount(getAccountData(billingDay), null, null, context);
+ AccountData accountData = getAccountData(billingDay);
+ Account account = accountUserApi.createAccount(accountData, null, null, context);
UUID accountId = account.getId();
assertNotNull(account);
@@ -424,7 +427,7 @@ public class TestIntegration extends TestIntegrationBase {
assertTrue(busHandler.isCompleted(DELAY));
invoices = invoiceUserApi.getInvoicesByAccount(accountId);
assertNotNull(invoices);
- assertTrue(invoices.size() == 2);
+ assertEquals(invoices.size(),2);
busHandler.pushExpectedEvent(NextEvent.PHASE);
busHandler.pushExpectedEvent(NextEvent.INVOICE);
@@ -433,6 +436,6 @@ public class TestIntegration extends TestIntegrationBase {
assertTrue(busHandler.isCompleted(DELAY));
invoices = invoiceUserApi.getInvoicesByAccount(accountId);
assertNotNull(invoices);
- assertTrue(invoices.size() == 3);
+ assertEquals(invoices.size(),3);
}
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index ca2ceae..1b123f3 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -104,13 +104,16 @@ public class TestIntegrationBase {
@Inject
protected MysqlTestingHelper helper;
-
+ @Inject
protected EntitlementUserApi entitlementUserApi;
+ @Inject
protected EntitlementRepairApi repairApi;
+ @Inject
protected InvoiceUserApi invoiceUserApi;
+ @Inject
protected AccountUserApi accountUserApi;
protected TestBusHandler busHandler;
@@ -146,16 +149,6 @@ public class TestIntegrationBase {
lifecycle.fireStartupSequencePriorEventRegistration();
busService.getBus().register(busHandler);
lifecycle.fireStartupSequencePostEventRegistration();
-
-
-
- /**
- * Retrieve APIs
- */
- entitlementUserApi = entitlementService.getUserApi();
- repairApi = entitlementService.getRepairApi();
- invoiceUserApi = invoiceService.getUserApi();
- accountUserApi = accountService.getAccountUserApi();
}
@AfterClass(groups = "slow")
bin/cleanAndInstall 23(+23 -0)
diff --git a/bin/cleanAndInstall b/bin/cleanAndInstall
new file mode 100755
index 0000000..fca07ad
--- /dev/null
+++ b/bin/cleanAndInstall
@@ -0,0 +1,23 @@
+#! /usr/bin/env bash
+
+###################################################################################
+# #
+# 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. #
+# #
+###################################################################################
+
+bin/db-helper -a clean -d killbill;
+bin/db-helper -a clean -d test_killbill;
+mvn -Dcom.ning.billing.dbi.test.useLocalDb=true clean install
bin/db-helper 3(+1 -2)
diff --git a/bin/db-helper b/bin/db-helper
index 3bd86ae..cc8b746 100755
--- a/bin/db-helper
+++ b/bin/db-helper
@@ -53,7 +53,6 @@ function get_modules() {
}
function find_test_ddl() {
-
local modules=`get_modules`
local ddl_test=
@@ -137,7 +136,7 @@ fi
if [ $ACTION == "dump" ]; then
- DDL_FILE=`create_ddl_file`
+ DDL_FILE=`create_ddl_file`
cat $DDL_FILE
fi
catalog/pom.xml 6(+6 -0)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index 489aba0..6f6a8c5 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -33,6 +33,12 @@
<artifactId>killbill-util</artifactId>
</dependency>
<dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
index b824617..2ed1cfa 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
@@ -43,7 +43,6 @@ public class DefaultCatalogService implements KillbillService, Provider<Catalog>
@Inject
public DefaultCatalogService(CatalogConfig config, VersionedCatalogLoader loader) {
this.config = config;
- System.out.println(config.getCatalogURI());
this.isInitialized = false;
this.loader = loader;
}
@@ -52,7 +51,6 @@ public class DefaultCatalogService implements KillbillService, Provider<Catalog>
public synchronized void loadCatalog() throws ServiceException {
if (!isInitialized) {
try {
- System.out.println("Really really::" + config.getCatalogURI());
String url = config.getCatalogURI();
catalog = loader.load(url);
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
index aba447d..c597dc0 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
@@ -107,10 +107,20 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
return count;
}
- public DefaultPriceList setRetired(boolean retired) {
+ protected DefaultPriceList setRetired(boolean retired) {
this.retired = retired;
return this;
}
+ public DefaultPriceList setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public DefaultPriceList setPlans(DefaultPlan[] plans) {
+ this.plans = plans;
+ return this;
+ }
+
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
index f0636dd..83d810b 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
@@ -48,7 +48,7 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> {
this.childPriceLists = childPriceLists;
}
- public DefaultPlan getPlanListFrom(String priceListName, Product product,
+ public DefaultPlan getPlanFrom(String priceListName, Product product,
BillingPeriod period) throws CatalogApiException {
DefaultPlan result = null;
DefaultPriceList pl = findPriceListFrom(priceListName);
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
index ff3868c..6687c75 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
@@ -55,7 +55,6 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
//Not included in XML
private String catalogName;
-
@Override
public String getCatalogName() {
return catalogName;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
index 029cdcd..a63645c 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
@@ -17,7 +17,6 @@
package com.ning.billing.catalog;
import java.net.URI;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
@@ -40,6 +39,7 @@ import com.ning.billing.catalog.api.PlanChangeResult;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.StaticCatalog;
import com.ning.billing.catalog.rules.PlanRules;
@@ -70,11 +70,11 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
private PlanRules planRules;
@XmlElementWrapper(name="plans", required=true)
- @XmlElement(name="plan", required=true)
+ @XmlElement(name="plan", required=true)
private DefaultPlan[] plans;
- @XmlElement(name="priceLists", required=true)
- private DefaultPriceListSet priceLists;
+ @XmlElement(name="priceLists", required=true)
+ private DefaultPriceListSet priceLists;
public StandaloneCatalog() {}
@@ -142,7 +142,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
throw new CatalogApiException(ErrorCode.CAT_PRICE_LIST_NOT_FOUND,priceListName);
}
Product product = findCurrentProduct(productName);
- DefaultPlan result = priceLists.getPlanListFrom(priceListName, product, period);
+ DefaultPlan result = priceLists.getPlanFrom(priceListName, product, period);
if ( result == null) {
String periodString = (period == null) ? "NULL" : period.toString();
throw new CatalogApiException(ErrorCode.CAT_PLAN_NOT_FOUND, productName, periodString, priceListName);
@@ -187,6 +187,16 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
return plan.findPhase(name);
}
+ @Override
+ public PriceList findCurrentPricelist(String name)
+ throws CatalogApiException {
+ if (name == null || priceLists == null) {
+ throw new CatalogApiException(ErrorCode.CAT_PRICE_LIST_NOT_FOUND, name);
+ }
+
+ return priceLists.findPriceListFrom(name);
+ }
+
//////////////////////////////////////////////////////////////////////////////
@@ -288,10 +298,10 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
return this;
}
- protected StandaloneCatalog setPriceLists(DefaultPriceListSet priceLists) {
- this.priceLists = priceLists;
- return this;
- }
+ protected StandaloneCatalog setPriceLists(DefaultPriceListSet priceLists) {
+ this.priceLists = priceLists;
+ return this;
+ }
@Override
public boolean canCreatePlan(PlanSpecifier specifier) throws CatalogApiException {
@@ -303,4 +313,5 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
(!plan.isRetired()) &&
(!priceList.isRetired());
}
+
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
index ef9b125..215b142 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -46,6 +46,7 @@ import com.ning.billing.catalog.api.PlanChangeResult;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.StaticCatalog;
import com.ning.billing.util.clock.Clock;
@@ -160,6 +161,8 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
throw new CatalogApiException(ErrorCode.CAT_NO_CATALOG_FOR_GIVEN_DATE, requestedDate.toDate().toString());
}
+
+
//
// Public methods not exposed in interface
//
@@ -270,6 +273,17 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
return plan.findPhase(phaseName);
}
+
+ //
+ // Find a price list
+ //
+ @Override
+ public PriceList findPriceList(String name, DateTime requestedDate)
+ throws CatalogApiException {
+ return versionForDate(requestedDate).findCurrentPriceList(name);
+ }
+
+
//
// Rules
//
@@ -381,6 +395,13 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
public PlanPhase findCurrentPhase(String name) throws CatalogApiException {
return versionForDate(clock.getUTCNow()).findCurrentPhase(name);
}
+
+
+ @Override
+ public PriceList findCurrentPricelist(String name)
+ throws CatalogApiException {
+ return versionForDate(clock.getUTCNow()).findCurrentPriceList(name);
+ }
@Override
public ActionPolicy planChangePolicy(PlanPhaseSpecifier from,
@@ -424,8 +445,4 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
return versionForDate(clock.getUTCNow()).canCreatePlan(specifier);
}
-
-
-
-
}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
index 244ca49..40dc146 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
@@ -18,14 +18,35 @@ package com.ning.billing.catalog;
import java.util.Date;
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingAlignment;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
+import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.PlanChangeResult;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.rules.CaseCancelPolicy;
import com.ning.billing.catalog.rules.CaseChangePlanAlignment;
import com.ning.billing.catalog.rules.CaseChangePlanPolicy;
import com.ning.billing.catalog.rules.CaseCreateAlignment;
import com.ning.billing.catalog.rules.PlanRules;
-public class MockCatalog extends StandaloneCatalog {
+public class MockCatalog extends StandaloneCatalog implements Catalog {
private static final String[] PRODUCT_NAMES = new String[]{ "TestProduct1", "TestProduct2", "TestProduct3"};
+ private boolean canCreatePlan;
+ private PlanChangeResult planChange;
+ private BillingAlignment billingAlignment;
+ private PlanAlignmentCreate planCreateAlignment;
public MockCatalog() {
setEffectiveDate(new Date());
@@ -34,8 +55,8 @@ public class MockCatalog extends StandaloneCatalog {
populateRules();
populatePriceLists();
}
-
- public void populateRules(){
+
+ public void populateRules(){
setPlanRules(new PlanRules());
}
@@ -47,6 +68,8 @@ public class MockCatalog extends StandaloneCatalog {
){
}
+
+
public void populatePriceLists() {
DefaultPlan[] plans = getCurrentPlans();
@@ -64,6 +87,156 @@ public class MockCatalog extends StandaloneCatalog {
return PRODUCT_NAMES;
}
+ @Override
+ public Currency[] getSupportedCurrencies(DateTime requestedDate) throws CatalogApiException {
+ return getCurrentSupportedCurrencies();
+ }
+
+ @Override
+ public Product[] getProducts(DateTime requestedDate) throws CatalogApiException {
+ return getCurrentProducts();
+ }
+
+ @Override
+ public Plan[] getPlans(DateTime requestedDate) throws CatalogApiException {
+ return getCurrentPlans();
+ }
+
+ @Override
+ public Plan findPlan(String name, DateTime requestedDate) throws CatalogApiException {
+ return findCurrentPlan(name);
+ }
+
+ @Override
+ public Plan findPlan(String productName, BillingPeriod term, String priceListName, DateTime requestedDate)
+ throws CatalogApiException {
+ return findCurrentPlan(productName, term, priceListName);
+ }
+
+ @Override
+ public Plan findPlan(String name, DateTime effectiveDate, DateTime subscriptionStartDate)
+ throws CatalogApiException {
+ return findCurrentPlan(name);
+ }
+
+ @Override
+ public Plan findPlan(String productName, BillingPeriod term, String priceListName, DateTime requestedDate,
+ DateTime subscriptionStartDate) throws CatalogApiException {
+ return findCurrentPlan(productName, term, priceListName);
+ }
+
+ @Override
+ public Product findProduct(String name, DateTime requestedDate) throws CatalogApiException {
+ return findCurrentProduct(name);
+ }
+
+ @Override
+ public PlanPhase findPhase(String name, DateTime requestedDate, DateTime subscriptionStartDate)
+ throws CatalogApiException {
+ return findCurrentPhase(name);
+ }
+
+ @Override
+ public PriceList findPriceList(String name, DateTime requestedDate) throws CatalogApiException {
+ return findCurrentPricelist(name);
+ }
+
+ @Override
+ public ActionPolicy planChangePolicy(PlanPhaseSpecifier from, PlanSpecifier to, DateTime requestedDate)
+ throws CatalogApiException {
+ return planChangePolicy(from, to);
+ }
+
+ @Override
+ public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to, DateTime requestedDate)
+ throws CatalogApiException {
+ return planChange(from, to);
+ }
+
+ @Override
+ public ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase, DateTime requestedDate)
+ throws CatalogApiException {
+ return planCancelPolicy(planPhase);
+ }
+
+ @Override
+ public PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier, DateTime requestedDate)
+ throws CatalogApiException {
+ return planCreateAlignment(specifier);
+ }
+
+ @Override
+ public BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase, DateTime requestedDate)
+ throws CatalogApiException {
+ return billingAlignment(planPhase);
+ }
+
+ @Override
+ public PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from, PlanSpecifier to, DateTime requestedDate)
+ throws CatalogApiException {
+ return planChangeAlignment(from, to);
+ }
+
+ @Override
+ public boolean canCreatePlan(PlanSpecifier specifier, DateTime requestedDate) throws CatalogApiException {
+ return canCreatePlan(specifier);
+ }
+
+ @Override
+ public ActionPolicy planChangePolicy(PlanPhaseSpecifier from, PlanSpecifier to) throws CatalogApiException {
+ // TODO Auto-generated method stub
+ return super.planChangePolicy(from, to);
+ }
+
+ @Override
+ public PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from, PlanSpecifier to)
+ throws CatalogApiException {
+ // TODO Auto-generated method stub
+ return super.planChangeAlignment(from, to);
+ }
+
+ @Override
+ public ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase) throws CatalogApiException {
+ // TODO Auto-generated method stub
+ return super.planCancelPolicy(planPhase);
+ }
+
+ @Override
+ public PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier) throws CatalogApiException {
+ return planCreateAlignment;
+ }
+
+ @Override
+ public BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase) throws CatalogApiException {
+ // TODO Auto-generated method stub
+ return billingAlignment;
+ }
+
+ @Override
+ public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to) throws CatalogApiException {
+ // TODO Auto-generated method stub
+ return planChange;
+ }
+
+ @Override
+ public boolean canCreatePlan(PlanSpecifier specifier) throws CatalogApiException {
+ return canCreatePlan;
+ }
+
+ public void setCanCreatePlan(boolean canCreatePlan) {
+ this.canCreatePlan = canCreatePlan;
+ }
+
+ public void setPlanChange(PlanChangeResult planChange) {
+ this.planChange = planChange;
+ }
+
+ public void setBillingAlignment(BillingAlignment billingAlignment) {
+ this.billingAlignment = billingAlignment;
+ }
+
+ public void setPlanCreateAlignment(PlanAlignmentCreate planCreateAlignment) {
+ this.planCreateAlignment = planCreateAlignment;
+ }
-
}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalogModule.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalogModule.java
new file mode 100644
index 0000000..2aceb5b
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalogModule.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+
+public class MockCatalogModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ CatalogService catalogService = BrainDeadProxyFactory.createBrainDeadProxyFor(CatalogService.class);
+ ((ZombieControl) catalogService).addResult("getCurrentCatalog", new MockCatalog());
+ bind(CatalogService.class).toInstance(catalogService);
+ }
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalogService.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalogService.java
new file mode 100644
index 0000000..f7277c7
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalogService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.StaticCatalog;
+
+
+public class MockCatalogService extends DefaultCatalogService {
+
+ private MockCatalog catalog;
+
+ public MockCatalogService(MockCatalog catalog) {
+ super(null, null);
+ this.catalog = catalog;
+ }
+
+ @Override
+ public synchronized void loadCatalog() throws ServiceException {
+ }
+
+ @Override
+ public String getName() {
+ return "Mock Catalog";
+ }
+
+ @Override
+ public Catalog getFullCatalog() {
+ return catalog;
+ }
+
+ @Override
+ public Catalog get() {
+ return catalog;
+ }
+
+ @Override
+ public StaticCatalog getCurrentCatalog() {
+ return catalog;
+ }
+
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
index deececb..f4dfab1 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
@@ -60,13 +60,21 @@ public class MockPlan extends DefaultPlan {
-1);
}
- public static MockPlan createJetTrialFixedTermEvergreen1000USD() {
- return new MockPlan("JetTrialEvergreen1000USD",
- MockProduct.createJet(),
- new DefaultPlanPhase[]{ MockPlanPhase.create30DayTrial(), MockPlanPhase.createUSDMonthlyFixedTerm("500.00", null, 6) },
- MockPlanPhase.create1USDMonthlyEvergreen(),
- -1);
- }
+ public static MockPlan createJetTrialFixedTermEvergreen1000USD() {
+ return new MockPlan("JetTrialEvergreen1000USD",
+ MockProduct.createJet(),
+ new DefaultPlanPhase[]{ MockPlanPhase.create30DayTrial(), MockPlanPhase.createUSDMonthlyFixedTerm("500.00", null, 6) },
+ MockPlanPhase.create1USDMonthlyEvergreen(),
+ -1);
+ }
+
+ public static MockPlan createHornMonthlyNoTrial1USD() {
+ return new MockPlan("Horn1USD",
+ MockProduct.createHorn(),
+ new DefaultPlanPhase[]{ },
+ MockPlanPhase.create1USDMonthlyEvergreen(),
+ -1);
+ }
public MockPlan() {
this("BicycleTrialEvergreen1USD",
@@ -123,7 +131,8 @@ public class MockPlan extends DefaultPlan {
createPickupTrialEvergreen10USD(),
createSportsCarTrialEvergreen100USD(),
createJetTrialEvergreen1000USD(),
- createJetTrialFixedTermEvergreen1000USD()
+ createJetTrialFixedTermEvergreen1000USD(),
+ createHornMonthlyNoTrial1USD()
};
}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockPriceList.java b/catalog/src/test/java/com/ning/billing/catalog/MockPriceList.java
new file mode 100644
index 0000000..9b672ba
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockPriceList.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import com.ning.billing.catalog.api.PriceListSet;
+
+public class MockPriceList extends DefaultPriceList {
+
+ public MockPriceList() {
+ setName(PriceListSet.DEFAULT_PRICELIST_NAME);
+ setRetired(false);
+ setPlans(MockPlan.createAll());
+ }
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
index 3cb8d2f..a26ce10 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
@@ -50,10 +50,10 @@ public class TestPriceListSet {
};
DefaultPriceListSet set = new DefaultPriceListSet(defaultPriceList, childPriceLists);
- Assert.assertEquals(set.getPlanListFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
- Assert.assertEquals(set.getPlanListFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
- Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.DISCOUNT);
- Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanFrom("child", foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.DISCOUNT);
+ Assert.assertEquals(set.getPlanFrom("child", foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
}
public void testForNullBillingPeriod() throws CatalogApiException {
@@ -76,10 +76,10 @@ public class TestPriceListSet {
};
DefaultPriceListSet set = new DefaultPriceListSet(defaultPriceList, childPriceLists);
- Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.DISCOUNT);
- Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
- Assert.assertEquals(set.getPlanListFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
- Assert.assertEquals(set.getPlanListFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanFrom("child", foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.DISCOUNT);
+ Assert.assertEquals(set.getPlanFrom("child", foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.ANNUAL).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
+ Assert.assertEquals(set.getPlanFrom(PriceListSet.DEFAULT_PRICELIST_NAME, foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
}
}
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
index c21aac1..ca17050 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
@@ -67,8 +67,7 @@
</createAlignmentCase>
</createAlignment>
</rules>
-
-
+
<plans>
<plan name="pistol-monthly">
<product>Pistol</product>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
index f7ae066..ccbd964 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
@@ -68,7 +68,6 @@
</createAlignment>
</rules>
-
<plans>
<plan name="pistol-monthly">
<product>Pistol</product>
diff --git a/catalog/src/test/resources/WeaponsHire.xml b/catalog/src/test/resources/WeaponsHire.xml
index 3d36b9d..4a895b0 100644
--- a/catalog/src/test/resources/WeaponsHire.xml
+++ b/catalog/src/test/resources/WeaponsHire.xml
@@ -169,8 +169,8 @@ Use Cases to do:
<toPriceList>DEFAULT</toPriceList>
</priceListCase>
</priceList>
- </rules>
-
+ </rules>
+
<plans>
<plan name="pistol-monthly">
<product>Pistol</product>
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 8006a39..5e0ded9 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
@@ -134,7 +134,7 @@ public class PlanAligner {
subscription.getBundleStartDate(),
lastPlanTransition.getNextPlan(),
lastPlanTransition.getNextPhase().getPhaseType(),
- lastPlanTransition.getNextPriceList(),
+ lastPlanTransition.getNextPriceList().getName(),
requestedDate);
return getTimedPhase(timedPhases, effectiveDate, WhichPhase.NEXT);
// If we went through Plan changes, borrow the logics for changePlan alignement
@@ -143,9 +143,9 @@ public class PlanAligner {
subscription.getBundleStartDate(),
lastPlanTransition.getPreviousPhase(),
lastPlanTransition.getPreviousPlan(),
- lastPlanTransition.getPreviousPriceList(),
+ lastPlanTransition.getPreviousPriceList().getName(),
lastPlanTransition.getNextPlan(),
- lastPlanTransition.getNextPriceList(),
+ lastPlanTransition.getNextPriceList().getName(),
requestedDate,
effectiveDate,
WhichPhase.NEXT);
@@ -193,7 +193,7 @@ public class PlanAligner {
subscription.getBundleStartDate(),
subscription.getCurrentPhase(),
subscription.getCurrentPlan(),
- subscription.getCurrentPriceList(),
+ subscription.getCurrentPriceList().getName(),
nextPlan,
nextPriceList,
requestedDate,
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java
new file mode 100644
index 0000000..7bde4a2
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java
@@ -0,0 +1,87 @@
+/*
+w * 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.billing;
+
+import java.util.Date;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.entitlement.api.SubscriptionFactory;
+import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory.SubscriptionBuilder;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.engine.dao.SubscriptionSqlDao;
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.audit.dao.AuditSqlDao;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+
+public class DefaultChargeThruApi implements ChargeThruApi {
+ private static final Logger log = LoggerFactory.getLogger(DefaultChargeThruApi.class);
+
+ private final EntitlementDao entitlementDao;
+ private final SubscriptionFactory subscriptionFactory;
+
+ private static final String SUBSCRIPTION_TABLE_NAME = "subscriptions";
+
+ @Inject
+ public DefaultChargeThruApi(final CallContextFactory factory, final SubscriptionFactory subscriptionFactory, final EntitlementDao dao, final AccountUserApi accountApi) {
+ super();
+ this.subscriptionFactory = subscriptionFactory;
+ this.entitlementDao = dao;
+ }
+
+ @Override
+ public UUID getAccountIdFromSubscriptionId(final UUID subscriptionId) {
+ return entitlementDao.getAccountIdFromSubscriptionId(subscriptionId);
+ }
+
+ @Override
+ public void setChargedThroughDate(final UUID subscriptionId, final DateTime ctd, CallContext context) {
+ SubscriptionData subscription = (SubscriptionData) entitlementDao.getSubscriptionFromId(subscriptionFactory, subscriptionId);
+
+ SubscriptionBuilder builder = new SubscriptionBuilder(subscription)
+ .setChargedThroughDate(ctd)
+ .setPaidThroughDate(subscription.getPaidThroughDate());
+ entitlementDao.updateChargedThroughDate(new SubscriptionData(builder), context);
+ }
+
+ @Override
+ public void setChargedThroughDateFromTransaction(final Transmogrifier transactionalDao, final UUID subscriptionId,
+ final DateTime ctd, final CallContext context) {
+ SubscriptionSqlDao subscriptionSqlDao = transactionalDao.become(SubscriptionSqlDao.class);
+ SubscriptionData subscription = (SubscriptionData) subscriptionSqlDao.getSubscriptionFromId(subscriptionId.toString());
+
+ if (subscription == null) {
+ log.warn("Subscription not found when setting CTD.");
+ } else {
+ DateTime chargedThroughDate = subscription.getChargedThroughDate();
+ if (chargedThroughDate == null || chargedThroughDate.isBefore(ctd)) {
+ subscriptionSqlDao.updateChargedThroughDate(subscriptionId.toString(),
+ ctd.toDate(), context);
+ AuditSqlDao auditSqlDao = transactionalDao.become(AuditSqlDao.class);
+ auditSqlDao.insertAuditFromTransaction(SUBSCRIPTION_TABLE_NAME, subscriptionId.toString(), ChangeType.UPDATE, context);
+ }
+ }
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
index 1b7fc80..115c60b 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
@@ -19,11 +19,11 @@ package com.ning.billing.entitlement.api.user;
import java.util.List;
import java.util.UUID;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.util.callcontext.CallContext;
import org.joda.time.DateTime;
+
import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.Catalog;
import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.api.Plan;
@@ -37,6 +37,7 @@ import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory.Subscrip
import com.ning.billing.entitlement.engine.addon.AddonUtils;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.DefaultClock;
@@ -91,6 +92,11 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
}
@Override
+ public Subscription getBaseSubscription(UUID bundleId) {
+ return dao.getBaseSubscription(subscriptionFactory, bundleId);
+ }
+
+
public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleName, CallContext context)
throws EntitlementUserApiException {
SubscriptionBundleData bundle = new SubscriptionBundleData(bundleName, accountId, clock.getUTCNow());
@@ -161,7 +167,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
}
SubscriptionData subscription = apiService.createPlan(new SubscriptionBuilder()
- .setId(UUID.randomUUID())
+ .setId(UUID.randomUUID())
.setBundleId(bundleId)
.setCategory(plan.getProduct().getCategory())
.setBundleStartDate(bundleStartDate)
@@ -174,20 +180,21 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
}
}
- @Override
- public DateTime getNextBillingDate(UUID accountId) {
- List<SubscriptionBundle> bundles = getBundlesForAccount(accountId);
- DateTime result = null;
- for(SubscriptionBundle bundle : bundles) {
- List<Subscription> subscriptions = getSubscriptionsForBundle(bundle.getId());
- for(Subscription subscription : subscriptions) {
- DateTime chargedThruDate = subscription.getChargedThroughDate();
- if(result == null ||
- (chargedThruDate != null && chargedThruDate.isBefore(result))) {
- result = subscription.getChargedThroughDate();
- }
- }
- }
- return result;
- }
+
+ @Override
+ public DateTime getNextBillingDate(UUID accountId) {
+ List<SubscriptionBundle> bundles = getBundlesForAccount(accountId);
+ DateTime result = null;
+ for(SubscriptionBundle bundle : bundles) {
+ List<Subscription> subscriptions = getSubscriptionsForBundle(bundle.getId());
+ for(Subscription subscription : subscriptions) {
+ DateTime chargedThruDate = subscription.getChargedThroughDate();
+ if(result == null ||
+ (chargedThruDate != null && chargedThruDate.isBefore(result))) {
+ result = subscription.getChargedThroughDate();
+ }
+ }
+ }
+ return result;
+ }
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java
index 7e1e91f..1560bd2 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionApiService.java
@@ -16,9 +16,26 @@
package com.ning.billing.entitlement.api.user;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.joda.time.DateTime;
+
import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.*;
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanChangeResult;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.PriceListSet;
+import com.ning.billing.catalog.api.Product;
import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.alignment.TimedPhase;
import com.ning.billing.entitlement.api.SubscriptionApiService;
@@ -28,15 +45,17 @@ import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEventData;
-import com.ning.billing.entitlement.events.user.*;
+import com.ning.billing.entitlement.events.user.ApiEvent;
+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.ApiEventReCreate;
+import com.ning.billing.entitlement.events.user.ApiEventUncancel;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.DefaultClock;
-import org.joda.time.DateTime;
-
-import java.util.ArrayList;
-import java.util.List;
public class DefaultSubscriptionApiService implements SubscriptionApiService {
@@ -56,13 +75,16 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
public SubscriptionData createPlan(SubscriptionBuilder builder, Plan plan, PhaseType initialPhase,
String realPriceList, DateTime requestedDate, DateTime effectiveDate, DateTime processedDate,
CallContext context)
- throws EntitlementUserApiException {
-
+ throws EntitlementUserApiException {
SubscriptionData subscription = new SubscriptionData(builder, this, clock);
+
+
+
createFromSubscription(subscription, plan, initialPhase, realPriceList, requestedDate, effectiveDate, processedDate, false, context);
return subscription;
}
+
public boolean recreatePlan(SubscriptionData subscription, PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
throws EntitlementUserApiException {
@@ -98,6 +120,7 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
boolean reCreate, CallContext context)
throws EntitlementUserApiException {
+
try {
TimedPhase [] curAndNextPhases = planAligner.getCurrentAndNextTimedPhaseOnCreate(subscription, plan, initialPhase, realPriceList, requestedDate, effectiveDate);
@@ -151,7 +174,7 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
currentPlan.getProduct().getCategory(),
subscription.getCurrentPlan().getBillingPeriod(),
- subscription.getCurrentPriceList(),
+ subscription.getCurrentPriceList().getName(),
subscription.getCurrentPhase().getPhaseType());
ActionPolicy policy = catalogService.getFullCatalog().planCancelPolicy(planPhase, requestedDate);
@@ -209,6 +232,7 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
public boolean changePlan(SubscriptionData subscription, String productName, BillingPeriod term,
String priceList, DateTime requestedDate, CallContext context)
+
throws EntitlementUserApiException {
try {
@@ -217,7 +241,7 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
validateRequestedDate(subscription, now, requestedDate);
- String currentPriceList = subscription.getCurrentPriceList();
+ PriceList currentPriceList = subscription.getCurrentPriceList();
SubscriptionState currentState = subscription.getState();
if (currentState != SubscriptionState.ACTIVE) {
@@ -235,7 +259,7 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
currentPlan.getProduct().getCategory(),
currentPlan.getBillingPeriod(),
- currentPriceList, subscription.getCurrentPhase().getPhaseType());
+ currentPriceList.getName(), subscription.getCurrentPhase().getPhaseType());
PlanSpecifier toPlanPhase = new PlanSpecifier(productName,
destProduct.getCategory(),
term,
@@ -284,6 +308,7 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
}
}
+
public void commitCustomFields(SubscriptionData subscription, CallContext context) {
dao.saveCustomFields(subscription, context);
}
@@ -301,4 +326,6 @@ public class DefaultSubscriptionApiService implements SubscriptionApiService {
requestedDate.toString(), previousTransition.getEffectiveTransitionTime());
}
}
+
+
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
index 75a4da1..219becc 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
@@ -16,9 +16,11 @@
package com.ning.billing.entitlement.api.user;
+import java.util.UUID;
+
import org.joda.time.DateTime;
-import java.util.UUID;
+import com.ning.billing.overdue.OverdueState;
public class SubscriptionBundleData implements SubscriptionBundle {
@@ -27,18 +29,24 @@ public class SubscriptionBundleData implements SubscriptionBundle {
private final UUID accountId;
private final DateTime startDate;
private final DateTime lastSysTimeUpdate;
+ private final OverdueState<SubscriptionBundle> overdueState;
+
+ public SubscriptionBundleData(String name, UUID accountId, DateTime startDate) {
+ this(UUID.randomUUID(), name, accountId, startDate, startDate);
+ }
- public SubscriptionBundleData(String name, UUID accountId, DateTime now) {
- this(UUID.randomUUID(), name, accountId, null, now);
+ public SubscriptionBundleData(UUID id, String key, UUID accountId, DateTime startDate, DateTime lastSysUpdate) {
+ this(id, key, accountId, startDate, lastSysUpdate, null);
}
- public SubscriptionBundleData(UUID id, String key, UUID accountId, DateTime startDate, DateTime now) {
+ public SubscriptionBundleData(UUID id, String key, UUID accountId, DateTime startDate, DateTime lastSysUpdate, OverdueState<SubscriptionBundle> overdueState) {
super();
this.id = id;
this.key = key;
this.accountId = accountId;
this.startDate = startDate;
- this.lastSysTimeUpdate = now;
+ this.lastSysTimeUpdate = lastSysUpdate;
+ this.overdueState = overdueState;
}
@Override
@@ -56,7 +64,6 @@ public class SubscriptionBundleData implements SubscriptionBundle {
return accountId;
}
-
// STEPH do we need it ? and should we return that and when is that populated/updated?
@Override
public DateTime getStartDate() {
@@ -66,4 +73,9 @@ public class SubscriptionBundleData implements SubscriptionBundle {
public DateTime getLastSysUpdateTime() {
return lastSysTimeUpdate;
}
+
+ @Override
+ public OverdueState<SubscriptionBundle> getOverdueState() {
+ return overdueState;
+ }
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index 80f25ab..d4e1685 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -16,6 +16,18 @@
package com.ning.billing.entitlement.api.user;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.ning.billing.catalog.api.ActionPolicy;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Catalog;
@@ -23,6 +35,7 @@ import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.SubscriptionApiService;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
@@ -39,18 +52,7 @@ import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.customfield.CustomField;
-
import com.ning.billing.util.entity.ExtendedEntityBase;
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
public class SubscriptionData extends ExtendedEntityBase implements
Subscription {
@@ -156,9 +158,10 @@ public class SubscriptionData extends ExtendedEntityBase implements
}
@Override
- public String getCurrentPriceList() {
- return (getPreviousTransition() == null) ? null
- : getPreviousTransition().getNextPriceList();
+ public PriceList getCurrentPriceList() {
+ return (getPreviousTransition() == null) ? null :
+ getPreviousTransition().getNextPriceList();
+
}
@Override
@@ -402,11 +405,11 @@ public class SubscriptionData extends ExtendedEntityBase implements
SubscriptionState nextState = null;
String nextPlanName = null;
String nextPhaseName = null;
- String nextPriceList = null;
+ String nextPriceListName = null;
UUID nextUserToken = null;
SubscriptionState previousState = null;
- String previousPriceList = null;
+ PriceList previousPriceList = null;
transitions = new LinkedList<SubscriptionTransitionData>();
Plan previousPlan = null;
@@ -447,12 +450,12 @@ public class SubscriptionData extends ExtendedEntityBase implements
nextState = SubscriptionState.ACTIVE;
nextPlanName = userEV.getEventPlan();
nextPhaseName = userEV.getEventPlanPhase();
- nextPriceList = userEV.getPriceList();
+ nextPriceListName = userEV.getPriceList();
break;
case CHANGE:
nextPlanName = userEV.getEventPlan();
nextPhaseName = userEV.getEventPlanPhase();
- nextPriceList = userEV.getPriceList();
+ nextPriceListName = userEV.getPriceList();
break;
case CANCEL:
nextState = SubscriptionState.CANCELLED;
@@ -474,11 +477,12 @@ public class SubscriptionData extends ExtendedEntityBase implements
Plan nextPlan = null;
PlanPhase nextPhase = null;
+ PriceList nextPriceList = null;
+
try {
- nextPlan = (nextPlanName != null) ? catalog.findPlan(nextPlanName, cur.getRequestedDate(), getStartDate())
- : null;
- nextPhase = (nextPhaseName != null) ? catalog.findPhase(nextPhaseName, cur.getRequestedDate(), getStartDate())
- : null;
+ nextPlan = (nextPlanName != null) ? catalog.findPlan(nextPlanName, cur.getRequestedDate(), getStartDate()) : null;
+ nextPhase = (nextPhaseName != null) ? catalog.findPhase(nextPhaseName, cur.getRequestedDate(), getStartDate()) : null;
+ nextPriceList = (nextPriceListName != null) ? catalog.findPriceList(nextPriceListName, cur.getRequestedDate()) : null;
} catch (CatalogApiException e) {
log.error(String.format(
"Failed to build transition for subscription %s", id),
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
index 6b28140..461fe3c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
@@ -16,18 +16,18 @@
package com.ning.billing.entitlement.api.user;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.exceptions.EntitlementError;
-import com.ning.billing.util.bus.BusEvent.BusEventType;
-
-import org.joda.time.DateTime;
-
-import java.util.UUID;
public class SubscriptionTransitionData implements SubscriptionEventTransition {
@@ -41,11 +41,11 @@ public class SubscriptionTransitionData implements SubscriptionEventTransition {
private final DateTime requestedTransitionTime;
private final DateTime effectiveTransitionTime;
private final SubscriptionState previousState;
- private final String previousPriceList;
+ private final PriceList previousPriceList;
private final Plan previousPlan;
private final PlanPhase previousPhase;
private final SubscriptionState nextState;
- private final String nextPriceList;
+ private final PriceList nextPriceList;
private final Plan nextPlan;
private final PlanPhase nextPhase;
private final boolean isFromDisk;
@@ -54,8 +54,8 @@ public class SubscriptionTransitionData implements SubscriptionEventTransition {
public SubscriptionTransitionData(UUID eventId, UUID subscriptionId, UUID bundleId, EventType eventType,
ApiEventType apiEventType, DateTime requestedTransitionTime, DateTime effectiveTransitionTime,
- SubscriptionState previousState, Plan previousPlan, PlanPhase previousPhase, String previousPriceList,
- SubscriptionState nextState, Plan nextPlan, PlanPhase nextPhase, String nextPriceList,
+ SubscriptionState previousState, Plan previousPlan, PlanPhase previousPhase, PriceList previousPriceList,
+ SubscriptionState nextState, Plan nextPlan, PlanPhase nextPhase, PriceList nextPriceList,
long totalOrdering, UUID userToken, boolean isFromDisk) {
super();
this.eventId = eventId;
@@ -156,12 +156,12 @@ public class SubscriptionTransitionData implements SubscriptionEventTransition {
@Override
- public String getPreviousPriceList() {
+ public PriceList getPreviousPriceList() {
return previousPriceList;
}
@Override
- public String getNextPriceList() {
+ public PriceList getNextPriceList() {
return nextPriceList;
}
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 031d9c7..c8f82a2 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
@@ -23,21 +23,16 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallContextFactory;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
+
import com.google.inject.name.Named;
+
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.ProductCategory;
@@ -47,15 +42,7 @@ import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.alignment.TimedPhase;
import com.ning.billing.entitlement.api.EntitlementService;
import com.ning.billing.entitlement.api.SubscriptionFactory;
-import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
-import com.ning.billing.entitlement.api.migration.DefaultEntitlementMigrationApi;
-import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.repair.EntitlementRepairApi;
-import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
-import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory;
import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.engine.addon.AddonUtils;
@@ -70,9 +57,13 @@ import com.ning.billing.entitlement.events.user.ApiEventCancel;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.lifecycle.LifecycleHandlerType;
import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.notificationq.NotificationQueue;
import com.ning.billing.util.notificationq.NotificationQueueService;
import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
@@ -89,10 +80,6 @@ public class Engine implements EventListener, EntitlementService {
private final Clock clock;
private final EntitlementDao dao;
private final PlanAligner planAligner;
- private final EntitlementUserApi userApi;
- private final EntitlementBillingApi billingApi;
- private final EntitlementMigrationApi migrationApi;
- private final EntitlementRepairApi repairApi;
private final AddonUtils addonUtils;
private final Bus eventBus;
@@ -104,10 +91,8 @@ public class Engine implements EventListener, EntitlementService {
@Inject
public Engine(Clock clock, EntitlementDao dao, PlanAligner planAligner,
- EntitlementConfig config, DefaultEntitlementUserApi userApi,
- DefaultEntitlementBillingApi billingApi,
- EntitlementRepairApi repairApi,
- DefaultEntitlementMigrationApi migrationApi, AddonUtils addonUtils, Bus eventBus,
+ EntitlementConfig config,
+ AddonUtils addonUtils, Bus eventBus,
NotificationQueueService notificationQueueService,
SubscriptionFactory subscriptionFactory,
CallContextFactory factory) {
@@ -115,10 +100,6 @@ public class Engine implements EventListener, EntitlementService {
this.clock = clock;
this.dao = dao;
this.planAligner = planAligner;
- this.userApi = userApi;
- this.repairApi = repairApi;
- this.billingApi = billingApi;
- this.migrationApi = migrationApi;
this.addonUtils = addonUtils;
this.config = config;
this.eventBus = eventBus;
@@ -189,27 +170,6 @@ public class Engine implements EventListener, EntitlementService {
}
@Override
- public EntitlementUserApi getUserApi() {
- return userApi;
- }
-
- @Override
- public EntitlementBillingApi getBillingApi() {
- return billingApi;
- }
-
-
- @Override
- public EntitlementMigrationApi getMigrationApi() {
- return migrationApi;
- }
-
- @Override
- public EntitlementRepairApi getRepairApi() {
- return repairApi;
- }
-
- @Override
public void processEventReady(final EntitlementEvent event, final int seqId, final CallContext context) {
if (!event.isActive()) {
return;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
index 29cc30e..5af5294 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
@@ -16,12 +16,12 @@
package com.ning.billing.entitlement.engine.dao;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallContextBinder;
-import com.ning.billing.util.dao.BinderBase;
-import com.ning.billing.util.dao.MapperBase;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
import org.joda.time.DateTime;
import org.skife.jdbi.v2.SQLStatement;
import org.skife.jdbi.v2.StatementContext;
@@ -36,11 +36,13 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextBinder;
+import com.ning.billing.util.dao.BinderBase;
+import com.ning.billing.util.dao.MapperBase;
+
@ExternalizedSqlViaStringTemplate3()
public interface BundleSqlDao extends Transactional<BundleSqlDao>, CloseMe, Transmogrifier {
@@ -76,10 +78,10 @@ public interface BundleSqlDao extends Transactional<BundleSqlDao>, CloseMe, Tran
}
public static class ISubscriptionBundleSqlMapper extends MapperBase implements ResultSetMapper<SubscriptionBundle> {
+
@Override
public SubscriptionBundle map(int arg, ResultSet r,
StatementContext ctx) throws SQLException {
-
UUID id = UUID.fromString(r.getString("id"));
String key = r.getString("external_key");
UUID accountId = UUID.fromString(r.getString("account_id"));
@@ -88,6 +90,5 @@ public interface BundleSqlDao extends Transactional<BundleSqlDao>, CloseMe, Tran
SubscriptionBundleData bundle = new SubscriptionBundleData(id, key, accountId, startDate, lastSysUpdateDate);
return bundle;
}
-
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
index 14e0dfd..f216561 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
@@ -27,12 +27,14 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
+
import com.ning.billing.util.ChangeType;
import com.ning.billing.util.audit.dao.AuditSqlDao;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.customfield.dao.CustomFieldDao;
+
import org.joda.time.DateTime;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.Transaction;
@@ -45,6 +47,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.SubscriptionFactory;
@@ -78,8 +81,6 @@ import com.ning.billing.util.notificationq.NotificationQueue;
import com.ning.billing.util.notificationq.NotificationQueueService;
import com.ning.billing.util.notificationq.NotificationQueueService.NoSuchNotificationQueue;
-import javax.annotation.Nullable;
-
public class EntitlementSqlDao implements EntitlementDao {
private final static Logger log = LoggerFactory.getLogger(EntitlementSqlDao.class);
@@ -99,8 +100,10 @@ public class EntitlementSqlDao implements EntitlementDao {
@Inject
public EntitlementSqlDao(final IDBI dbi, final Clock clock,
- final AddonUtils addonUtils, final NotificationQueueService notificationQueueService,
- final CustomFieldDao customFieldDao, final Bus eventBus) {
+ final AddonUtils addonUtils, final NotificationQueueService notificationQueueService,
+ final CustomFieldDao customFieldDao,
+ final Bus eventBus) {
+
this.clock = clock;
this.subscriptionsDao = dbi.onDemand(SubscriptionSqlDao.class);
this.eventsDao = dbi.onDemand(EventSqlDao.class);
@@ -430,7 +433,7 @@ public class EntitlementSqlDao implements EntitlementDao {
}
private void cancelFutureEventFromTransaction(final UUID subscriptionId, final EventSqlDao dao,
- final EventType type, @Nullable final ApiEventType apiType,
+ final EventType type, final ApiEventType apiType,
final CallContext context) {
UUID futureEventId = null;
@@ -675,4 +678,5 @@ public class EntitlementSqlDao implements EntitlementDao {
subscription.setFields(fields);
}
}
+
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index a79705a..a3810c6 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -26,8 +26,8 @@ import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.api.EntitlementService;
import com.ning.billing.entitlement.api.SubscriptionApiService;
import com.ning.billing.entitlement.api.SubscriptionFactory;
-import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.billing.DefaultChargeThruApi;
import com.ning.billing.entitlement.api.migration.DefaultEntitlementMigrationApi;
import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
import com.ning.billing.entitlement.api.repair.DefaultEntitlementRepairApi;
@@ -60,7 +60,7 @@ public class EntitlementModule extends AbstractModule {
bind(RepairEntitlementLifecycleDao.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairEntitlementDao.class);
bind(RepairEntitlementDao.class).asEagerSingleton();
}
-
+
protected void installEntitlementCore() {
bind(SubscriptionFactory.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionFactory.class).asEagerSingleton();
@@ -77,8 +77,8 @@ public class EntitlementModule extends AbstractModule {
bind(EntitlementRepairApi.class).to(DefaultEntitlementRepairApi.class).asEagerSingleton();
bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
- bind(EntitlementBillingApi.class).to(DefaultEntitlementBillingApi.class).asEagerSingleton();
bind(EntitlementMigrationApi.class).to(DefaultEntitlementMigrationApi.class).asEagerSingleton();
+ bind(ChargeThruApi.class).to(DefaultChargeThruApi.class).asEagerSingleton();
}
@Override
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
index cceed8c..7380ec9 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
@@ -46,7 +46,6 @@ import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import org.testng.annotations.Test;
-@Test(groups = {"slow"})
public abstract class TestMigration extends TestApiBase {
public void testSingleBasePlan() {
@@ -69,7 +68,7 @@ public abstract class TestMigration extends TestApiBase {
Subscription subscription = subscriptions.get(0);
assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
assertEquals(subscription.getEndDate(), null);
- assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-annual");
@@ -103,7 +102,7 @@ public abstract class TestMigration extends TestApiBase {
subscriptions.get(0) : subscriptions.get(1);
assertDateWithin(baseSubscription.getStartDate(), beforeMigration, afterMigration);
assertEquals(baseSubscription.getEndDate(), null);
- assertEquals(baseSubscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(baseSubscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(baseSubscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
assertEquals(baseSubscription.getState(), SubscriptionState.ACTIVE);
assertEquals(baseSubscription.getCurrentPlan().getName(), "shotgun-annual");
@@ -115,7 +114,7 @@ public abstract class TestMigration extends TestApiBase {
// e.g : March 31 + 1 month => April 30 and April 30 - 1 month = March 30 which is != March 31 !!!!
assertEquals(aoSubscription.getStartDate(), initalAddonStart.plusMonths(1).minusMonths(1));
assertEquals(aoSubscription.getEndDate(), null);
- assertEquals(aoSubscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(aoSubscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(aoSubscription.getCurrentPhase().getPhaseType(), PhaseType.DISCOUNT);
assertEquals(aoSubscription.getState(), SubscriptionState.ACTIVE);
assertEquals(aoSubscription.getCurrentPlan().getName(), "telescopic-scope-monthly");
@@ -148,7 +147,7 @@ public abstract class TestMigration extends TestApiBase {
assertEquals(subscriptions.size(), 1);
Subscription subscription = subscriptions.get(0);
assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
- assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-annual");
@@ -163,7 +162,7 @@ public abstract class TestMigration extends TestApiBase {
assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
assertNotNull(subscription.getEndDate());
assertTrue(subscription.getEndDate().isAfterNow());
- assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(subscription.getCurrentPhase(), null);
assertEquals(subscription.getState(), SubscriptionState.CANCELLED);
assertNull(subscription.getCurrentPlan());
@@ -193,7 +192,7 @@ public abstract class TestMigration extends TestApiBase {
assertEquals(subscription.getStartDate(), trialDate);
assertEquals(subscription.getEndDate(), null);
- assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.TRIAL);
assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-monthly");
@@ -207,7 +206,7 @@ public abstract class TestMigration extends TestApiBase {
assertEquals(subscription.getStartDate(), trialDate);
assertEquals(subscription.getEndDate(), null);
- assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-monthly");
@@ -238,7 +237,7 @@ public abstract class TestMigration extends TestApiBase {
Subscription subscription = subscriptions.get(0);
assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
assertEquals(subscription.getEndDate(), null);
- assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-monthly");
@@ -250,7 +249,7 @@ public abstract class TestMigration extends TestApiBase {
assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
assertEquals(subscription.getEndDate(), null);
- assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME);
assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java
index 587ca46..34b2266 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java
@@ -23,9 +23,7 @@ import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
-@Test(groups = "slow")
public class TestMigrationSql extends TestMigration {
-
@Override
protected Injector getInjector() {
return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
index 5a63166..2dfadef 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
@@ -26,21 +26,18 @@ import java.net.URL;
import java.util.List;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.TestCallContext;
+import javax.annotation.Nullable;
+
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
-import org.testng.ITestResult;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
-import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.BeforeSuite;
import com.google.inject.Injector;
import com.ning.billing.account.api.AccountData;
@@ -57,7 +54,7 @@ import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.config.EntitlementConfig;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
import com.ning.billing.entitlement.api.repair.EntitlementRepairApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
@@ -73,12 +70,12 @@ import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.user.ApiEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.ning.billing.util.bus.BusService;
+import com.ning.billing.util.bus.DefaultBusService;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TestCallContext;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.bus.DefaultBusService;
-import com.ning.billing.util.bus.BusService;
-
-import javax.annotation.Nullable;
public abstract class TestApiBase {
@@ -88,7 +85,7 @@ public abstract class TestApiBase {
protected EntitlementService entitlementService;
protected EntitlementUserApi entitlementApi;
- protected EntitlementBillingApi billingApi;
+ protected ChargeThruApi billingApi;
protected EntitlementMigrationApi migrationApi;
protected EntitlementRepairApi repairApi;
@@ -133,12 +130,16 @@ public abstract class TestApiBase {
}
@BeforeClass(alwaysRun = true)
- public void setup() {
+ public void setup() throws Exception {
loadSystemPropertiesFromClasspath("/entitlement.properties");
final Injector g = getInjector();
entitlementService = g.getInstance(EntitlementService.class);
+ entitlementApi = g.getInstance(EntitlementUserApi.class);
+ billingApi = g.getInstance(ChargeThruApi.class);
+ migrationApi = g.getInstance(EntitlementMigrationApi.class);
+ repairApi = g.getInstance(EntitlementRepairApi.class);
catalogService = g.getInstance(CatalogService.class);
busService = g.getInstance(BusService.class);
config = g.getInstance(EntitlementConfig.class);
@@ -146,20 +147,17 @@ public abstract class TestApiBase {
clock = (ClockMock) g.getInstance(Clock.class);
helper = (isSqlTest(dao)) ? g.getInstance(MysqlTestingHelper.class) : null;
- try {
- ((DefaultCatalogService) catalogService).loadCatalog();
- ((DefaultBusService) busService).startBus();
- ((Engine) entitlementService).initialize();
- init(g);
- } catch (Exception e) {
- }
+ ((DefaultCatalogService) catalogService).loadCatalog();
+ ((DefaultBusService) busService).startBus();
+ ((Engine) entitlementService).initialize();
+ init(g);
}
private static boolean isSqlTest(EntitlementDao theDao) {
return (! (theDao instanceof MockEntitlementDaoMemory));
}
- private void setupMySQL() throws IOException {
+ private void setupMySQL() throws IOException {
if (helper != null) {
final String entitlementDdl = IOUtils.toString(TestApiBase.class.getResourceAsStream("/com/ning/billing/entitlement/ddl.sql"));
final String utilDdl = IOUtils.toString(TestApiBase.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
@@ -172,24 +170,15 @@ public abstract class TestApiBase {
private void init(Injector g) throws Exception {
setupMySQL();
-
accountData = getAccountData();
assertNotNull(accountData);
-
catalog = catalogService.getFullCatalog();
assertNotNull(catalog);
-
-
testListener = new ApiTestListener(busService.getBus());
- entitlementApi = entitlementService.getUserApi();
- billingApi = entitlementService.getBillingApi();
- migrationApi = entitlementService.getMigrationApi();
-
- repairApi = g.getInstance(EntitlementRepairApi.class);
}
@BeforeMethod(alwaysRun = true)
- public void setupTest() {
+ public void setupTest() throws Exception {
log.warn("RESET TEST FRAMEWORK\n\n");
@@ -200,26 +189,18 @@ public abstract class TestApiBase {
clock.resetDeltaFromReality();
((MockEntitlementDao) dao).reset();
- try {
- busService.getBus().register(testListener);
- UUID accountId = UUID.randomUUID();
- bundle = entitlementApi.createBundleForAccount(accountId, "myDefaultBundle", context);
- } catch (Exception e) {
- Assert.fail(e.getMessage());
- }
+ busService.getBus().register(testListener);
+ UUID accountId = UUID.randomUUID();
+ bundle = entitlementApi.createBundleForAccount(accountId, "myDefaultBundle", context);
assertNotNull(bundle);
((Engine)entitlementService).start();
}
@AfterMethod(alwaysRun = true)
- public void cleanupTest() {
- try {
- busService.getBus().unregister(testListener);
- ((Engine)entitlementService).stop();
- } catch (Exception e) {
- Assert.fail(e.getMessage());
- }
+ public void cleanupTest() throws Exception {
+ busService.getBus().unregister(testListener);
+ ((Engine)entitlementService).stop();
log.warn("DONE WITH TEST\n");
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
index 9db8d6e..4f26a75 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
@@ -21,6 +21,7 @@ import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
+import org.apache.commons.lang.NotImplementedException;
import org.joda.time.DateTime;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -38,8 +39,9 @@ import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PlanSpecifier;
import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.TestApiBase;
+import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
import com.ning.billing.util.clock.DefaultClock;
@@ -280,6 +282,7 @@ public class TestUserApiAddOn extends TestApiBase {
}
}
+ //TODO MDW - debugging reenable if you find this
@Test(enabled=true, groups={"slow"})
public void testAddonCreateWithSubscriptionAlign() {
@@ -352,7 +355,29 @@ public class TestUserApiAddOn extends TestApiBase {
testListener.pushNextApiExpectedEvent(NextEvent.PHASE);
// MOVE THROUGH TIME TO GO INTO EVERGREEN
- someTimeLater = aoCurrentPhase.getDuration();
+
+ // Talk with Stephane about this fix. It seemed that the add on phase change was not appearing in the queue
+ // hypothesis is that waiting a period that is exactly the duration of the phase might be an instant too short
+ // depending how the comparison works
+
+ //someTimeLater = aoCurrentPhase.getDuration();
+ someTimeLater = new Duration() {
+ @Override
+ public TimeUnit getUnit() {
+ return TimeUnit.DAYS;
+ }
+
+ @Override
+ public int getNumber() {
+ return 32;
+ }
+
+ @Override
+ public DateTime addToDateTime(DateTime dateTime) {
+ throw new NotImplementedException();
+ }
+ };
+
clock.addDeltaFromReality(someTimeLater);
clock.addDeltaFromReality(getDurationDay(1));
assertTrue(testListener.isApiCompleted(5000));
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
index 6500761..09046f1 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
@@ -17,25 +17,23 @@
package com.ning.billing.entitlement.api.user;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
-import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
-import com.ning.billing.util.clock.DefaultClock;
import org.joda.time.DateTime;
import org.testng.Assert;
-
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.entitlement.api.TestApiBase;
-import java.util.List;
+import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
+import com.ning.billing.util.clock.DefaultClock;
public abstract class TestUserApiCancel extends TestApiBase {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
index 57e34e9..7eccbdd 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
@@ -16,12 +16,13 @@
package com.ning.billing.entitlement.api.user;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
-import org.testng.annotations.Test;
public class TestUserApiCancelMemory extends TestUserApiCancel {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java
index 469d374..6d02736 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java
@@ -16,12 +16,13 @@
package com.ning.billing.entitlement.api.user;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
-import org.testng.annotations.Test;
public class TestUserApiCancelSql extends TestUserApiCancel {
@@ -34,7 +35,7 @@ public class TestUserApiCancelSql extends TestUserApiCancel {
}
@Test(enabled= false, groups={"stress"})
- public void stressTest() throws EntitlementBillingApiException {
+ public void stressTest() throws Exception {
for (int i = 0; i < MAX_STRESS_ITERATIONS; i++) {
cleanupTest();
setupTest();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
index eed1726..f43e843 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
@@ -29,14 +29,13 @@ import org.testng.Assert;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.TestApiBase;
-
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.user.ApiEvent;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
index f390cdb..8bbdd2d 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
@@ -16,12 +16,13 @@
package com.ning.billing.entitlement.api.user;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
-import org.testng.annotations.Test;
public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
index 735099c..509b056 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
@@ -16,12 +16,13 @@
package com.ning.billing.entitlement.api.user;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
-import org.testng.annotations.Test;
public class TestUserApiChangePlanSql extends TestUserApiChangePlan {
@@ -33,7 +34,7 @@ public class TestUserApiChangePlanSql extends TestUserApiChangePlan {
}
@Test(enabled= true, groups={"stress"})
- public void stressTest() throws EntitlementBillingApiException {
+ public void stressTest() throws Exception {
for (int i = 0; i < MAX_STRESS_ITERATIONS; i++) {
cleanupTest();
setupTest();
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 392722f..ef4533d 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
@@ -22,19 +22,20 @@ import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
+
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.util.clock.DefaultClock;
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 b674e34..7987d87 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
@@ -16,11 +16,12 @@
package com.ning.billing.entitlement.api.user;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
-import org.testng.annotations.Test;
public class TestUserApiCreateMemory extends TestUserApiCreate {
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 6820fec..c890da7 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
@@ -16,11 +16,12 @@
package com.ning.billing.entitlement.api.user;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
-import org.testng.annotations.Test;
public class TestUserApiCreateSql extends TestUserApiCreate {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
index 2f58619..502d133 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
@@ -16,31 +16,33 @@
package com.ning.billing.entitlement.api.user;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
-
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.TestApiBase;
-
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
import com.ning.billing.util.clock.DefaultClock;
-import org.joda.time.DateTime;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import static org.testng.Assert.*;
public class TestUserApiDemos extends TestApiBase {
@@ -174,7 +176,7 @@ public class TestUserApiDemos extends TestApiBase {
Plan currentPlan = subscription.getCurrentPlan();
PlanPhase currentPhase = subscription.getCurrentPhase();
- String priceList = subscription.getCurrentPriceList();
+ String priceList = subscription.getCurrentPriceList().getName();
System.out.println("");
System.out.println("\t CURRENT TIME = " + clock.getUTCNow());
System.out.println("");
@@ -190,7 +192,7 @@ public class TestUserApiDemos extends TestApiBase {
}
@Test(enabled= true, groups={"stress"})
- public void stressTest() throws EntitlementBillingApiException {
+ public void stressTest() throws Exception {
for (int i = 0; i < 100; i++) {
cleanupTest();
setupTest();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
index 92519ac..c3f6061 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
@@ -16,6 +16,18 @@
package com.ning.billing.entitlement.api.user;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
@@ -24,20 +36,10 @@ import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Duration;
import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
import com.ning.billing.util.clock.DefaultClock;
-import org.joda.time.DateTime;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import javax.annotation.Nullable;
-import java.util.UUID;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
public class TestUserApiError extends TestApiBase {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
index 11d13be..b7506dd 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
@@ -25,11 +25,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
-import com.google.inject.Injector;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.TestApiBase;
public abstract class TestUserApiRecreate extends TestApiBase {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
index ca136d1..92ac1b0 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
@@ -16,6 +16,14 @@
package com.ning.billing.entitlement.api.user;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
@@ -23,17 +31,11 @@ import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Duration;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.PlanPhase;
-
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
import com.ning.billing.util.clock.DefaultClock;
-import org.joda.time.DateTime;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.*;
public class TestUserApiScenarios extends TestApiBase {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
index 25f969e..90966d8 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
@@ -16,16 +16,11 @@
package com.ning.billing.entitlement.api.user;
-import java.util.List;
-
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.clock.DefaultClock;
+import java.util.List;
+
import org.joda.time.DateTime;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -35,9 +30,14 @@ import com.google.inject.Injector;
import com.google.inject.Stage;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.TestApiBase;
import com.ning.billing.entitlement.glue.MockEngineModuleSql;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.DefaultClock;
import com.ning.billing.util.customfield.CustomField;
@@ -51,7 +51,7 @@ public class TestUserCustomFieldsSql extends TestApiBase {
}
@Test(enabled=false, groups={"slow"})
- public void stress() {
+ public void stress() throws Exception {
cleanupTest();
for (int i = 0; i < 20; i++) {
setupTest();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
index e905008..f777204 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
@@ -25,7 +25,6 @@ import java.util.Map;
import java.util.TreeSet;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
import org.apache.commons.lang.NotImplementedException;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
@@ -52,6 +51,7 @@ import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
import com.ning.billing.entitlement.events.user.ApiEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.notificationq.NotificationKey;
import com.ning.billing.util.notificationq.NotificationQueue;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
index b048f36..3851eb2 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
@@ -16,9 +16,9 @@
package com.ning.billing.entitlement.engine.dao;
+
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.customfield.dao.CustomFieldDao;
-import com.ning.billing.util.tag.dao.TagDao;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.Transaction;
import org.skife.jdbi.v2.TransactionStatus;
@@ -27,9 +27,9 @@ import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
import com.google.inject.Inject;
-import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory;
import com.ning.billing.entitlement.engine.addon.AddonUtils;
import com.ning.billing.util.clock.Clock;
+
import com.ning.billing.util.notificationq.NotificationQueueService;
public class MockEntitlementDaoSql extends EntitlementSqlDao implements MockEntitlementDao {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
index acb1a2a..c795ca5 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
@@ -25,6 +25,7 @@ import com.ning.billing.util.glue.CallContextModule;
public class MockEngineModule extends EntitlementModule {
+
@Override
protected void configure() {
super.configure();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
index ebe60c4..6d863a9 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
@@ -16,23 +16,25 @@
package com.ning.billing.entitlement.glue;
+
import com.google.inject.name.Names;
+
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.IDBI;
+
+
import com.ning.billing.dbi.DBIProvider;
import com.ning.billing.dbi.DbiConfig;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.api.repair.RepairEntitlementLifecycleDao;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
-import com.ning.billing.entitlement.engine.dao.EntitlementSqlDao;
import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoSql;
+
import com.ning.billing.entitlement.engine.dao.RepairEntitlementDao;
-import com.ning.billing.util.clock.Clock;
-import com.ning.billing.util.clock.ClockMock;
+
import com.ning.billing.util.glue.FieldStoreModule;
import com.ning.billing.util.glue.NotificationQueueModule;
-import org.skife.config.ConfigurationObjectFactory;
-import org.skife.jdbi.v2.IDBI;
-
public class MockEngineModuleSql extends MockEngineModule {
invoice/pom.xml 12(+12 -0)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 8db3258..552b41d 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -52,6 +52,18 @@
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.ning.billing</groupId>
<artifactId>killbill-catalog</artifactId>
<scope>test</scope>
</dependency>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java b/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java
index 6f033db..da41e77 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java
@@ -26,18 +26,14 @@ import com.ning.billing.util.bus.Bus;
public class DefaultInvoiceService implements InvoiceService {
public static final String INVOICE_SERVICE_NAME = "invoice-service";
- private final InvoiceUserApi userApi;
- private final InvoicePaymentApi paymentApi;
private final NextBillingDateNotifier dateNotifier;
private final InvoiceListener invoiceListener;
private final Bus eventBus;
@Inject
- public DefaultInvoiceService(InvoiceListener invoiceListener, Bus eventBus, InvoiceUserApi userApi, InvoicePaymentApi paymentApi, NextBillingDateNotifier dateNotifier) {
+ public DefaultInvoiceService(InvoiceListener invoiceListener, Bus eventBus, NextBillingDateNotifier dateNotifier) {
this.invoiceListener = invoiceListener;
this.eventBus = eventBus;
- this.userApi = userApi;
- this.paymentApi = paymentApi;
this.dateNotifier = dateNotifier;
}
@@ -47,16 +43,6 @@ public class DefaultInvoiceService implements InvoiceService {
return INVOICE_SERVICE_NAME;
}
- @Override
- public InvoiceUserApi getUserApi() {
- return userApi;
- }
-
- @Override
- public InvoicePaymentApi getPaymentApi() {
- return paymentApi;
- }
-
@LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.INIT_SERVICE)
public void initialize() {
dateNotifier.initialize();
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index beadd47..9572e57 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -24,14 +24,6 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
-import com.ning.billing.util.ChangeType;
-import com.ning.billing.util.audit.dao.AuditSqlDao;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.customfield.CustomField;
-import com.ning.billing.util.customfield.dao.CustomFieldSqlDao;
-import com.ning.billing.util.tag.ControlTagType;
-import com.ning.billing.util.tag.Tag;
-import com.ning.billing.util.tag.dao.TagDao;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.Transaction;
@@ -41,7 +33,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceCreationEvent;
import com.ning.billing.invoice.api.InvoiceItem;
@@ -50,14 +41,23 @@ import com.ning.billing.invoice.api.user.DefaultInvoiceCreationNotification;
import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
import com.ning.billing.invoice.model.RecurringInvoiceItem;
import com.ning.billing.invoice.notification.NextBillingDatePoster;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.audit.dao.AuditSqlDao;
import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.customfield.dao.CustomFieldSqlDao;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.dao.TagDao;
public class DefaultInvoiceDao implements InvoiceDao {
private final static Logger log = LoggerFactory.getLogger(DefaultInvoiceDao.class);
private final InvoiceSqlDao invoiceSqlDao;
private final InvoicePaymentSqlDao invoicePaymentSqlDao;
- private final EntitlementBillingApi entitlementBillingApi;
+ private final BillingApi billingApi;
private final TagDao tagDao;
private final Bus eventBus;
@@ -66,13 +66,13 @@ public class DefaultInvoiceDao implements InvoiceDao {
@Inject
public DefaultInvoiceDao(final IDBI dbi, final Bus eventBus,
- final EntitlementBillingApi entitlementBillingApi,
+ final BillingApi entitlementBillingApi,
final NextBillingDatePoster nextBillingDatePoster,
final TagDao tagDao) {
this.invoiceSqlDao = dbi.onDemand(InvoiceSqlDao.class);
this.invoicePaymentSqlDao = dbi.onDemand(InvoicePaymentSqlDao.class);
this.eventBus = eventBus;
- this.entitlementBillingApi = entitlementBillingApi;
+ this.billingApi = entitlementBillingApi;
this.nextBillingDatePoster = nextBillingDatePoster;
this.tagDao = tagDao;
}
@@ -384,9 +384,11 @@ public class DefaultInvoiceDao implements InvoiceDao {
addInvoiceItemsToChargeThroughDates(chargeThroughDates, recurringItems);
for (UUID subscriptionId : chargeThroughDates.keySet()) {
- DateTime chargeThroughDate = chargeThroughDates.get(subscriptionId);
- log.info("Setting CTD for subscription {} to {}", subscriptionId.toString(), chargeThroughDate.toString());
- entitlementBillingApi.setChargedThroughDateFromTransaction(dao, subscriptionId, chargeThroughDate, context);
+ if(subscriptionId != null) {
+ DateTime chargeThroughDate = chargeThroughDates.get(subscriptionId);
+ log.info("Setting CTD for subscription {} to {}", subscriptionId.toString(), chargeThroughDate.toString());
+ billingApi.setChargedThroughDateFromTransaction(dao, subscriptionId, chargeThroughDate, context);
+ }
}
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.java
index f564658..b89c68b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.java
@@ -16,12 +16,17 @@
package com.ning.billing.invoice.dao;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallContextBinder;
-import com.ning.billing.util.entity.EntityDao;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
+
import org.joda.time.DateTime;
import org.skife.jdbi.v2.SQLStatement;
import org.skife.jdbi.v2.StatementContext;
@@ -36,16 +41,12 @@ import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.math.BigDecimal;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-import java.util.UUID;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextBinder;
+import com.ning.billing.util.entity.EntityDao;
@ExternalizedSqlViaStringTemplate3()
@RegisterMapper(FixedPriceInvoiceItemSqlDao.FixedPriceInvoiceItemMapper.class)
@@ -78,9 +79,10 @@ public interface FixedPriceInvoiceItemSqlDao extends EntityDao<InvoiceItem> {
return new Binder<FixedPriceInvoiceItemBinder, FixedPriceInvoiceItem>() {
public void bind(SQLStatement q, FixedPriceInvoiceItemBinder bind, FixedPriceInvoiceItem item) {
q.bind("id", item.getId().toString());
- q.bind("invoiceId", item.getInvoiceId().toString());
q.bind("accountId", item.getAccountId().toString());
- q.bind("subscriptionId", item.getSubscriptionId().toString());
+ q.bind("invoiceId", item.getInvoiceId().toString());
+ q.bind("bundleId", item.getBundleId() == null ? null : item.getBundleId().toString());
+ q.bind("subscriptionId", item.getSubscriptionId() == null ? null : item.getSubscriptionId().toString());
q.bind("planName", item.getPlanName());
q.bind("phaseName", item.getPhaseName());
q.bind("startDate", item.getStartDate().toDate());
@@ -99,7 +101,8 @@ public interface FixedPriceInvoiceItemSqlDao extends EntityDao<InvoiceItem> {
UUID id = UUID.fromString(result.getString("id"));
UUID invoiceId = UUID.fromString(result.getString("invoice_id"));
UUID accountId = UUID.fromString(result.getString("account_id"));
- UUID subscriptionId = UUID.fromString(result.getString("subscription_id"));
+ UUID bundleId = result.getString("bundle_id") == null ? null :UUID.fromString(result.getString("bundle_id"));
+ UUID subscriptionId = result.getString("subscription_id") == null ? null : UUID.fromString(result.getString("subscription_id"));
String planName = result.getString("plan_name");
String phaseName = result.getString("phase_name");
DateTime startDate = new DateTime(result.getTimestamp("start_date"));
@@ -109,7 +112,7 @@ public interface FixedPriceInvoiceItemSqlDao extends EntityDao<InvoiceItem> {
String createdBy = result.getString("created_by");
DateTime createdDate = new DateTime(result.getTimestamp("created_date"));
- return new FixedPriceInvoiceItem(id, invoiceId, accountId, subscriptionId, planName, phaseName,
+ return new FixedPriceInvoiceItem(id, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName,
startDate, endDate, amount, currency, createdBy, createdDate);
}
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.java
index 29dfb9e..46c5153 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.java
@@ -16,12 +16,17 @@
package com.ning.billing.invoice.dao;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.model.RecurringInvoiceItem;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallContextBinder;
-import com.ning.billing.util.entity.EntityDao;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
+
import org.joda.time.DateTime;
import org.skife.jdbi.v2.SQLStatement;
import org.skife.jdbi.v2.StatementContext;
@@ -36,16 +41,12 @@ import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.math.BigDecimal;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-import java.util.UUID;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextBinder;
+import com.ning.billing.util.entity.EntityDao;
@ExternalizedSqlViaStringTemplate3()
@RegisterMapper(RecurringInvoiceItemSqlDao.RecurringInvoiceItemMapper.class)
@@ -79,7 +80,8 @@ public interface RecurringInvoiceItemSqlDao extends EntityDao<InvoiceItem> {
q.bind("id", item.getId().toString());
q.bind("invoiceId", item.getInvoiceId().toString());
q.bind("accountId", item.getAccountId().toString());
- q.bind("subscriptionId", item.getSubscriptionId().toString());
+ q.bind("bundleId", item.getBundleId() == null ? null : item.getBundleId().toString());
+ q.bind("subscriptionId", item.getSubscriptionId() == null ? null : item.getSubscriptionId().toString());
q.bind("planName", item.getPlanName());
q.bind("phaseName", item.getPhaseName());
q.bind("startDate", item.getStartDate().toDate());
@@ -100,7 +102,8 @@ public interface RecurringInvoiceItemSqlDao extends EntityDao<InvoiceItem> {
UUID id = UUID.fromString(result.getString("id"));
UUID invoiceId = UUID.fromString(result.getString("invoice_id"));
UUID accountId = UUID.fromString(result.getString("account_id"));
- UUID subscriptionId = UUID.fromString(result.getString("subscription_id"));
+ UUID subscriptionId = result.getString("subscription_id") == null ? null : UUID.fromString(result.getString("subscription_id"));
+ UUID bundleId = result.getString("bundle_id") == null ? null : UUID.fromString(result.getString("bundle_id"));
String planName = result.getString("plan_name");
String phaseName = result.getString("phase_name");
DateTime startDate = new DateTime(result.getTimestamp("start_date"));
@@ -113,8 +116,9 @@ public interface RecurringInvoiceItemSqlDao extends EntityDao<InvoiceItem> {
String createdBy = result.getString("created_by");
DateTime createdDate = new DateTime(result.getTimestamp("created_date"));
- return new RecurringInvoiceItem(id, invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate,
+ return new RecurringInvoiceItem(id, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate,
amount, rate, currency, reversedItemId, createdBy, createdDate);
+
}
}
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
index 7d1253c..870e7c5 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -21,12 +21,6 @@ import java.util.List;
import java.util.SortedSet;
import java.util.UUID;
-import com.ning.billing.util.bus.Bus;
-import com.ning.billing.util.bus.Bus.EventBusException;
-import com.ning.billing.util.bus.BusEvent;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.clock.Clock;
-
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +31,6 @@ import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.entitlement.api.billing.BillingEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
@@ -46,17 +39,23 @@ import com.ning.billing.invoice.api.user.DefaultEmptyInvoiceNotification;
import com.ning.billing.invoice.dao.InvoiceDao;
import com.ning.billing.invoice.model.BillingEventSet;
import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.bus.Bus.EventBusException;
+import com.ning.billing.util.bus.BusEvent;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.globallocker.GlobalLock;
import com.ning.billing.util.globallocker.GlobalLocker;
-import com.ning.billing.util.globallocker.LockFailedException;
import com.ning.billing.util.globallocker.GlobalLocker.LockerService;
+import com.ning.billing.util.globallocker.LockFailedException;
public class InvoiceDispatcher {
private final static Logger log = LoggerFactory.getLogger(InvoiceDispatcher.class);
private final static int NB_LOCK_TRY = 5;
private final InvoiceGenerator generator;
- private final EntitlementBillingApi entitlementBillingApi;
+ private final BillingApi billingApi;
private final AccountUserApi accountUserApi;
private final InvoiceDao invoiceDao;
private final GlobalLocker locker;
@@ -67,13 +66,13 @@ public class InvoiceDispatcher {
@Inject
public InvoiceDispatcher(final InvoiceGenerator generator, final AccountUserApi accountUserApi,
- final EntitlementBillingApi entitlementBillingApi,
+ final BillingApi billingApi,
final InvoiceDao invoiceDao,
final GlobalLocker locker,
final Bus eventBus,
final Clock clock) {
this.generator = generator;
- this.entitlementBillingApi = entitlementBillingApi;
+ this.billingApi = billingApi;
this.accountUserApi = accountUserApi;
this.invoiceDao = invoiceDao;
this.locker = locker;
@@ -100,7 +99,7 @@ public class InvoiceDispatcher {
return;
}
- UUID accountId = entitlementBillingApi.getAccountIdFromSubscriptionId(subscriptionId);
+ UUID accountId = billingApi.getAccountIdFromSubscriptionId(subscriptionId);
if (accountId == null) {
log.error("Failed handling entitlement change.",
new InvoiceApiException(ErrorCode.INVOICE_NO_ACCOUNT_ID_FOR_SUBSCRIPTION_ID, subscriptionId.toString()));
@@ -148,7 +147,7 @@ public class InvoiceDispatcher {
return null;
}
- SortedSet<BillingEvent> events = entitlementBillingApi.getBillingEventsForAccount(accountId);
+ SortedSet<BillingEvent> events = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId);
BillingEventSet billingEvents = new BillingEventSet(events);
Currency targetCurrency = account.getCurrency();
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/BillingEventSet.java b/invoice/src/main/java/com/ning/billing/invoice/model/BillingEventSet.java
index da95559..8cf1e1e 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/BillingEventSet.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/BillingEventSet.java
@@ -28,7 +28,10 @@ public class BillingEventSet extends ArrayList<BillingEvent> {
public BillingEventSet(Collection<BillingEvent> events) {
super();
- addAll(events);
+ if(events != null) {
+ addAll(events);
+
+ }
}
public boolean isLast(final BillingEvent event) {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
index 389010c..627a7be 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
@@ -16,6 +16,18 @@
package com.ning.billing.invoice.model;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.joda.time.Months;
+
import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
import com.ning.billing.catalog.api.BillingPeriod;
@@ -28,16 +40,6 @@ import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.util.clock.Clock;
-import org.joda.time.DateTime;
-import org.joda.time.Months;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.UUID;
-import javax.annotation.Nullable;
public class DefaultInvoiceGenerator implements InvoiceGenerator {
private static final int ROUNDING_MODE = InvoicingConfiguration.getRoundingMode();
@@ -211,7 +213,9 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
if (rate != null) {
BigDecimal amount = itemDatum.getNumberOfCycles().multiply(rate).setScale(NUMBER_OF_DECIMALS, ROUNDING_MODE);
- RecurringInvoiceItem recurringItem = new RecurringInvoiceItem(invoiceId, accountId,
+ RecurringInvoiceItem recurringItem = new RecurringInvoiceItem(invoiceId,
+ accountId,
+ thisEvent.getSubscription().getBundleId(),
thisEvent.getSubscription().getId(),
thisEvent.getPlan().getName(),
thisEvent.getPlanPhase().getName(),
@@ -246,7 +250,8 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
Duration duration = thisEvent.getPlanPhase().getDuration();
DateTime endDate = duration.addToDateTime(thisEvent.getEffectiveDate());
- return new FixedPriceInvoiceItem(invoiceId, accountId, thisEvent.getSubscription().getId(),
+ return new FixedPriceInvoiceItem(invoiceId, accountId, thisEvent.getSubscription().getBundleId(),
+ thisEvent.getSubscription().getId(),
thisEvent.getPlan().getName(), thisEvent.getPlanPhase().getName(),
thisEvent.getEffectiveDate(), endDate, fixedPrice, currency);
} else {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/FixedPriceInvoiceItem.java b/invoice/src/main/java/com/ning/billing/invoice/model/FixedPriceInvoiceItem.java
index 91e49fa..8c2398b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/FixedPriceInvoiceItem.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/FixedPriceInvoiceItem.java
@@ -16,23 +16,25 @@
package com.ning.billing.invoice.model;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.InvoiceItem;
-import org.joda.time.DateTime;
-
import java.math.BigDecimal;
import java.util.UUID;
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+
public class FixedPriceInvoiceItem extends InvoiceItemBase {
- public FixedPriceInvoiceItem(UUID invoiceId, UUID accountId, UUID subscriptionId, String planName, String phaseName,
+
+ public FixedPriceInvoiceItem(UUID invoiceId, UUID accountId, UUID bundleId, UUID subscriptionId, String planName, String phaseName,
DateTime startDate, DateTime endDate, BigDecimal amount, Currency currency) {
- super(invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency);
+ super(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency);
}
- public FixedPriceInvoiceItem(UUID id, UUID invoiceId, UUID accountId, UUID subscriptionId, String planName, String phaseName,
+ public FixedPriceInvoiceItem(UUID id, UUID invoiceId, UUID accountId, UUID bundleId, UUID subscriptionId, String planName, String phaseName,
DateTime startDate, DateTime endDate, BigDecimal amount, Currency currency,
String createdBy, DateTime createdDate) {
- super(id, invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency, createdBy, createdDate);
+ super(id, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency, createdBy, createdDate);
}
@Override
@@ -49,6 +51,7 @@ public class FixedPriceInvoiceItem extends InvoiceItemBase {
public int hashCode() {
int result = accountId.hashCode();
result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
result = 31 * result + (planName != null ? planName.hashCode() : 0);
result = 31 * result + (phaseName != null ? phaseName.hashCode() : 0);
result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
@@ -66,12 +69,17 @@ public class FixedPriceInvoiceItem extends InvoiceItemBase {
FixedPriceInvoiceItem that = (FixedPriceInvoiceItem) item;
int compareAccounts = getAccountId().compareTo(that.getAccountId());
- if (compareAccounts == 0) {
- int compareSubscriptions = getSubscriptionId().compareTo(that.getSubscriptionId());
- if (compareSubscriptions == 0) {
- return getStartDate().compareTo(that.getStartDate());
+ if (compareAccounts == 0 && bundleId != null) {
+ int compareBundles = getBundleId().compareTo(that.getBundleId());
+ if (compareBundles == 0 && subscriptionId != null) {
+ int compareSubscriptions = getSubscriptionId().compareTo(that.getSubscriptionId());
+ if (compareSubscriptions == 0) {
+ return getStartDate().compareTo(that.getStartDate());
+ } else {
+ return compareSubscriptions;
+ }
} else {
- return compareSubscriptions;
+ return compareBundles;
}
} else {
return compareAccounts;
@@ -84,7 +92,8 @@ public class FixedPriceInvoiceItem extends InvoiceItemBase {
sb.append("InvoiceItem = {").append("id = ").append(id.toString()).append(", ");
sb.append("invoiceId = ").append(invoiceId.toString()).append(", ");
sb.append("accountId = ").append(accountId.toString()).append(", ");
- sb.append("subscriptionId = ").append(subscriptionId.toString()).append(", ");
+ sb.append("subscriptionId = ").append(subscriptionId == null ? null : subscriptionId.toString()).append(", ");
+ sb.append("bundleId = ").append(bundleId == null ? null : bundleId.toString()).append(", ");
sb.append("planName = ").append(planName).append(", ");
sb.append("phaseName = ").append(phaseName).append(", ");
sb.append("startDate = ").append(startDate.toString()).append(", ");
@@ -110,6 +119,8 @@ public class FixedPriceInvoiceItem extends InvoiceItemBase {
if (accountId.compareTo(that.accountId) != 0) return false;
if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null)
return false;
+ if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null)
+ return false;
if (amount != null ? amount.compareTo(that.amount) != 0 : that.amount != null) return false;
if (currency != that.currency) return false;
if (startDate != null ? startDate.compareTo(that.startDate) != 0 : that.startDate != null) return false;
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemBase.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemBase.java
index 2f16468..175a08e 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemBase.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemBase.java
@@ -29,6 +29,7 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem
protected final UUID invoiceId;
protected final UUID accountId;
protected final UUID subscriptionId;
+ protected final UUID bundleId;
protected final String planName;
protected final String phaseName;
protected final DateTime startDate;
@@ -36,19 +37,21 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem
protected final BigDecimal amount;
protected final Currency currency;
- public InvoiceItemBase(UUID invoiceId, UUID accountId, @Nullable UUID subscriptionId, String planName, String phaseName,
- DateTime startDate, DateTime endDate, BigDecimal amount, Currency currency) {
- this(UUID.randomUUID(), invoiceId, accountId, subscriptionId, planName, phaseName,
+ public InvoiceItemBase(UUID invoiceId, UUID accountId, UUID bundleId, UUID subscriptionId, String planName, String phaseName,
+ DateTime startDate, DateTime endDate, BigDecimal amount, Currency currency) {
+ this(UUID.randomUUID(), invoiceId, accountId, bundleId, subscriptionId, planName, phaseName,
startDate, endDate, amount, currency, null, null);
}
- public InvoiceItemBase(UUID id, UUID invoiceId, UUID accountId, @Nullable UUID subscriptionId, String planName, String phaseName,
- DateTime startDate, DateTime endDate, BigDecimal amount, Currency currency,
- @Nullable String createdBy, @Nullable DateTime createdDate) {
+
+ public InvoiceItemBase(UUID id, UUID invoiceId, UUID accountId, @Nullable UUID bundleId, @Nullable UUID subscriptionId, String planName, String phaseName,
+ DateTime startDate, DateTime endDate, BigDecimal amount, Currency currency,
+ @Nullable String createdBy, @Nullable DateTime createdDate) {
super(id, createdBy, createdDate);
this.invoiceId = invoiceId;
this.accountId = accountId;
this.subscriptionId = subscriptionId;
+ this.bundleId = bundleId;
this.planName = planName;
this.phaseName = phaseName;
this.startDate = startDate;
@@ -72,6 +75,10 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem
}
@Override
+ public UUID getBundleId() {
+ return bundleId;
+ }
+
public UUID getAccountId() {
return accountId;
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/MigrationInvoiceItem.java b/invoice/src/main/java/com/ning/billing/invoice/model/MigrationInvoiceItem.java
index 01c1296..ec0962b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/MigrationInvoiceItem.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/MigrationInvoiceItem.java
@@ -25,10 +25,9 @@ import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.MigrationPlan;
public class MigrationInvoiceItem extends FixedPriceInvoiceItem {
- private final static UUID MIGRATION_SUBSCRIPTION_ID = UUID.fromString("ed25f954-3aa2-4422-943b-c3037ad7257c"); //new UUID(0L,0L);
public MigrationInvoiceItem(UUID invoiceId, UUID accountId, DateTime startDate, BigDecimal amount, Currency currency) {
- super(invoiceId, accountId, MIGRATION_SUBSCRIPTION_ID, MigrationPlan.MIGRATION_PLAN_NAME, MigrationPlan.MIGRATION_PLAN_PHASE_NAME,
+ super(invoiceId, accountId, null, null, MigrationPlan.MIGRATION_PLAN_NAME, MigrationPlan.MIGRATION_PLAN_PHASE_NAME,
startDate, startDate, amount, currency);
}
}
\ No newline at end of file
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/RecurringInvoiceItem.java b/invoice/src/main/java/com/ning/billing/invoice/model/RecurringInvoiceItem.java
index f63599d..683a610 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/RecurringInvoiceItem.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/RecurringInvoiceItem.java
@@ -27,43 +27,41 @@ public class RecurringInvoiceItem extends InvoiceItemBase {
private final BigDecimal rate;
private final UUID reversedItemId;
- public RecurringInvoiceItem(UUID invoiceId, UUID accountId, UUID subscriptionId, String planName, String phaseName,
+ public RecurringInvoiceItem(UUID invoiceId, UUID accountId, UUID bundleId, UUID subscriptionId, String planName, String phaseName,
DateTime startDate, DateTime endDate,
BigDecimal amount, BigDecimal rate,
- Currency currency) {
- super(invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency);
+ Currency currency) {
+ super(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency);
this.rate = rate;
this.reversedItemId = null;
}
- public RecurringInvoiceItem(UUID invoiceId, UUID accountId, UUID subscriptionId, String planName, String phaseName,
+ public RecurringInvoiceItem(UUID invoiceId, UUID accountId, UUID bundleId, UUID subscriptionId, String planName, String phaseName,
DateTime startDate, DateTime endDate,
BigDecimal amount, BigDecimal rate,
Currency currency, UUID reversedItemId) {
- super(invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate,
+ super(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate,
amount, currency);
this.rate = rate;
this.reversedItemId = reversedItemId;
}
- public RecurringInvoiceItem(UUID id, UUID invoiceId, UUID accountId, UUID subscriptionId, String planName, String phaseName,
+ public RecurringInvoiceItem(UUID id, UUID invoiceId, UUID accountId, UUID bundleId, UUID subscriptionId, String planName, String phaseName,
DateTime startDate, DateTime endDate,
BigDecimal amount, BigDecimal rate,
Currency currency,
String createdBy, DateTime createdDate) {
- super(id, invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency, createdBy, createdDate);
-
+ super(id, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency, createdBy, createdDate);
this.rate = rate;
this.reversedItemId = null;
}
- public RecurringInvoiceItem(UUID id, UUID invoiceId, UUID accountId, UUID subscriptionId, String planName, String phaseName,
+ public RecurringInvoiceItem(UUID id, UUID invoiceId, UUID accountId, UUID bundleId, UUID subscriptionId, String planName, String phaseName,
DateTime startDate, DateTime endDate,
BigDecimal amount, BigDecimal rate,
Currency currency, UUID reversedItemId,
String createdBy, DateTime createdDate) {
- super(id, invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency, createdBy, createdDate);
-
+ super(id, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount, currency, createdBy, createdDate);
this.rate = rate;
this.reversedItemId = reversedItemId;
}
@@ -71,7 +69,8 @@ public class RecurringInvoiceItem extends InvoiceItemBase {
@Override
public InvoiceItem asCredit() {
BigDecimal amountNegated = amount == null ? null : amount.negate();
- return new RecurringInvoiceItem(invoiceId, accountId, subscriptionId, planName, phaseName, startDate, endDate,
+
+ return new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate,
amountNegated, rate, currency, id);
}
@@ -103,17 +102,23 @@ public class RecurringInvoiceItem extends InvoiceItemBase {
RecurringInvoiceItem that = (RecurringInvoiceItem) item;
int compareAccounts = getAccountId().compareTo(that.getAccountId());
- if (compareAccounts == 0) {
- int compareSubscriptions = getSubscriptionId().compareTo(that.getSubscriptionId());
- if (compareSubscriptions == 0) {
- int compareStartDates = getStartDate().compareTo(that.getStartDate());
- if (compareStartDates == 0) {
- return getEndDate().compareTo(that.getEndDate());
+ if (compareAccounts == 0 && bundleId != null) {
+ int compareBundles = getBundleId().compareTo(that.getBundleId());
+ if (compareBundles == 0 && subscriptionId != null) {
+
+ int compareSubscriptions = getSubscriptionId().compareTo(that.getSubscriptionId());
+ if (compareSubscriptions == 0) {
+ int compareStartDates = getStartDate().compareTo(that.getStartDate());
+ if (compareStartDates == 0) {
+ return getEndDate().compareTo(that.getEndDate());
+ } else {
+ return compareStartDates;
+ }
} else {
- return compareStartDates;
+ return compareSubscriptions;
}
} else {
- return compareSubscriptions;
+ return compareBundles;
}
} else {
return compareAccounts;
@@ -137,7 +142,10 @@ public class RecurringInvoiceItem extends InvoiceItemBase {
if (rate.compareTo(that.rate) != 0) return false;
if (reversedItemId != null ? !reversedItemId.equals(that.reversedItemId) : that.reversedItemId != null)
return false;
- if (!subscriptionId.equals(that.subscriptionId)) return false;
+ if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null)
+ return false;
+ if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null)
+ return false;
return true;
}
@@ -146,6 +154,7 @@ public class RecurringInvoiceItem extends InvoiceItemBase {
public int hashCode() {
int result = accountId.hashCode();
result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
result = 31 * result + planName.hashCode();
result = 31 * result + phaseName.hashCode();
result = 31 * result + startDate.hashCode();
@@ -165,6 +174,8 @@ public class RecurringInvoiceItem extends InvoiceItemBase {
sb.append(startDate.toString()).append(", ");
sb.append(endDate.toString()).append(", ");
sb.append(amount.toString()).append(", ");
+ sb.append("subscriptionId = ").append(subscriptionId == null ? null : subscriptionId.toString()).append(", ");
+ sb.append("bundleId = ").append(bundleId == null ? null : bundleId.toString()).append(", ");
return sb.toString();
}
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.sql.stg
index 100182f..659d876 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/FixedPriceInvoiceItemSqlDao.sql.stg
@@ -4,6 +4,7 @@ fields(prefix) ::= <<
<prefix>id,
<prefix>invoice_id,
<prefix>account_id,
+ <prefix>bundle_id,
<prefix>subscription_id,
<prefix>plan_name,
<prefix>phase_name,
@@ -42,13 +43,13 @@ getInvoiceItemsBySubscription() ::= <<
create() ::= <<
INSERT INTO fixed_invoice_items(<fields()>)
- VALUES(:id, :invoiceId, :accountId, :subscriptionId, :planName, :phaseName,
+ VALUES(:id, :invoiceId, :accountId, :bundleId, :subscriptionId, :planName, :phaseName,
:startDate, :endDate, :amount, :currency, :userName, :createdDate);
>>
batchCreateFromTransaction() ::= <<
INSERT INTO fixed_invoice_items(<fields()>)
- VALUES(:id, :invoiceId, :accountId, :subscriptionId, :planName, :phaseName,
+ VALUES(:id, :invoiceId, :accountId, :bundleId, :subscriptionId, :planName, :phaseName,
:startDate, :endDate, :amount, :currency, :userName, :createdDate);
>>
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.sql.stg
index 6b5f504..7573ef3 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/RecurringInvoiceItemSqlDao.sql.stg
@@ -4,6 +4,7 @@ fields(prefix) ::= <<
<prefix>id,
<prefix>invoice_id,
<prefix>account_id,
+ <prefix>bundle_id,
<prefix>subscription_id,
<prefix>plan_name,
<prefix>phase_name,
@@ -44,13 +45,13 @@ getInvoiceItemsBySubscription() ::= <<
create() ::= <<
INSERT INTO recurring_invoice_items(<fields()>)
- VALUES(:id, :invoiceId, :accountId, :subscriptionId, :planName, :phaseName, :startDate, :endDate,
+ VALUES(:id, :invoiceId, :accountId, :bundleId, :subscriptionId, :planName, :phaseName, :startDate, :endDate,
:amount, :rate, :currency, :reversedItemId, :userName, :createdDate);
>>
batchCreateFromTransaction() ::= <<
INSERT INTO recurring_invoice_items(<fields()>)
- VALUES(:id, :invoiceId, :accountId, :subscriptionId, :planName, :phaseName, :startDate, :endDate,
+ VALUES(:id, :invoiceId, :accountId, :bundleId, :subscriptionId, :planName, :phaseName, :startDate, :endDate,
:amount, :rate, :currency, :reversedItemId, :userName, :createdDate);
>>
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql b/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
index 3adb40e..d04806a 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
+++ b/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
@@ -4,7 +4,8 @@ CREATE TABLE recurring_invoice_items (
id char(36) NOT NULL,
invoice_id char(36) NOT NULL,
account_id char(36) NOT NULL,
- subscription_id char(36) NOT NULL,
+ bundle_id char(36),
+ subscription_id char(36),
plan_name varchar(50) NOT NULL,
phase_name varchar(50) NOT NULL,
start_date datetime NOT NULL,
@@ -25,7 +26,8 @@ CREATE TABLE fixed_invoice_items (
id char(36) NOT NULL,
invoice_id char(36) NOT NULL,
account_id char(36) NOT NULL,
- subscription_id char(36) NOT NULL,
+ bundle_id char(36),
+ subscription_id char(36),
plan_name varchar(50) NOT NULL,
phase_name varchar(50) NOT NULL,
start_date datetime NOT NULL,
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java
index 4701bc8..28077d2 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java
@@ -16,14 +16,13 @@
package com.ning.billing.invoice.api.migration;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
-import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.invoice.MockModule;
import com.ning.billing.invoice.glue.InvoiceModule;
-import com.ning.billing.invoice.notification.DefaultNextBillingDateNotifier;
-import com.ning.billing.invoice.notification.DefaultNextBillingDatePoster;
import com.ning.billing.invoice.notification.NextBillingDateNotifier;
import com.ning.billing.invoice.notification.NextBillingDatePoster;
+import com.ning.billing.junction.api.BillingApi;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
@@ -31,11 +30,14 @@ public class MockModuleNoEntitlement extends MockModule {
@Override
protected void installEntitlementModule() {
- EntitlementBillingApi entitlementApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
- ((ZombieControl)entitlementApi).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
- bind(EntitlementBillingApi.class).toInstance(entitlementApi);
- bind(EntitlementDao.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementDao.class));
-
+ BillingApi entitlementApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
+ ((ZombieControl)entitlementApi).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
+ ((ZombieControl)entitlementApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", BrainDeadProxyFactory.ZOMBIE_VOID);
+ //bind(BillingApi.class).toInstance(entitlementApi);
+ bind(EntitlementUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class));
+ ChargeThruApi cta = BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class);
+ bind(ChargeThruApi.class).toInstance(cta);
+ ((ZombieControl)cta).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
}
@Override
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
index 04af58b..997061d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
@@ -23,11 +23,6 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.clock.Clock;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
@@ -51,8 +46,6 @@ import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
import com.ning.billing.entitlement.api.billing.BillingEvent;
import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.invoice.InvoiceDispatcher;
import com.ning.billing.invoice.TestInvoiceDispatcher;
@@ -62,10 +55,17 @@ import com.ning.billing.invoice.api.InvoicePaymentApi;
import com.ning.billing.invoice.api.InvoiceUserApi;
import com.ning.billing.invoice.dao.InvoiceDao;
import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
import com.ning.billing.util.bus.BusService;
import com.ning.billing.util.bus.DefaultBusService;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.globallocker.GlobalLocker;
@@ -94,6 +94,9 @@ public class TestDefaultInvoiceMigrationApi {
@Inject
private InvoiceMigrationApi migrationApi;
+
+ @Inject
+ private BillingApi billingApi;
@@ -110,7 +113,7 @@ public class TestDefaultInvoiceMigrationApi {
private final Clock clock = new ClockMock();
- @BeforeClass(alwaysRun = true)
+ @BeforeClass(groups={"slow"})
public void setup() throws Exception
{
log.info("Starting set up");
@@ -129,11 +132,13 @@ public class TestDefaultInvoiceMigrationApi {
busService.getBus().start();
+ ((ZombieControl)billingApi).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
migrationInvoiceId = createAndCheckMigrationInvoice();
regularInvoiceId = generateRegularInvoice();
+
}
- @AfterClass(alwaysRun = true)
+ @AfterClass(groups={"slow"})
public void tearDown() {
try {
((DefaultBusService) busService).stopBus();
@@ -171,20 +176,20 @@ public class TestDefaultInvoiceMigrationApi {
((ZombieControl)account).addResult("getId", accountId);
Subscription subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
- ((ZombieControl)subscription).addResult("getId", subscriptionId);
+ ((ZombieControl)subscription).addResult("getId", subscriptionId);
+ ((ZombieControl)subscription).addResult("getBundleId", new UUID(0L,0L));
SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
Plan plan = MockPlan.createBicycleNoTrialEvergreen1USD();
PlanPhase planPhase = MockPlanPhase.create1USDMonthlyEvergreen();
DateTime effectiveDate = new DateTime().minusDays(1);
Currency currency = Currency.USD;
BigDecimal fixedPrice = null;
- events.add(new DefaultBillingEvent(subscription, effectiveDate,plan, planPhase,
+ events.add(new DefaultBillingEvent(account, subscription, effectiveDate,plan, planPhase,
fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.CREATE));
- EntitlementBillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
- ((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccount", events);
-
+ BillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
+ ((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountUserApi, entitlementBillingApi, invoiceDao, locker, busService.getBus(), clock);
CallContext context = new DefaultCallContextFactory(clock).createCallContext("Migration test", CallOrigin.TEST, UserType.TEST);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
index 3a00c1b..09b809c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
@@ -22,11 +22,11 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
-import com.ning.billing.util.callcontext.CallContext;
import org.joda.time.DateTime;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.model.DefaultInvoicePayment;
+import com.ning.billing.util.callcontext.CallContext;
public class MockInvoicePaymentApi implements InvoicePaymentApi
{
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
index 96aeab5..a6980bc 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
@@ -17,33 +17,32 @@
package com.ning.billing.invoice.dao;
import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
import java.io.IOException;
-import com.ning.billing.config.InvoiceConfig;
-import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
-import com.ning.billing.invoice.model.InvoiceGenerator;
-import com.ning.billing.invoice.tests.InvoicingTestBase;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.clock.Clock;
import org.apache.commons.io.IOUtils;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.TransactionCallback;
import org.skife.jdbi.v2.TransactionStatus;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
+import com.ning.billing.config.InvoiceConfig;
import com.ning.billing.invoice.glue.InvoiceModuleWithEmbeddedDb;
+import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
+import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.invoice.tests.InvoicingTestBase;
import com.ning.billing.util.bus.BusService;
import com.ning.billing.util.bus.DefaultBusService;
-import org.testng.annotations.BeforeMethod;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
protected InvoiceDao invoiceDao;
@@ -69,14 +68,15 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
@BeforeClass(alwaysRun = true)
protected void setup() throws IOException {
- try {
module = new InvoiceModuleWithEmbeddedDb();
final String invoiceDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
final String entitlementDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/entitlement/ddl.sql"));
+ final String utilDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
module.startDb();
module.initDb(invoiceDdl);
module.initDb(entitlementDdl);
+ module.initDb(utilDdl);
final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
@@ -94,10 +94,7 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
((DefaultBusService) busService).startBus();
assertTrue(true);
- }
- catch (Throwable t) {
- fail(t.toString());
- }
+
}
@BeforeMethod(alwaysRun = true)
@@ -106,7 +103,7 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
@Override
public Void inTransaction(Handle h, TransactionStatus status)
throws Exception {
- h.execute("truncate table accounts");
+ //h.execute("truncate table accounts");
//h.execute("truncate table entitlement_events");
//h.execute("truncate table subscriptions");
//h.execute("truncate table bundles");
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
index aa8abb5..85d1c16 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
@@ -16,6 +16,21 @@
package com.ning.billing.invoice.dao;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
import com.ning.billing.catalog.DefaultPrice;
import com.ning.billing.catalog.MockInternationalPrice;
import com.ning.billing.catalog.MockPlan;
@@ -29,7 +44,6 @@ import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
import com.ning.billing.entitlement.api.billing.BillingEvent;
import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
@@ -39,23 +53,10 @@ import com.ning.billing.invoice.model.BillingEventSet;
import com.ning.billing.invoice.model.DefaultInvoice;
import com.ning.billing.invoice.model.DefaultInvoicePayment;
import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
import com.ning.billing.util.tag.ControlTagType;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.UUID;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
@Test(groups = {"invoicing", "invoicing-invoiceDao"})
public class InvoiceDaoTests extends InvoiceDaoTestBase {
@@ -84,11 +85,12 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
Invoice invoice = new DefaultInvoice(accountId, clock.getUTCNow(), clock.getUTCNow(), Currency.USD);
UUID invoiceId = invoice.getId();
UUID subscriptionId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
DateTime startDate = new DateTime(2010, 1, 1, 0, 0, 0, 0);
DateTime endDate = new DateTime(2010, 4, 1, 0, 0, 0, 0);
- InvoiceItem invoiceItem = new RecurringInvoiceItem(invoiceId, accountId, subscriptionId,
- "test plan", "test phase", startDate, endDate,
+ InvoiceItem invoiceItem = new RecurringInvoiceItem(invoiceId, accountId, bundleId,subscriptionId, "test plan", "test phase", startDate, endDate,
new BigDecimal("21.00"), new BigDecimal("7.00"), Currency.USD);
+
invoice.addInvoiceItem(invoiceItem);
invoiceDao.create(invoice, context);
@@ -155,6 +157,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
@Test
public void testGetInvoicesBySubscription() {
UUID accountId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
UUID subscriptionId1 = UUID.randomUUID();
BigDecimal rate1 = new BigDecimal("17.0");
@@ -177,19 +180,20 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
DateTime endDate = startDate.plusMonths(1);
- RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoiceId1, accountId, subscriptionId1, "test plan", "test A", startDate, endDate,
+
+ RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId,subscriptionId1, "test plan", "test A", startDate, endDate,
rate1, rate1, Currency.USD);
recurringInvoiceItemDao.create(item1, context);
- RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoiceId1, accountId, subscriptionId2, "test plan", "test B", startDate, endDate,
+ RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId,subscriptionId2, "test plan", "test B", startDate, endDate,
rate2, rate2, Currency.USD);
recurringInvoiceItemDao.create(item2, context);
- RecurringInvoiceItem item3 = new RecurringInvoiceItem(invoiceId1, accountId, subscriptionId3, "test plan", "test C", startDate, endDate,
+ RecurringInvoiceItem item3 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId,subscriptionId3, "test plan", "test C", startDate, endDate,
rate3, rate3, Currency.USD);
recurringInvoiceItemDao.create(item3, context);
- RecurringInvoiceItem item4 = new RecurringInvoiceItem(invoiceId1, accountId, subscriptionId4, "test plan", "test D", startDate, endDate,
+ RecurringInvoiceItem item4 = new RecurringInvoiceItem(invoiceId1, accountId, bundleId,subscriptionId4, "test plan", "test D", startDate, endDate,
rate4, rate4, Currency.USD);
recurringInvoiceItemDao.create(item4, context);
@@ -202,15 +206,16 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
startDate = endDate;
endDate = startDate.plusMonths(1);
- RecurringInvoiceItem item5 = new RecurringInvoiceItem(invoiceId2, accountId, subscriptionId1, "test plan", "test phase A", startDate, endDate,
+
+ RecurringInvoiceItem item5 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId,subscriptionId1, "test plan", "test phase A", startDate, endDate,
rate1, rate1, Currency.USD);
recurringInvoiceItemDao.create(item5, context);
- RecurringInvoiceItem item6 = new RecurringInvoiceItem(invoiceId2, accountId, subscriptionId2, "test plan", "test phase B", startDate, endDate,
+ RecurringInvoiceItem item6 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId,subscriptionId2, "test plan", "test phase B", startDate, endDate,
rate2, rate2, Currency.USD);
recurringInvoiceItemDao.create(item6, context);
- RecurringInvoiceItem item7 = new RecurringInvoiceItem(invoiceId2, accountId, subscriptionId3, "test plan", "test phase C", startDate, endDate,
+ RecurringInvoiceItem item7 = new RecurringInvoiceItem(invoiceId2, accountId, bundleId,subscriptionId3, "test plan", "test phase C", startDate, endDate,
rate3, rate3, Currency.USD);
recurringInvoiceItemDao.create(item7, context);
@@ -260,6 +265,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
@Test
public void testAccountBalance() {
UUID accountId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
invoiceDao.create(invoice1, context);
@@ -270,11 +276,11 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate1 = new BigDecimal("17.0");
BigDecimal rate2 = new BigDecimal("42.0");
- RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, UUID.randomUUID(), "test plan", "test phase A", startDate,
+ RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId,UUID.randomUUID(), "test plan", "test phase A", startDate,
endDate, rate1, rate1, Currency.USD);
recurringInvoiceItemDao.create(item1, context);
- RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, UUID.randomUUID(), "test plan", "test phase B", startDate,
+ RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId,UUID.randomUUID(), "test plan", "test phase B", startDate,
endDate, rate2, rate2, Currency.USD);
recurringInvoiceItemDao.create(item2, context);
@@ -289,6 +295,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
@Test
public void testAccountBalanceWithNoPayments() {
UUID accountId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
invoiceDao.create(invoice1, context);
@@ -299,11 +306,11 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate1 = new BigDecimal("17.0");
BigDecimal rate2 = new BigDecimal("42.0");
- RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, UUID.randomUUID(), "test plan", "test phase A", startDate, endDate,
+ RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate, endDate,
rate1, rate1, Currency.USD);
recurringInvoiceItemDao.create(item1, context);
- RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate,
+ RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate,
rate2, rate2, Currency.USD);
recurringInvoiceItemDao.create(item2, context);
@@ -329,6 +336,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
@Test
public void testGetUnpaidInvoicesByAccountId() {
UUID accountId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate1, Currency.USD);
invoiceDao.create(invoice1, context);
@@ -339,11 +347,12 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate1 = new BigDecimal("17.0");
BigDecimal rate2 = new BigDecimal("42.0");
- RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, UUID.randomUUID(), "test plan", "test phase A", startDate, endDate,
+
+ RecurringInvoiceItem item1 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate, endDate,
rate1, rate1, Currency.USD);
recurringInvoiceItemDao.create(item1, context);
- RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate,
+ RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate,
rate2, rate2, Currency.USD);
recurringInvoiceItemDao.create(item2, context);
@@ -367,7 +376,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BigDecimal rate3 = new BigDecimal("21.0");
- RecurringInvoiceItem item3 = new RecurringInvoiceItem(invoice2.getId(), accountId, UUID.randomUUID(), "test plan", "test phase C", startDate2, endDate2,
+ RecurringInvoiceItem item3 = new RecurringInvoiceItem(invoice2.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase C", startDate2, endDate2,
rate3, rate3, Currency.USD);
recurringInvoiceItemDao.create(item3, context);
@@ -402,7 +411,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
((ZombieControl) subscription).addResult("getId", UUID.randomUUID());
DateTime effectiveDate1 = new DateTime(2011, 2, 1, 0, 0, 0, 0);
- BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan1, phase1, null,
+ BillingEvent event1 = new DefaultBillingEvent(null, subscription, effectiveDate1, plan1, phase1, null,
recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
"testEvent1", 1L, SubscriptionTransitionType.CREATE);
@@ -420,7 +429,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
MockPlan plan2 = new MockPlan(phase2);
DateTime effectiveDate2 = new DateTime(2011, 2, 15, 0, 0, 0, 0);
- BillingEvent event2 = new DefaultBillingEvent(subscription, effectiveDate2, plan2, phase2, null,
+ BillingEvent event2 = new DefaultBillingEvent(null, subscription, effectiveDate2, plan2, phase2, null,
recurringPrice2.getPrice(currency), currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
"testEvent2", 2L, SubscriptionTransitionType.CREATE);
events.add(event2);
@@ -453,7 +462,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
((ZombieControl) subscription).addResult("getId", UUID.randomUUID());
DateTime effectiveDate = buildDateTime(2011, 1, 1);
- BillingEvent event = new DefaultBillingEvent(subscription, effectiveDate, plan, phase, null,
+ BillingEvent event = new DefaultBillingEvent(null, subscription, effectiveDate, plan, phase, null,
recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 15, BillingModeType.IN_ADVANCE,
"testEvent", 1L, SubscriptionTransitionType.CREATE);
BillingEventSet events = new BillingEventSet();
@@ -486,7 +495,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
((ZombieControl) subscription).addResult("getId", UUID.randomUUID());
DateTime effectiveDate1 = buildDateTime(2011, 1, 1);
- BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan, phase1, fixedPrice.getPrice(currency),
+ BillingEvent event1 = new DefaultBillingEvent(null, subscription, effectiveDate1, plan, phase1, fixedPrice.getPrice(currency),
null, currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
"testEvent1", 1L, SubscriptionTransitionType.CREATE);
BillingEventSet events = new BillingEventSet();
@@ -502,7 +511,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
invoiceList.add(invoice1);
DateTime effectiveDate2 = effectiveDate1.plusDays(30);
- BillingEvent event2 = new DefaultBillingEvent(subscription, effectiveDate2, plan, phase2, null,
+ BillingEvent event2 = new DefaultBillingEvent(null, subscription, effectiveDate2, plan, phase2, null,
recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
"testEvent2", 2L, SubscriptionTransitionType.CHANGE);
events.add(event2);
@@ -546,7 +555,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
((ZombieControl) subscription).addResult("getId", UUID.randomUUID());
DateTime effectiveDate1 = buildDateTime(2011, 1, 1);
- BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan, phase1,
+ BillingEvent event1 = new DefaultBillingEvent(null, subscription, effectiveDate1, plan, phase1,
fixedPrice.getPrice(currency), null, currency,
BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
"testEvent1", 1L, SubscriptionTransitionType.CREATE);
@@ -554,7 +563,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
events.add(event1);
DateTime effectiveDate2 = effectiveDate1.plusDays(30);
- BillingEvent event2 = new DefaultBillingEvent(subscription, effectiveDate2, plan, phase2, null,
+ BillingEvent event2 = new DefaultBillingEvent(null, subscription, effectiveDate2, plan, phase2, null,
recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
"testEvent2", 2L, SubscriptionTransitionType.CHANGE);
events.add(event2);
@@ -593,7 +602,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
BillingEventSet events = new BillingEventSet();
List<Invoice> invoices = new ArrayList<Invoice>();
- BillingEvent event1 = new DefaultBillingEvent(subscription, targetDate1, plan, phase1, null,
+ BillingEvent event1 = new DefaultBillingEvent(null, subscription, targetDate1, plan, phase1, null,
TEN, currency,
BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
"testEvent1", 1L, SubscriptionTransitionType.CHANGE);
@@ -605,7 +614,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
invoice1 = invoiceDao.getById(invoice1.getId());
assertNotNull(invoice1.getInvoiceNumber());
- BillingEvent event2 = new DefaultBillingEvent(subscription, targetDate1, plan, phase2, null,
+ BillingEvent event2 = new DefaultBillingEvent(null, subscription, targetDate1, plan, phase2, null,
TWENTY, currency,
BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
"testEvent2", 2L, SubscriptionTransitionType.CHANGE);
@@ -631,7 +640,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
Currency currency = Currency.USD;
// create pseudo-random invoice
- BillingEvent event1 = new DefaultBillingEvent(subscription, targetDate1, plan, phase1, null,
+ BillingEvent event1 = new DefaultBillingEvent(null, subscription, targetDate1, plan, phase1, null,
TEN, currency,
BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
"testEvent1", 1L, SubscriptionTransitionType.CHANGE);
@@ -662,7 +671,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
Currency currency = Currency.USD;
// create pseudo-random invoice
- BillingEvent event1 = new DefaultBillingEvent(subscription, targetDate1, plan, phase1, null,
+ BillingEvent event1 = new DefaultBillingEvent(null, subscription, targetDate1, plan, phase1, null,
TEN, currency,
BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
"testEvent1", 1L, SubscriptionTransitionType.CHANGE);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
index 464ef86..9acde8e 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
@@ -16,19 +16,20 @@
package com.ning.billing.invoice.dao;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.model.DefaultInvoice;
-import com.ning.billing.invoice.model.RecurringInvoiceItem;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.invoice.model.RecurringInvoiceItem;
@Test(groups = {"invoicing", "invoicing-invoiceDao"})
public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
@@ -36,12 +37,13 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
public void testInvoiceItemCreation() {
UUID accountId = UUID.randomUUID();
UUID invoiceId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
UUID subscriptionId = UUID.randomUUID();
DateTime startDate = new DateTime(2011, 10, 1, 0, 0, 0, 0);
DateTime endDate = new DateTime(2011, 11, 1, 0, 0, 0, 0);
BigDecimal rate = new BigDecimal("20.00");
- RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, subscriptionId, "test plan", "test phase", startDate, endDate,
+ RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "test plan", "test phase", startDate, endDate,
rate, rate, Currency.USD);
recurringInvoiceItemDao.create(item, context);
@@ -63,12 +65,14 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
public void testGetInvoiceItemsBySubscriptionId() {
UUID accountId = UUID.randomUUID();
UUID subscriptionId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
BigDecimal rate = new BigDecimal("20.00");
for (int i = 0; i < 3; i++) {
UUID invoiceId = UUID.randomUUID();
- RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, subscriptionId,
+
+ RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId,
"test plan", "test phase", startDate.plusMonths(i), startDate.plusMonths(i + 1),
rate, rate, Currency.USD);
recurringInvoiceItemDao.create(item, context);
@@ -82,13 +86,15 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
public void testGetInvoiceItemsByInvoiceId() {
UUID accountId = UUID.randomUUID();
UUID invoiceId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
BigDecimal rate = new BigDecimal("20.00");
for (int i = 0; i < 5; i++) {
UUID subscriptionId = UUID.randomUUID();
BigDecimal amount = rate.multiply(new BigDecimal(i + 1));
- RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, subscriptionId,
+
+ RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId,
"test plan", "test phase", startDate, startDate.plusMonths(1),
amount, amount, Currency.USD);
recurringInvoiceItemDao.create(item, context);
@@ -101,6 +107,7 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
@Test(groups = "slow")
public void testGetInvoiceItemsByAccountId() {
UUID accountId = UUID.randomUUID();
+ UUID bundleId = UUID.randomUUID();
DateTime targetDate = new DateTime(2011, 5, 23, 0, 0, 0, 0);
DefaultInvoice invoice = new DefaultInvoice(accountId, clock.getUTCNow(), targetDate, Currency.USD);
@@ -111,7 +118,8 @@ public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
BigDecimal rate = new BigDecimal("20.00");
UUID subscriptionId = UUID.randomUUID();
- RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, subscriptionId,
+
+ RecurringInvoiceItem item = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId,
"test plan", "test phase", startDate, startDate.plusMonths(1),
rate, rate, Currency.USD);
recurringInvoiceItemDao.create(item, context);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index c7818d8..c733442 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -23,16 +23,16 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
-import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.bus.Bus;
-import com.ning.billing.util.tag.ControlTagType;
import org.joda.time.DateTime;
import com.google.inject.Inject;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoicePayment;
import com.ning.billing.invoice.api.user.DefaultInvoiceCreationNotification;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.tag.ControlTagType;
public class MockInvoiceDao implements InvoiceDao {
private final Bus eventBus;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
index fd15171..1bf9586 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
@@ -16,37 +16,38 @@
package com.ning.billing.invoice.glue;
+import static org.testng.Assert.assertNotNull;
+
import java.io.IOException;
import java.net.URL;
-import com.ning.billing.invoice.api.test.InvoiceTestApi;
+import org.skife.jdbi.v2.IDBI;
+
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.catalog.glue.CatalogModule;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.glue.EntitlementModule;
import com.ning.billing.invoice.api.test.DefaultInvoiceTestApi;
+import com.ning.billing.invoice.api.test.InvoiceTestApi;
import com.ning.billing.invoice.dao.InvoicePaymentSqlDao;
import com.ning.billing.invoice.dao.RecurringInvoiceItemSqlDao;
import com.ning.billing.invoice.notification.MockNextBillingDateNotifier;
import com.ning.billing.invoice.notification.MockNextBillingDatePoster;
import com.ning.billing.invoice.notification.NextBillingDateNotifier;
import com.ning.billing.invoice.notification.NextBillingDatePoster;
+import com.ning.billing.junction.api.BillingApi;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.util.callcontext.CallContextFactory;
import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.glue.FieldStoreModule;
-import com.ning.billing.util.glue.GlobalLockerModule;
-import com.ning.billing.util.glue.TagStoreModule;
-import org.skife.jdbi.v2.IDBI;
-
-import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.catalog.glue.CatalogModule;
-import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.glue.EntitlementModule;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.DefaultClock;
import com.ning.billing.util.glue.BusModule;
+import com.ning.billing.util.glue.FieldStoreModule;
+import com.ning.billing.util.glue.GlobalLockerModule;
+import com.ning.billing.util.glue.TagStoreModule;
import com.ning.billing.util.notificationq.MockNotificationQueueService;
import com.ning.billing.util.notificationq.NotificationQueueService;
-import static org.testng.Assert.assertNotNull;
-
public class InvoiceModuleWithEmbeddedDb extends InvoiceModule {
private final MysqlTestingHelper helper = new MysqlTestingHelper();
private IDBI dbi;
@@ -100,6 +101,7 @@ public class InvoiceModuleWithEmbeddedDb extends InvoiceModule {
installNotificationQueue();
// install(new AccountModule());
bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
+ bind(BillingApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class));
install(new CatalogModule());
install(new EntitlementModule());
install(new GlobalLockerModule());
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java
index fe4feb4..a6366b8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java
@@ -20,10 +20,7 @@ import com.ning.billing.invoice.dao.InvoiceDao;
import com.ning.billing.invoice.dao.MockInvoiceDao;
import com.ning.billing.util.globallocker.GlobalLocker;
import com.ning.billing.util.globallocker.MockGlobalLocker;
-import com.ning.billing.util.glue.CallContextModule;
import com.ning.billing.util.glue.FieldStoreModule;
-import com.ning.billing.util.glue.TagStoreModule;
-import org.skife.jdbi.v2.Call;
public class InvoiceModuleWithMocks extends InvoiceModule {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/MockModule.java b/invoice/src/test/java/com/ning/billing/invoice/MockModule.java
index 99f12b4..a95864b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/MockModule.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/MockModule.java
@@ -16,10 +16,6 @@
package com.ning.billing.invoice;
-import com.ning.billing.util.callcontext.CallContextFactory;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.glue.FieldStoreModule;
-import com.ning.billing.util.glue.TagStoreModule;
import org.skife.config.ConfigurationObjectFactory;
import org.skife.jdbi.v2.IDBI;
@@ -32,11 +28,16 @@ import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.glue.EntitlementModule;
import com.ning.billing.invoice.glue.InvoiceModule;
import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.glue.MockJunctionModule;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.glue.BusModule;
+import com.ning.billing.util.glue.FieldStoreModule;
import com.ning.billing.util.glue.GlobalLockerModule;
import com.ning.billing.util.glue.NotificationQueueModule;
+import com.ning.billing.util.glue.TagStoreModule;
public class MockModule extends AbstractModule {
@@ -63,18 +64,15 @@ public class MockModule extends AbstractModule {
install(new GlobalLockerModule());
install(new NotificationQueueModule());
-// install(new AccountModule());
- bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
-
installEntitlementModule();
install(new CatalogModule());
install(new BusModule());
installInvoiceModule();
-
+ install(new MockJunctionModule());
}
protected void installEntitlementModule() {
- install(new EntitlementModule());
+ install(new EntitlementModule());
}
protected void installInvoiceModule() {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java b/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java
index 493ba5d..88ff62a 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java
@@ -16,11 +16,11 @@
package com.ning.billing.invoice.notification;
+import java.util.UUID;
+
import org.joda.time.DateTime;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
-import java.util.UUID;
-
public class MockNextBillingDatePoster implements NextBillingDatePoster {
@Override
public void insertNextBillingNotification(Transmogrifier transactionalDao, UUID subscriptionId, DateTime futureNotificationTime) {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
index a15b2c1..d81e218 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
@@ -24,12 +24,11 @@ import java.sql.SQLException;
import java.util.UUID;
import java.util.concurrent.Callable;
+
import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.account.api.MockAccountUserApi;
import com.ning.billing.entitlement.api.SubscriptionApiService;
import com.ning.billing.entitlement.api.SubscriptionFactory;
-import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.invoice.InvoiceDispatcher;
import com.ning.billing.invoice.dao.DefaultInvoiceDao;
import com.ning.billing.invoice.dao.InvoiceDao;
@@ -43,6 +42,7 @@ import com.ning.billing.util.globallocker.GlobalLocker;
import com.ning.billing.util.globallocker.MySqlGlobalLocker;
import com.ning.billing.util.tag.dao.AuditedTagDao;
import com.ning.billing.util.tag.dao.TagDao;
+
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.skife.config.ConfigurationObjectFactory;
@@ -64,9 +64,12 @@ import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.config.CatalogConfig;
import com.ning.billing.config.InvoiceConfig;
import com.ning.billing.dbi.MysqlTestingHelper;
+
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
import com.ning.billing.entitlement.api.repair.RepairEntitlementLifecycleDao;
import com.ning.billing.entitlement.api.repair.RepairSubscriptionApiService;
import com.ning.billing.entitlement.api.repair.RepairSubscriptionFactory;
+
import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
import com.ning.billing.entitlement.api.user.DefaultSubscriptionApiService;
import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory;
@@ -76,12 +79,16 @@ import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.engine.dao.EntitlementSqlDao;
import com.ning.billing.entitlement.engine.dao.RepairEntitlementDao;
import com.ning.billing.entitlement.glue.EntitlementModule;
+
import com.ning.billing.invoice.InvoiceListener;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
import com.ning.billing.lifecycle.KillbillService.ServiceException;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.InMemoryBus;
+
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.notificationq.DefaultNotificationQueueService;
@@ -89,6 +96,7 @@ import com.ning.billing.util.notificationq.DummySqlTest;
import com.ning.billing.util.notificationq.NotificationQueueService;
import com.ning.billing.util.notificationq.dao.NotificationSqlDao;
+
public class TestNextBillingDateNotifier {
private Clock clock;
private DefaultNextBillingDateNotifier notifier;
@@ -129,7 +137,7 @@ public class TestNextBillingDateNotifier {
public void setup() throws ServiceException, IOException, ClassNotFoundException, SQLException {
//TestApiBase.loadSystemPropertiesFromClasspath("/entitlement.properties");
final Injector g = Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
- @Override
+
protected void configure() {
bind(Clock.class).to(ClockMock.class).asEagerSingleton();
bind(CallContextFactory.class).to(DefaultCallContextFactory.class).asEagerSingleton();
@@ -155,13 +163,19 @@ public class TestNextBillingDateNotifier {
bind(InvoiceDao.class).to(DefaultInvoiceDao.class).asEagerSingleton();
bind(NextBillingDatePoster.class).to(DefaultNextBillingDatePoster.class).asEagerSingleton();
bind(AccountUserApi.class).to(MockAccountUserApi.class).asEagerSingleton();
- bind(EntitlementBillingApi.class).to(DefaultEntitlementBillingApi.class).asEagerSingleton();
- bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
+
+
+
bind(SubscriptionApiService.class).annotatedWith(Names.named(EntitlementModule.REPAIR_NAMED)).to(RepairSubscriptionApiService.class).asEagerSingleton();
bind(SubscriptionApiService.class).to(DefaultSubscriptionApiService.class).asEagerSingleton();
bind(SubscriptionFactory.class).annotatedWith(Names.named(EntitlementModule.REPAIR_NAMED)).to(RepairSubscriptionFactory.class).asEagerSingleton();
bind(SubscriptionFactory.class).to(DefaultSubscriptionFactory.class).asEagerSingleton();
- }
+
+ bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
+ bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
+ bind(ChargeThruApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class));
+
+ }
});
clock = g.getInstance(Clock.class);
@@ -231,8 +245,9 @@ public class TestNextBillingDateNotifier {
Assert.assertEquals(listener.getLatestSubscriptionId(), subscriptionId);
}
- @AfterClass(alwaysRun = true)
+ @AfterClass(groups="slow")
public void tearDown() {
+ notifier.stop();
helper.stopMysql();
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
index c13e386..0ae049e 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -23,11 +23,6 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.clock.Clock;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
@@ -51,19 +46,23 @@ import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
import com.ning.billing.entitlement.api.billing.BillingEvent;
import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
-import com.ning.billing.invoice.api.InvoiceUserApi;
import com.ning.billing.invoice.dao.InvoiceDao;
import com.ning.billing.invoice.model.InvoiceGenerator;
import com.ning.billing.invoice.notification.NextBillingDateNotifier;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
import com.ning.billing.util.bus.BusService;
import com.ning.billing.util.bus.DefaultBusService;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.globallocker.GlobalLocker;
@Test(groups = "slow")
@@ -72,9 +71,6 @@ public class TestInvoiceDispatcher {
private Logger log = LoggerFactory.getLogger(TestInvoiceDispatcher.class);
@Inject
- private InvoiceUserApi invoiceUserApi;
-
- @Inject
private InvoiceGenerator generator;
@Inject
@@ -89,8 +85,11 @@ public class TestInvoiceDispatcher {
@Inject
private NextBillingDateNotifier notifier;
- @Inject
- private BusService busService;
+ @Inject
+ private BusService busService;
+
+ @Inject
+ private BillingApi billingApi;
@Inject
private Clock clock;
@@ -115,6 +114,7 @@ public class TestInvoiceDispatcher {
context = new DefaultCallContextFactory(clock).createCallContext("Miracle Max", CallOrigin.TEST, UserType.TEST);
busService.getBus().start();
+ ((ZombieControl)billingApi).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
}
@AfterClass(alwaysRun = true)
@@ -141,19 +141,20 @@ public class TestInvoiceDispatcher {
((ZombieControl)account).addResult("getId", accountId);
Subscription subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
- ((ZombieControl)subscription).addResult("getId", subscriptionId);
+ ((ZombieControl)subscription).addResult("getId", subscriptionId);
+ ((ZombieControl)subscription).addResult("getBundleId", new UUID(0L,0L));
SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
Plan plan = MockPlan.createBicycleNoTrialEvergreen1USD();
PlanPhase planPhase = MockPlanPhase.create1USDMonthlyEvergreen();
DateTime effectiveDate = new DateTime().minusDays(1);
Currency currency = Currency.USD;
BigDecimal fixedPrice = null;
- events.add(new DefaultBillingEvent(subscription, effectiveDate,plan, planPhase,
+ events.add(new DefaultBillingEvent(account, subscription, effectiveDate,plan, planPhase,
fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.CREATE));
- EntitlementBillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
- ((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccount", events);
+ BillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
+ ((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
DateTime target = new DateTime();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
index 5792abd..1eaa8af 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
@@ -16,6 +16,20 @@
package com.ning.billing.invoice.tests;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
import com.ning.billing.catalog.DefaultPrice;
import com.ning.billing.catalog.MockInternationalPrice;
import com.ning.billing.catalog.MockPlan;
@@ -30,10 +44,9 @@ import com.ning.billing.config.InvoiceConfig;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
import com.ning.billing.entitlement.api.billing.BillingEvent;
import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
+import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionData;
-import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
import com.ning.billing.invoice.model.BillingEventSet;
@@ -41,23 +54,11 @@ import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
import com.ning.billing.invoice.model.InvoiceGenerator;
import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
-
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.DefaultClock;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-import javax.annotation.Nullable;
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
@Test(groups = {"fast", "invoicing", "invoiceGenerator"})
public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
@@ -481,6 +482,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
UUID accountId = UUID.randomUUID();
Subscription subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
((ZombieControl) subscription).addResult("getId", UUID.randomUUID());
+ ((ZombieControl) subscription).addResult("getBundleId", UUID.randomUUID());
Plan plan = new MockPlan("plan 1");
MockInternationalPrice zeroPrice = new MockInternationalPrice(new DefaultPrice(ZERO, Currency.USD));
@@ -493,13 +495,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BillingEventSet events = new BillingEventSet();
- BillingEvent event1 = new DefaultBillingEvent(subscription, new DateTime("2012-01-1T00:00:00.000-08:00"),
+ BillingEvent event1 = new DefaultBillingEvent(null, subscription, new DateTime("2012-01-1T00:00:00.000-08:00"),
plan, phase1,
ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
BillingModeType.IN_ADVANCE, "Test Event 1", 1L,
SubscriptionTransitionType.CREATE);
- BillingEvent event2 = new DefaultBillingEvent(subscription, changeDate,
+ BillingEvent event2 = new DefaultBillingEvent(null, subscription, changeDate,
plan, phase2,
ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
BillingModeType.IN_ADVANCE, "Test Event 2", 2L,
@@ -631,7 +633,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
assertNotNull(invoice2);
assertEquals(invoice2.getNumberOfItems(), 1);
assertEquals(invoice2.getInvoiceItems().get(0).getStartDate().compareTo(trialPhaseEndDate), 0);
- assertEquals(invoice2.getTotalAmount().compareTo(new BigDecimal("3.2097")), 0);
+ assertEquals(invoice2.getTotalAmount().compareTo(new BigDecimal("3.21")), 0);
invoiceList.add(invoice2);
DateTime targetDate = trialPhaseEndDate.toMutableDateTime().dayOfMonth().set(BILL_CYCLE_DAY).toDateTime();
@@ -691,7 +693,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(subscriptionId));
Currency currency = Currency.USD;
- return new DefaultBillingEvent(sub, startDate, plan, planPhase,
+ return new DefaultBillingEvent(null, sub, startDate, plan, planPhase,
planPhase.getFixedPrice() == null ? null : planPhase.getFixedPrice().getPrice(currency),
planPhase.getRecurringPrice() == null ? null : planPhase.getRecurringPrice().getPrice(currency),
currency, planPhase.getBillingPeriod(),
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java
index fd37599..c08c8b8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.annual;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class DoubleProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java
index 8d0eb06..81d5347 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java
@@ -16,11 +16,12 @@
package com.ning.billing.invoice.tests.inAdvance.annual;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
+import java.math.BigDecimal;
+
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class GenericProRationTests extends GenericProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java
index a009fba..68611f7 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.annual;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class LeadingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java
index f882005..88922e2 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.annual;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class ProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java
index e0216b5..d1c2013 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.annual;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class TrailingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java
index 60892e6..70f1f8f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java
@@ -16,11 +16,12 @@
package com.ning.billing.invoice.tests.inAdvance;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
@Test(groups = {"fast", "invoicing", "proRation"})
public abstract class GenericProRationTestBase extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java
index 240b8aa..8c9b61d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.monthly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class DoubleProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java
index 8b40db8..b749ab8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java
@@ -16,11 +16,12 @@
package com.ning.billing.invoice.tests.inAdvance.monthly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
+import java.math.BigDecimal;
+
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class GenericProRationTests extends GenericProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java
index 998e566..f723738 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.monthly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class LeadingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java
index c3748d1..8d564c8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.monthly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class ProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java
index 6a5e5ef..581e8af 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.monthly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class TrailingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
index 18bd096..b8f3848 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
@@ -16,10 +16,11 @@
package com.ning.billing.invoice.tests.inAdvance;
+import org.testng.annotations.Test;
+
import com.ning.billing.invoice.model.BillingMode;
import com.ning.billing.invoice.model.InAdvanceBillingMode;
import com.ning.billing.invoice.tests.ProRationTestBase;
-import org.testng.annotations.Test;
@Test(groups = {"fast", "invoicing", "proRation"})
public abstract class ProRationInAdvanceTestBase extends ProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java
index 184f5d5..e6c3cf3 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.quarterly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class DoubleProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java
index c4237a6..3351807 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java
@@ -16,11 +16,12 @@
package com.ning.billing.invoice.tests.inAdvance.quarterly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
+import java.math.BigDecimal;
+
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class GenericProRationTests extends GenericProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java
index 04ec683..18bb8af 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.quarterly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class LeadingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java
index e13db0d..2988dfe 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.quarterly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class ProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java
index 8f63010..270518d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java
@@ -16,13 +16,14 @@
package com.ning.billing.invoice.tests.inAdvance.quarterly;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
import org.testng.annotations.Test;
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
@Test(groups = {"fast", "invoicing", "proRation"})
public class TrailingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
index bd8a38d..21dd092 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
@@ -16,17 +16,18 @@
package com.ning.billing.invoice.tests.inAdvance;
+import static org.testng.Assert.assertEquals;
+
+import java.math.BigDecimal;
+
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.invoice.model.BillingMode;
import com.ning.billing.invoice.model.InAdvanceBillingMode;
import com.ning.billing.invoice.model.InvalidDateSequenceException;
import com.ning.billing.invoice.tests.ProRationTestBase;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-import java.math.BigDecimal;
-
-import static org.testng.Assert.assertEquals;
@Test(groups = {"fast", "invoicing", "proRation"})
public class ValidationProRationTests extends ProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java
index 4b47237..50f1b23 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java
@@ -16,10 +16,11 @@
package com.ning.billing.invoice.tests;
-import com.ning.billing.invoice.model.InvoicingConfiguration;
+import java.math.BigDecimal;
+
import org.joda.time.DateTime;
-import java.math.BigDecimal;
+import com.ning.billing.invoice.model.InvoicingConfiguration;
public abstract class InvoicingTestBase {
protected static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
index 122b13b..1cd4e2f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
@@ -16,17 +16,18 @@
package com.ning.billing.invoice.tests;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.BillingMode;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.model.RecurringInvoiceItemData;
-import org.joda.time.DateTime;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
import java.math.BigDecimal;
import java.util.List;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.BillingMode;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.model.RecurringInvoiceItemData;
public abstract class ProRationTestBase extends InvoicingTestBase {
protected abstract BillingMode getBillingMode();
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
index 20b222c..0619020 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
@@ -23,7 +23,6 @@ import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonView;
import org.joda.time.DateTime;
-import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.util.clock.DefaultClock;
@@ -245,7 +244,7 @@ public class SubscriptionJson {
this.productName = data.getCurrentPlan().getProduct().getName();
this.productCategory = data.getCurrentPlan().getProduct().getCategory().toString();
this.billingPeriod = data.getCurrentPlan().getBillingPeriod().toString();
- this.priceList = data.getCurrentPriceList();
+ this.priceList = data.getCurrentPriceList().getName();
this.events = events;
this.deletedEvents = deletedEvents;
this.newEvents = newEvents;
junction/pom.xml 131(+131 -0)
diff --git a/junction/pom.xml b/junction/pom.xml
new file mode 100644
index 0000000..b5dfd03
--- /dev/null
+++ b/junction/pom.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ 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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill</artifactId>
+ <version>0.1.11-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>killbill-junction</artifactId>
+ <name>killbill-junction</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.skife.config</groupId>
+ <artifactId>config-magic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jdbi</groupId>
+ <artifactId>jdbi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-entitlement</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-entitlement</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj-db-files</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!-- Strangely this is needed in order to run the tests in local db mode -->
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <groups>fast,slow, stress</groups>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/junction/src/main/java/com/ning/billing/junction/api/billing/BlockingEventCalculator.java b/junction/src/main/java/com/ning/billing/junction/api/billing/BlockingEventCalculator.java
new file mode 100644
index 0000000..a1111b4
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/api/billing/BlockingEventCalculator.java
@@ -0,0 +1,290 @@
+/*
+ * 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.junction.api.billing;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+
+public class BlockingEventCalculator {
+ private final BlockingApi overdueApi;
+ private final CatalogService catalogService;
+
+ protected static class DisabledDuration {
+ private final DateTime start;
+ private final DateTime end;
+
+ public DisabledDuration(DateTime start,DateTime end) {
+ this.start = start;
+ this.end = end;
+ }
+ public DateTime getStart() {
+ return start;
+ }
+ public DateTime getEnd() {
+ return end;
+ }
+
+ }
+
+ protected static class MergeEvent extends BlockingState {
+
+ public MergeEvent(DateTime timestamp) {
+ super(null,null,null,null,false,false,false,timestamp);
+ }
+
+ }
+
+ @Inject
+ public BlockingEventCalculator(BlockingApi overdueApi, CatalogService catalogService) {
+ this.overdueApi = overdueApi;
+ this.catalogService = catalogService;
+ }
+
+ public void insertOverdueEvents(SortedSet<BillingEvent> billingEvents) {
+ if(billingEvents.size() <= 0) { return; }
+
+ Account account = billingEvents.first().getAccount();
+
+ Hashtable<UUID,Set<Subscription>> bundleMap = createBundleSubscriptionMap(billingEvents);
+
+ SortedSet<BillingEvent> billingEventsToAdd = new TreeSet<BillingEvent>();
+ SortedSet<BillingEvent> billingEventsToRemove = new TreeSet<BillingEvent>();
+
+ for(UUID bundleId : bundleMap.keySet()) {
+ SortedSet<BlockingState> overdueBundleEvents = overdueApi.getBlockingHistory(bundleId, Blockable.Type.SUBSCRIPTION_BUNDLE);
+ List<DisabledDuration> bundleDisablePairs = createDisablePairs(overdueBundleEvents);
+
+ for (Subscription subscription: bundleMap.get(bundleId)) {
+ billingEventsToAdd.addAll(createNewEvents( bundleDisablePairs, billingEvents, account, subscription));
+ billingEventsToRemove.addAll(eventsToRemove(bundleDisablePairs, billingEvents, subscription));
+ }
+ }
+
+ for(BillingEvent eventToAdd: billingEventsToAdd ) {
+ billingEvents.add(eventToAdd);
+ }
+
+ for(BillingEvent eventToRemove : billingEventsToRemove) {
+ billingEvents.remove(eventToRemove);
+ }
+
+ }
+
+ protected SortedSet<BillingEvent> eventsToRemove(List<DisabledDuration> disabledDuration,
+ SortedSet<BillingEvent> billingEvents, Subscription subscription) {
+ SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();
+
+ SortedSet<BillingEvent> filteredBillingEvents = filter(billingEvents, subscription);
+ for(DisabledDuration duration : disabledDuration) {
+ for(BillingEvent event : filteredBillingEvents) {
+ if(duration.getEnd() == null || event.getEffectiveDate().isBefore(duration.getEnd())) {
+ if( event.getEffectiveDate().isAfter(duration.getStart()) ) { //between the pair
+ result.add(event);
+ }
+ } else { //after the last event of the pair no need to keep checking
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ protected SortedSet<BillingEvent> createNewEvents( List<DisabledDuration> disabledDuration, SortedSet<BillingEvent> billingEvents, Account account, Subscription subscription) {
+ SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();
+ for(DisabledDuration duration : disabledDuration) {
+ BillingEvent precedingInitialEvent = precedingBillingEventForSubscription(duration.getStart(), billingEvents, subscription);
+ BillingEvent precedingFinalEvent = precedingBillingEventForSubscription(duration.getEnd(), billingEvents, subscription);
+
+ if(precedingInitialEvent != null) { // there is a preceding billing event
+ result.add(createNewDisableEvent(duration.getStart(), precedingInitialEvent));
+ if(duration.getEnd() != null) { // no second event in the pair means they are still disabled (no re-enable)
+ result.add(createNewReenableEvent(duration.getEnd(), precedingFinalEvent));
+ }
+
+ } else if(precedingFinalEvent != null) { // can happen - e.g. phase event
+ //
+ // TODO: check with Jeff that this is going to do something sensible
+ //
+ result.add(createNewReenableEvent(duration.getEnd(), precedingFinalEvent));
+
+ }
+
+ // N.B. if there's no precedingInitial and no precedingFinal then there's nothing to do
+ }
+ return result;
+ }
+
+ protected BillingEvent precedingBillingEventForSubscription(DateTime datetime, SortedSet<BillingEvent> billingEvents, Subscription subscription) {
+ if(datetime == null) { //second of a pair can be null if there's no re-enabling
+ return null;
+ }
+
+ SortedSet<BillingEvent> filteredBillingEvents = filter(billingEvents, subscription);
+ BillingEvent result = filteredBillingEvents.first();
+
+ if(datetime.isBefore(result.getEffectiveDate())) {
+ //This case can happen, for example, if we have an add on and the bundle goes into disabled before the add on is created
+ return null;
+ }
+
+ for(BillingEvent event : filteredBillingEvents) {
+ if(event.getEffectiveDate().isAfter(datetime)) { // found it its the previous event
+ return result;
+ } else { // still looking
+ result = event;
+ }
+ }
+ return result;
+ }
+
+ protected SortedSet<BillingEvent> filter(SortedSet<BillingEvent> billingEvents, Subscription subscription) {
+ SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();
+ for(BillingEvent event : billingEvents) {
+ if(event.getSubscription() == subscription) {
+ result.add(event);
+ }
+ }
+ return result;
+ }
+
+ protected BillingEvent createNewDisableEvent(DateTime odEventTime, BillingEvent previousEvent) {
+ final Account account = previousEvent.getAccount();
+ final int billCycleDay = previousEvent.getBillCycleDay();
+ final Subscription subscription = previousEvent.getSubscription();
+ final DateTime effectiveDate = odEventTime;
+ final PlanPhase planPhase = previousEvent.getPlanPhase();
+ final Plan plan = previousEvent.getPlan();
+ final BigDecimal fixedPrice = BigDecimal.ZERO;
+ final BigDecimal recurringPrice = BigDecimal.ZERO;
+ final Currency currency = previousEvent.getCurrency();
+ final String description = "";
+ final BillingModeType billingModeType = previousEvent.getBillingMode();
+ final BillingPeriod billingPeriod = previousEvent.getBillingPeriod();
+ final SubscriptionTransitionType type = SubscriptionTransitionType.CANCEL;
+ final Long totalOrdering = 0L; //TODO
+
+ return null;
+
+ //TODO MDW
+// new DefaultBillingEvent(account, subscription, effectiveDate, plan, planPhase,
+// fixedPrice, recurringPrice, currency,
+// billingPeriod, billCycleDay, billingModeType,
+// description, totalOrdering, type);
+ }
+
+ protected BillingEvent createNewReenableEvent(DateTime odEventTime, BillingEvent previousEvent) {
+ final Account account = previousEvent.getAccount();
+ final int billCycleDay = previousEvent.getBillCycleDay();
+ final Subscription subscription = previousEvent.getSubscription();
+ final DateTime effectiveDate = odEventTime;
+ final PlanPhase planPhase = previousEvent.getPlanPhase();
+ final Plan plan = previousEvent.getPlan();
+ final BigDecimal fixedPrice = previousEvent.getFixedPrice();
+ final BigDecimal recurringPrice = previousEvent.getRecurringPrice();
+ final Currency currency = previousEvent.getCurrency();
+ final String description = "";
+ final BillingModeType billingModeType = previousEvent.getBillingMode();
+ final BillingPeriod billingPeriod = previousEvent.getBillingPeriod();
+ final SubscriptionTransitionType type = SubscriptionTransitionType.RE_CREATE;
+ final Long totalOrdering = 0L; //TODO
+
+ return null;
+
+ //TODO MDW
+// return new DefaultBillingEvent(account, subscription, effectiveDate, plan, planPhase,
+// fixedPrice, recurringPrice, currency,
+// billingPeriod, billCycleDay, billingModeType,
+// description, totalOrdering, type);
+ }
+
+ protected Hashtable<UUID,Set<Subscription>> createBundleSubscriptionMap(SortedSet<BillingEvent> billingEvents) {
+ Hashtable<UUID,Set<Subscription>> result = new Hashtable<UUID,Set<Subscription>>();
+ for(BillingEvent event : billingEvents) {
+ UUID bundleId = event.getSubscription().getBundleId();
+ Set<Subscription> subs = result.get(bundleId);
+ if(subs == null) {
+ subs = new TreeSet<Subscription>();
+ result.put(bundleId,subs);
+ }
+ subs.add(event.getSubscription());
+ }
+ return result;
+ }
+
+
+
+ protected List<DisabledDuration> createDisablePairs(SortedSet<BlockingState> overdueBundleEvents) {
+ List<DisabledDuration> result = new ArrayList<BlockingEventCalculator.DisabledDuration>();
+ BlockingState first = null;
+
+ for(BlockingState e : overdueBundleEvents) {
+ if(isDisableEvent(e) && first == null) { // found a transition to disabled
+ first = e;
+ } else if(first != null && !isDisableEvent(e)) { // found a transition from disabled
+ result.add(new DisabledDuration(first.getTimestamp(), e.getTimestamp()));
+ first = null;
+ }
+ }
+
+ if(first != null) { // found a transition to disabled with no terminating event
+ result.add(new DisabledDuration(first.getTimestamp(), null));
+ }
+
+ return result;
+ }
+
+ protected boolean isDisableEvent(BlockingState e) {
+ //TODO Martin refactoring
+ return false;
+// OverdueState<?> state = null;
+// try {
+// if (e.getType() == Overdueable.Type.SUBSCRIPTION_BUNDLE) {
+// state = catalogService.getCurrentCatalog().currentBundleOverdueStateSet().findState(e.getStateName());
+// }
+// } catch (CatalogApiException exp) {
+// throw new EntitlementError(exp);
+// }
+// if (state == null) {
+// throw new EntitlementError("Unable to find an overdue state with name: " + e.getStateName());
+// }
+// return state.disableEntitlementAndChangesBlocked();
+ }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
new file mode 100644
index 0000000..02b3b41
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
@@ -0,0 +1,67 @@
+/*
+ * 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.junction.api.blocking;
+
+import java.util.SortedSet;
+import java.util.UUID;
+
+import com.google.inject.Inject;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.dao.BlockingStateDao;
+import com.ning.billing.util.clock.Clock;
+
+public class DefaultBlockingApi implements BlockingApi {
+ private BlockingStateDao dao;
+ private Clock clock;
+
+ @Inject
+ public DefaultBlockingApi(BlockingStateDao dao, Clock clock) {
+ this.dao = dao;
+ this.clock = clock;
+ }
+
+ @Override
+ public BlockingState getBlockingStateFor(Blockable overdueable) {
+ return dao.getBlockingStateFor(overdueable);
+ }
+
+ @Override
+ public BlockingState getBlockingStateFor(UUID overdueableId, Type type) {
+ return dao.getBlockingStateFor(overdueableId, type);
+ }
+
+ @Override
+ public SortedSet<BlockingState> getBlockingHistory(Blockable overdueable) {
+ return dao.getBlockingHistoryFor(overdueable);
+ }
+
+ @Override
+ public SortedSet<BlockingState> getBlockingHistory(UUID overdueableId,
+ Type type) {
+ return dao.getBlockingHistoryForIdAndType(overdueableId, type);
+ }
+
+ @Override
+ public <T extends Blockable> void setBlockingState(BlockingState state) {
+ dao.setBlockingState(state, clock);
+
+ }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java b/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
new file mode 100644
index 0000000..a6ab7da
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.junction.block;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.BlockingApiException;
+
+public interface BlockingChecker {
+
+ public void checkBlockedChange(Subscription subscription) throws BlockingApiException;
+
+ public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException;
+
+ public void checkBlockedChange(Account account) throws BlockingApiException;
+
+ public void checkBlockedEntitlement(Subscription subscription) throws BlockingApiException;
+
+ public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException;
+
+ public void checkBlockedEntitlement(Account account) throws BlockingApiException;
+
+ public void checkBlockedBilling(Subscription subscription) throws BlockingApiException;
+
+ public void checkBlockedBilling(SubscriptionBundle bundleId) throws BlockingApiException;
+
+ public void checkBlockedBilling(Account account) throws BlockingApiException;
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java b/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
new file mode 100644
index 0000000..1f65391
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
@@ -0,0 +1,195 @@
+/*
+ * 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.junction.block;
+
+import java.util.UUID;
+
+import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.dao.BlockingStateDao;
+
+public class DefaultBlockingChecker implements BlockingChecker {
+
+ private static class BlockingAggregator {
+ private boolean blockChange = false;
+ private boolean blockEntitlement= false;
+ private boolean blockBilling = false;
+
+ public void or(BlockingState state) {
+ if (state == null) { return; }
+ blockChange = blockChange || state.isBlockChange();
+ blockEntitlement = blockEntitlement || state.isBlockEntitlement();
+ blockBilling = blockBilling || state.isBlockBilling();
+ }
+
+ public void or(BlockingAggregator state) {
+ if (state == null) { return; }
+ blockChange = blockChange || state.isBlockChange();
+ blockEntitlement = blockEntitlement || state.isBlockEntitlement();
+ blockBilling = blockBilling || state.isBlockBilling();
+ }
+
+ public boolean isBlockChange() {
+ return blockChange;
+ }
+ public boolean isBlockEntitlement() {
+ return blockEntitlement;
+ }
+ public boolean isBlockBilling() {
+ return blockBilling;
+ }
+
+ }
+
+ private static final Object TYPE_SUBSCRIPTION = "Subscription";
+ private static final Object TYPE_BUNDLE = "Bundle";
+ private static final Object TYPE_ACCOUNT = "Account";
+
+ private static final Object ACTION_CHANGE = "Change";
+ private static final Object ACTION_ENTITLEMENT = "Entitlement";
+ private static final Object ACTION_BILLING = "Billing";
+
+ private final EntitlementUserApi entitlementApi;
+ private final BlockingStateDao dao;
+
+ @Inject
+ public DefaultBlockingChecker(EntitlementUserApi entitlementApi, BlockingStateDao dao) {
+ this.entitlementApi = entitlementApi;
+ this.dao = dao;
+ }
+
+ public BlockingAggregator getBlockedStateSubscriptionId(UUID subscriptionId) {
+ Subscription subscription = entitlementApi.getSubscriptionFromId(subscriptionId);
+ return getBlockedStateSubscription(subscription);
+ }
+
+ public BlockingAggregator getBlockedStateSubscription(Subscription subscription) {
+ BlockingAggregator result = new BlockingAggregator();
+ if(subscription != null) {
+ BlockingState subscriptionState = dao.getBlockingStateFor(subscription);
+ if(subscriptionState != null) {
+ result.or(subscriptionState);
+ }
+ if(subscription.getBundleId() != null) {
+ SubscriptionBundle bundle = entitlementApi.getBundleFromId(subscription.getBundleId());
+ result.or(getBlockedStateBundleId(subscription.getBundleId()));
+ }
+ }
+ return result;
+ }
+
+ public BlockingAggregator getBlockedStateBundleId(UUID bundleId) {
+ SubscriptionBundle bundle = entitlementApi.getBundleFromId(bundleId);
+ return getBlockedStateBundle(bundle);
+ }
+
+ public BlockingAggregator getBlockedStateBundle(SubscriptionBundle bundle) {
+ BlockingAggregator result = getBlockedStateAccount(bundle.getAccountId());
+ BlockingState bundleState = dao.getBlockingStateFor(bundle);
+ if(bundleState != null) {
+ result.or(bundleState);
+ }
+ return result;
+ }
+
+ public BlockingAggregator getBlockedStateAccount(UUID accountId) {
+ BlockingAggregator result = new BlockingAggregator();
+ if(accountId != null) {
+ BlockingState accountState = dao.getBlockingStateFor(accountId, Blockable.Type.ACCOUNT);
+ result.or(accountState);
+ }
+ return result;
+ }
+
+ public BlockingAggregator getBlockedStateAccount(Account account) {
+ if(account != null) {
+ return getBlockedStateAccount(account.getId());
+ }
+ return new BlockingAggregator();
+ }
+ @Override
+ public void checkBlockedChange(Subscription subscription) throws BlockingApiException {
+ if(getBlockedStateSubscription(subscription).isBlockChange()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_SUBSCRIPTION, subscription.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException {
+ if(getBlockedStateBundle(bundle).isBlockChange()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_BUNDLE, bundle.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedChange(Account account) throws BlockingApiException {
+ if(getBlockedStateAccount(account).isBlockChange()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_ACCOUNT, account.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedEntitlement(Subscription subscription) throws BlockingApiException {
+ if(getBlockedStateSubscription(subscription).isBlockEntitlement()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_SUBSCRIPTION, subscription.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException {
+ if(getBlockedStateBundle(bundle).isBlockEntitlement()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_BUNDLE, bundle.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedEntitlement(Account account) throws BlockingApiException {
+ if(getBlockedStateAccount(account).isBlockEntitlement()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_ACCOUNT, account.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedBilling(Subscription subscription) throws BlockingApiException {
+ if(getBlockedStateSubscription(subscription).isBlockBilling()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_SUBSCRIPTION, subscription.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedBilling(SubscriptionBundle bundle) throws BlockingApiException {
+ if(getBlockedStateBundle(bundle).isBlockBilling()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_BUNDLE, bundle.getId().toString());
+ }
+ }
+
+ @Override
+ public void checkBlockedBilling(Account account) throws BlockingApiException {
+ if(getBlockedStateAccount(account).isBlockBilling()) {
+ throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_ACCOUNT, account.getId().toString());
+ }
+ }
+
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateDao.java b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateDao.java
new file mode 100644
index 0000000..b5b03ae
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateDao.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.junction.dao;
+
+import java.util.SortedSet;
+import java.util.UUID;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.util.clock.Clock;
+
+public interface BlockingStateDao {
+
+ //Read
+ public BlockingState getBlockingStateFor(Blockable blockable);
+
+ public BlockingState getBlockingStateFor(UUID blockableId, Type type);
+
+ public SortedSet<BlockingState> getBlockingHistoryFor(Blockable blockable);
+
+ public SortedSet<BlockingState> getBlockingHistoryForIdAndType(UUID blockableId, Type type);
+
+ //Write
+ <T extends Blockable> void setBlockingState(BlockingState state, Clock clock);
+
+}
\ No newline at end of file
diff --git a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
new file mode 100644
index 0000000..895724c
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
@@ -0,0 +1,168 @@
+/*
+ * 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.junction.dao;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
+import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
+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.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.dao.BinderBase;
+import com.ning.billing.util.dao.MapperBase;
+
+@ExternalizedSqlViaStringTemplate3()
+public interface BlockingStateSqlDao extends BlockingStateDao, CloseMe, Transmogrifier {
+
+ @Override
+ @SqlUpdate
+ public abstract <T extends Blockable> void setBlockingState(
+ @Bind(binder = BlockingStateBinder.class) BlockingState state,
+ @Bind(binder = CurrentTimeBinder.class) Clock clock) ;
+
+
+ @Override
+ @SqlQuery
+ @Mapper(BlockingHistorySqlMapper.class)
+ public abstract BlockingState getBlockingStateFor(@Bind(binder = BlockableBinder.class)Blockable overdueable) ;
+
+ @Override
+ @SqlQuery
+ @Mapper(BlockingHistorySqlMapper.class)
+ public abstract BlockingState getBlockingStateFor(@Bind(binder = UUIDBinder.class) UUID overdueableId, @Bind(binder = BlockableTypeBinder.class) Type type);
+
+ @Override
+ @SqlQuery
+ @Mapper(BlockingHistorySqlMapper.class)
+ public abstract SortedSet<BlockingState> getBlockingHistoryFor(@Bind(binder = BlockableBinder.class)Blockable blockable) ;
+
+ @Override
+ @SqlQuery
+ @Mapper(BlockingHistorySqlMapper.class)
+ public abstract SortedSet<BlockingState> getBlockingHistoryForIdAndType(@Bind(binder = UUIDBinder.class) UUID blockableId, @Bind(binder = BlockableTypeBinder.class) Type type);
+
+
+ public class BlockingHistorySqlMapper extends MapperBase implements ResultSetMapper<BlockingState> {
+
+ @Override
+ public BlockingState map(int index, ResultSet r, StatementContext ctx)
+ throws SQLException {
+
+ DateTime timestamp;
+ UUID blockableId;
+ String stateName;
+ String service;
+ boolean blockChange;
+ boolean blockEntitlement;
+ boolean blockBilling;
+ Type type;
+ try {
+ timestamp = new DateTime(r.getDate("created_date"));
+ blockableId = UUID.fromString(r.getString("id"));
+ stateName = r.getString("state") == null ? BlockingApi.CLEAR_STATE_NAME : r.getString("state");
+ type = Type.get(r.getString("type"));
+ service = r.getString("service");
+ blockChange = r.getBoolean("block_change");
+ blockEntitlement = r.getBoolean("block_entitlement");
+ blockBilling = r.getBoolean("block_billing");
+ } catch (BlockingApiException e) {
+ throw new SQLException(e);
+ }
+ return new BlockingState(blockableId, stateName, type, service, blockChange, blockEntitlement, blockBilling, timestamp);
+ }
+ }
+
+ public static class BlockingStateSqlMapper extends MapperBase implements ResultSetMapper<String> {
+
+ @Override
+ public String map(int index, ResultSet r, StatementContext ctx)
+ throws SQLException {
+ return r.getString("state") == null ? BlockingApi.CLEAR_STATE_NAME : r.getString("state");
+ }
+ }
+
+ public static class BlockingStateBinder extends BinderBase implements Binder<Bind, BlockingState> {
+ @Override
+ public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, BlockingState state) {
+ stmt.bind("id", state.getBlockedId().toString());
+ stmt.bind("state", state.getStateName().toString());
+ stmt.bind("type", state.getType().toString());
+ stmt.bind("service", state.getService().toString());
+ stmt.bind("block_change", state.isBlockChange());
+ stmt.bind("block_entitlement", state.isBlockEntitlement());
+ stmt.bind("block_billing", state.isBlockBilling());
+ }
+ }
+
+ public static class UUIDBinder extends BinderBase implements Binder<Bind, UUID> {
+ @Override
+ public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, UUID id) {
+ stmt.bind("id", id.toString());
+ }
+ }
+
+ public static class BlockableBinder extends BinderBase implements Binder<Bind, Blockable> {
+ @Override
+ public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, Blockable overdueable) {
+ stmt.bind("id", overdueable.getId().toString());
+ }
+ }
+
+ public static class OverdueStateBinder<T extends Blockable> extends BinderBase implements Binder<Bind, OverdueState<T>> {
+ @Override
+ public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, OverdueState<T> overdueState) {
+ stmt.bind("state", overdueState.getName());
+ }
+ }
+
+ public class BlockableTypeBinder extends BinderBase implements Binder<Bind, Blockable.Type>{
+
+ @Override
+ public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, Type type) {
+ stmt.bind("type", type.name());
+ }
+
+ }
+
+ public static class CurrentTimeBinder extends BinderBase implements Binder<Bind, Clock> {
+ @Override
+ public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, Clock clock) {
+ stmt.bind("created_date", clock.getUTCNow().toDate());
+ }
+
+ }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java b/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
new file mode 100644
index 0000000..0d42e5f
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.junction.glue;
+
+import org.skife.jdbi.v2.IDBI;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.blocking.DefaultBlockingApi;
+import com.ning.billing.junction.dao.BlockingStateDao;
+import com.ning.billing.junction.dao.BlockingStateSqlDao;
+import com.ning.billing.junction.plumbing.api.BlockingAccountUserApi;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
+
+public class JunctionModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ installBlockingApi();
+ installAccountUserApi();
+ installBlockingStateDao();
+ installBillingApi();
+ }
+
+ protected void installBillingApi() {
+ bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
+ }
+
+ protected void installBlockingStateDao() {
+ bind(BlockingStateDao.class).toProvider(BlockingDaoProvider.class);
+ }
+
+ protected void installAccountUserApi() {
+ bind(AccountUserApi.class).to(BlockingAccountUserApi.class).asEagerSingleton();
+ }
+
+ protected void installBlockingApi() {
+ bind(BlockingApi.class).to(DefaultBlockingApi.class).asEagerSingleton();
+ }
+
+ public static class BlockingDaoProvider implements Provider<BlockingStateDao>{
+ private IDBI dbi;
+
+
+ @Inject
+ public BlockingDaoProvider(IDBI dbi){
+ this.dbi = dbi;
+ }
+ @Override
+ public BlockingStateDao get() {
+ return dbi.onDemand(BlockingStateSqlDao.class);
+ }
+ }
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
new file mode 100644
index 0000000..2fc3110
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
@@ -0,0 +1,89 @@
+/*
+ * 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.junction.plumbing.api;
+
+import java.util.List;
+import java.util.UUID;
+
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.MigrationAccountData;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.glue.RealImplementation;
+import com.ning.billing.util.tag.Tag;
+
+public class BlockingAccountUserApi implements AccountUserApi {
+
+ private AccountUserApi userApi;
+
+ @Inject
+ public BlockingAccountUserApi(@RealImplementation AccountUserApi userApi) {
+ this.userApi = userApi;
+ }
+
+ @Override
+ public Account createAccount(AccountData data, List<CustomField> fields, List<Tag> tags, CallContext context)
+ throws AccountApiException {
+ return userApi.createAccount(data, fields, tags, context);
+ }
+
+ @Override
+ public Account migrateAccount(MigrationAccountData data, List<CustomField> fields, List<Tag> tags,
+ CallContext context) throws AccountApiException {
+ return userApi.migrateAccount(data, fields, tags, context);
+ }
+
+ @Override
+ public void updateAccount(Account account, CallContext context) throws AccountApiException {
+ userApi.updateAccount(account, context);
+ }
+
+ @Override
+ public void updateAccount(String key, AccountData accountData, CallContext context) throws AccountApiException {
+ userApi.updateAccount(key, accountData, context);
+ }
+
+ @Override
+ public void updateAccount(UUID accountId, AccountData accountData, CallContext context) throws AccountApiException {
+ userApi.updateAccount(accountId, accountData, context);
+ }
+
+ @Override
+ public Account getAccountByKey(String key) {
+ return userApi.getAccountByKey(key);
+ }
+
+ @Override
+ public Account getAccountById(UUID accountId) {
+ return userApi.getAccountById(accountId);
+ }
+
+ @Override
+ public List<Account> getAccounts() {
+ return userApi.getAccounts();
+ }
+
+ @Override
+ public UUID getIdFromKey(String externalKey) throws AccountApiException {
+ return userApi.getIdFromKey(externalKey);
+ }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
new file mode 100644
index 0000000..f07fa04
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
@@ -0,0 +1,98 @@
+/*
+ * 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.junction.plumbing.billing;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.catalog.api.BillingAlignment;
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
+
+public class BillCycleDayCalculator {
+ private static final Logger log = LoggerFactory.getLogger(BillCycleDayCalculator.class);
+
+ private final CatalogService catalogService;
+ private final EntitlementUserApi entitlementApi;
+
+ @Inject
+ public BillCycleDayCalculator(final CatalogService catalogService, final EntitlementUserApi entitlementApi) {
+ super();
+ this.catalogService = catalogService;
+ this.entitlementApi = entitlementApi;
+ }
+
+ protected int calculateBcd(SubscriptionBundle bundle, Subscription subscription, final SubscriptionEventTransition transition, final Account account) throws CatalogApiException, AccountApiException {
+ Catalog catalog = catalogService.getFullCatalog();
+ Plan plan = (transition.getTransitionType() != SubscriptionTransitionType.CANCEL) ?
+ transition.getNextPlan() : transition.getPreviousPlan();
+ Product product = plan.getProduct();
+ PlanPhase phase = (transition.getTransitionType() != SubscriptionTransitionType.CANCEL) ?
+ transition.getNextPhase() : transition.getPreviousPhase();
+
+ BillingAlignment alignment = catalog.billingAlignment(
+ new PlanPhaseSpecifier(product.getName(),
+ product.getCategory(),
+ phase.getBillingPeriod(),
+ transition.getNextPriceList().getName(),
+ phase.getPhaseType()),
+ transition.getRequestedTransitionTime());
+ int result = -1;
+
+ switch (alignment) {
+ case ACCOUNT :
+ result = account.getBillCycleDay();
+ if(result == 0) {
+ result = calculateBcdFromSubscription(subscription, plan, account);
+ }
+ break;
+ case BUNDLE :
+ Subscription baseSub = entitlementApi.getBaseSubscription(bundle.getId());
+ result = calculateBcdFromSubscription(baseSub, plan, account);
+ break;
+ case SUBSCRIPTION :
+ result = calculateBcdFromSubscription(subscription, plan, account);
+ break;
+ }
+ if(result == -1) {
+ throw new CatalogApiException(ErrorCode.CAT_INVALID_BILLING_ALIGNMENT, alignment.toString());
+ }
+ return result;
+
+ }
+
+ private int calculateBcdFromSubscription(Subscription subscription, Plan plan, Account account) throws AccountApiException {
+ DateTime date = plan.dateOfFirstRecurringNonZeroCharge(subscription.getStartDate());
+ return date.toDateTime(account.getTimeZone()).getDayOfMonth();
+ }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
new file mode 100644
index 0000000..3a6c110
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
@@ -0,0 +1,118 @@
+/*
+ * 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.junction.plumbing.billing;
+
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.MutableAccountData;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.UserType;
+
+public class DefaultBillingApi implements BillingApi {
+ private static final String API_USER_NAME = "Billing Api";
+ private static final Logger log = LoggerFactory.getLogger(DefaultBillingApi.class);
+ private final ChargeThruApi chargeThruApi;
+ private final CallContextFactory factory;
+ private final AccountUserApi accountApi;
+ private final BillCycleDayCalculator bcdCalculator;
+ private final EntitlementUserApi entitlementUserApi;
+
+ @Inject
+ public DefaultBillingApi(ChargeThruApi chargeThruApi, CallContextFactory factory, AccountUserApi accountApi,
+ BillCycleDayCalculator bcdCalculator, EntitlementUserApi entitlementUserApi) {
+ this.chargeThruApi = chargeThruApi;
+ this.accountApi = accountApi;
+ this.bcdCalculator = bcdCalculator;
+ this.factory = factory;
+ this.entitlementUserApi = entitlementUserApi;
+ }
+
+ @Override
+ public SortedSet<BillingEvent> getBillingEventsForAccountAndUpdateAccountBCD(final UUID accountId) {
+ Account account = accountApi.getAccountById(accountId);
+ CallContext context = factory.createCallContext(API_USER_NAME, CallOrigin.INTERNAL, UserType.SYSTEM);
+
+ List<SubscriptionBundle> bundles = entitlementUserApi.getBundlesForAccount(accountId);
+ SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();
+ for (final SubscriptionBundle bundle: bundles) {
+ List<Subscription> subscriptions = entitlementUserApi.getSubscriptionsForBundle(bundle.getId());
+
+ for (final Subscription subscription: subscriptions) {
+ for (final SubscriptionEventTransition transition : subscription.getBillingTransitions()) {
+ try {
+ int bcd = bcdCalculator.calculateBcd(bundle, subscription, transition, account);
+
+ if(account.getBillCycleDay() == 0) {
+ MutableAccountData modifiedData = account.toMutableAccountData();
+ modifiedData.setBillCycleDay(bcd);
+ accountApi.updateAccount(account.getExternalKey(), modifiedData, context);
+ }
+
+ BillingEvent event = new DefaultBillingEvent(account, transition, subscription, bcd, account.getCurrency());
+ result.add(event);
+ } catch (CatalogApiException e) {
+ log.error("Failing to identify catalog components while creating BillingEvent from transition: " +
+ transition.getId().toString(), e);
+ } catch (Exception e) {
+ log.warn("Failed while getting BillingEvent", e);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ @Override
+ public UUID getAccountIdFromSubscriptionId(UUID subscriptionId) {
+ return chargeThruApi.getAccountIdFromSubscriptionId(subscriptionId);
+ }
+
+ @Override
+ public void setChargedThroughDate(UUID subscriptionId, DateTime ctd, CallContext context) {
+ chargeThruApi.setChargedThroughDate(subscriptionId, ctd, context);
+ }
+
+ @Override
+ public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId,
+ DateTime ctd, CallContext context) {
+ chargeThruApi.setChargedThroughDateFromTransaction(transactionalDao, subscriptionId, ctd, context);
+ }
+
+}
diff --git a/junction/src/main/resources/com/ning/billing/junction/dao/BlockingStateSqlDao.sql.stg b/junction/src/main/resources/com/ning/billing/junction/dao/BlockingStateSqlDao.sql.stg
new file mode 100644
index 0000000..98125a2
--- /dev/null
+++ b/junction/src/main/resources/com/ning/billing/junction/dao/BlockingStateSqlDao.sql.stg
@@ -0,0 +1,92 @@
+group BlockingStateSqlDao;
+
+getBlockingStateFor() ::= <<
+ select
+ id
+ , state
+ , type
+ , service
+ , block_change
+ , block_entitlement
+ , block_billing
+ , created_date
+ from blocking_states
+ where id = :id
+ order by created_date desc
+ limit 1
+ ;
+>>
+
+getBlockingStateForIdAndType() ::= <<
+ select
+ id
+ , state
+ , type
+ , service
+ , block_change
+ , block_entitlement
+ , block_billing
+ , created_date
+ from blocking_states
+ where id = :id
+ and type = :type
+ order by created_date desc
+ limit 1
+ ;
+>>
+
+
+getBlockingHistoryFor() ::= <<
+ select
+ id
+ , state
+ , type
+ , service
+ , block_change
+ , block_entitlement
+ , block_billing
+ , created_date
+ from blocking_states
+ where id = :id
+ order by created_date asc
+ ;
+>>
+
+getBlockingHistoryForIdAndType() ::= <<
+ select
+ id
+ , state
+ , type
+ , service
+ , block_change
+ , block_entitlement
+ , block_billing
+ , created_date
+ from blocking_states
+ where id = :id
+ and type = :type
+ order by created_date asc
+ ;
+>>
+
+setBlockingState() ::= <<
+ insert into blocking_states (
+ id
+ , state
+ , type
+ , service
+ , block_change
+ , block_entitlement
+ , block_billing
+ , created_date
+ ) values (
+ :id
+ , :state
+ , :type
+ , :service
+ , :block_change
+ , :block_entitlement
+ , :block_billing
+ , :created_date
+ );
+>>
\ No newline at end of file
diff --git a/junction/src/main/resources/com/ning/billing/junction/ddl.sql b/junction/src/main/resources/com/ning/billing/junction/ddl.sql
new file mode 100644
index 0000000..656ce70
--- /dev/null
+++ b/junction/src/main/resources/com/ning/billing/junction/ddl.sql
@@ -0,0 +1,13 @@
+
+DROP TABLE IF EXISTS blocking_states;
+CREATE TABLE blocking_states (
+ id char(36) NOT NULL,
+ type varchar(20) NOT NULL,
+ state varchar(50) NOT NULL,
+ service varchar(20) NOT NULL,
+ block_change bool NOT NULL,
+ block_entitlement bool NOT NULL,
+ block_billing bool NOT NULL,
+ created_date datetime NOT NULL
+) ENGINE=innodb;
+CREATE INDEX blocking_states_by_id ON blocking_states (id);
\ No newline at end of file
diff --git a/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java b/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
new file mode 100644
index 0000000..faaa848
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
@@ -0,0 +1,146 @@
+/*
+ * 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.junction.api.blocking;
+
+import java.io.IOException;
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.MockModule;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.dao.TestBlockingDao;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.clock.ClockMock;
+
+@Guice(modules = { MockModule.class })
+public class TestBlockingApi {
+ private Logger log = LoggerFactory.getLogger(TestBlockingDao.class);
+
+ @Inject
+ private MysqlTestingHelper helper;
+
+ @Inject
+ private BlockingApi api;
+
+ @Inject
+ private ClockMock clock;
+
+ @BeforeClass(groups={"slow"})
+ public void setup() throws IOException {
+ log.info("Starting set up TestBlockingApi");
+
+ final String utilDdl = IOUtils.toString(TestBlockingDao.class.getResourceAsStream("/com/ning/billing/junction/ddl.sql"));
+
+ helper.startMysql();
+ helper.initDb(utilDdl);
+
+ }
+
+ @BeforeMethod(groups={"slow"})
+ public void clean() {
+ helper.cleanupTable("blocking_states");
+ clock.resetDeltaFromReality();
+ }
+
+ @AfterClass(groups = "slow")
+ public void stopMysql()
+ {
+ helper.stopMysql();
+ }
+
+ @Test(groups={"slow"}, enabled=true)
+ public void testApi() {
+
+ UUID uuid = UUID.randomUUID();
+ String overdueStateName = "WayPassedItMan";
+ String service = "TEST";
+
+ boolean blockChange = true;
+ boolean blockEntitlement = false;
+ boolean blockBilling = false;
+
+ BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ api.setBlockingState(state1);
+ clock.setDeltaFromReality(1000 * 3600 * 24);
+
+ String overdueStateName2 = "NoReallyThisCantGoOn";
+ BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ api.setBlockingState(state2);
+
+ SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+ ((ZombieControl)bundle).addResult("getId", uuid);
+
+ Assert.assertEquals(api.getBlockingStateFor(bundle).getStateName(), overdueStateName2);
+ Assert.assertEquals(api.getBlockingStateFor(bundle.getId(), Blockable.Type.SUBSCRIPTION_BUNDLE).getStateName(), overdueStateName2);
+
+ }
+
+ @Test(groups={"slow"}, enabled=true)
+ public void testApiHistory() throws Exception {
+ UUID uuid = UUID.randomUUID();
+ String overdueStateName = "WayPassedItMan";
+ String service = "TEST";
+
+ boolean blockChange = true;
+ boolean blockEntitlement = false;
+ boolean blockBilling = false;
+
+ BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ api.setBlockingState(state1);
+
+ clock.setDeltaFromReality(1000 * 3600 * 24);
+
+ String overdueStateName2 = "NoReallyThisCantGoOn";
+ BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ api.setBlockingState(state2);
+
+ SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+ ((ZombieControl)bundle).addResult("getId", uuid);
+
+
+ SortedSet<BlockingState> history1 = api.getBlockingHistory(bundle);
+ SortedSet<BlockingState> history2 = api.getBlockingHistory(bundle.getId(), Blockable.Type.get(bundle));
+
+ Assert.assertEquals(history1.size(), 2);
+ Assert.assertEquals(history1.first().getStateName(), overdueStateName);
+ Assert.assertEquals(history1.last().getStateName(), overdueStateName2);
+
+ Assert.assertEquals(history2.size(), 2);
+ Assert.assertEquals(history2.first().getStateName(), overdueStateName);
+ Assert.assertEquals(history2.last().getStateName(), overdueStateName2);
+
+ }
+
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java b/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java
new file mode 100644
index 0000000..f188a6f
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java
@@ -0,0 +1,82 @@
+/*
+ * 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.junction.blocking;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.block.BlockingChecker;
+
+public class MockBlockingChecker implements BlockingChecker {
+
+ @Override
+ public void checkBlockedChange(Subscription subscription) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedChange(Account account) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedEntitlement(Subscription subscription) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedEntitlement(Account account) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedBilling(Subscription subscription) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedBilling(SubscriptionBundle bundleId) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+ @Override
+ public void checkBlockedBilling(Account account) throws BlockingApiException {
+ // Intentionally blank
+
+ }
+
+
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
new file mode 100644
index 0000000..b973bba
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
@@ -0,0 +1,378 @@
+/*
+ * 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.junction.blocking;
+
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.block.BlockingChecker;
+import com.ning.billing.junction.block.DefaultBlockingChecker;
+import com.ning.billing.junction.dao.BlockingStateDao;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.clock.Clock;
+
+
+public class TestBlockingChecker {
+
+ private BlockingState bundleState;
+ private BlockingState subscriptionState;
+ private BlockingState accountState;
+
+ private BlockingStateDao dao = new BlockingStateDao() {
+
+ @Override
+ public BlockingState getBlockingStateFor(Blockable blockable) {
+ if(blockable instanceof Account) {
+ return accountState;
+ } else if(blockable instanceof Subscription) {
+ return subscriptionState;
+ } else {
+ return bundleState;
+ }
+ }
+
+ @Override
+ public BlockingState getBlockingStateFor(UUID blockableId, Type type) {
+ if(type == Blockable.Type.ACCOUNT) {
+ return accountState;
+ } else if(type == Blockable.Type.SUBSCRIPTION) {
+ return subscriptionState;
+ } else {
+ return bundleState;
+ }
+ }
+
+ @Override
+ public SortedSet<BlockingState> getBlockingHistoryFor(Blockable overdueable) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public SortedSet<BlockingState> getBlockingHistoryForIdAndType(UUID overdueableId, Type type) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public <T extends Blockable> void setBlockingState(BlockingState state, Clock clock) {
+ throw new NotImplementedException();
+ }
+
+ };
+ private BlockingChecker checker;
+ private Subscription subscription;
+ private Account account;
+ private SubscriptionBundle bundle;
+
+ @BeforeClass(groups={"fast"})
+ public void setup() {
+ subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
+ ((ZombieControl) subscription).addResult("getId", new UUID(0L,0L));
+
+ bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+ ((ZombieControl) bundle).addResult("getAccountId", new UUID(0L,0L));
+ ((ZombieControl) bundle).addResult("getId", new UUID(0L,0L));
+ ((ZombieControl) bundle).addResult("getKey", "key");
+ ((ZombieControl) subscription).addResult("getBundleId", new UUID(0L,0L));
+
+ account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl) account).addResult("getId", new UUID(0L,0L));
+
+ Injector i = Guice.createInjector(new AbstractModule() {
+
+ @Override
+ protected void configure() {
+ bind(BlockingChecker.class).to(DefaultBlockingChecker.class).asEagerSingleton();
+
+ bind(BlockingStateDao.class).toInstance(dao);
+
+ EntitlementUserApi entitlementUserApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+ //((ZombieControl) entitlementDao).addResult("", result)
+ bind(EntitlementUserApi.class).toInstance(entitlementUserApi);
+ ((ZombieControl) entitlementUserApi).addResult("getBundleFromId",bundle);
+
+ }
+
+ });
+ checker = i.getInstance(BlockingChecker.class);
+ }
+
+
+ private void setStateBundle(boolean bC, boolean bE, boolean bB) {
+ bundleState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+ }
+
+ private void setStateAccount(boolean bC, boolean bE, boolean bB) {
+ accountState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+ }
+
+ private void setStateSubscription(boolean bC, boolean bE, boolean bB) {
+ subscriptionState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+ }
+
+ @Test(groups={"fast"}, enabled = true)
+ public void testSubscriptionChecker() throws Exception {
+ setStateAccount(false, false, false);
+ setStateBundle(false, false, false);
+ setStateSubscription(false, false, false);
+ checker.checkBlockedChange(subscription);
+ checker.checkBlockedEntitlement(subscription);
+ checker.checkBlockedBilling(subscription);
+
+ //BLOCKED SUBSCRIPTION
+ setStateSubscription(true, false, false);
+ checker.checkBlockedEntitlement(subscription);
+ checker.checkBlockedBilling(subscription);
+ try {
+ checker.checkBlockedChange(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateSubscription(false, true, false);
+ checker.checkBlockedChange(subscription);
+ checker.checkBlockedBilling(subscription);
+ try {
+ checker.checkBlockedEntitlement(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateSubscription(false, false, true);
+ checker.checkBlockedChange(subscription);
+ checker.checkBlockedEntitlement(subscription);
+ try {
+ checker.checkBlockedBilling(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ //BLOCKED BUNDLE
+ setStateSubscription(false, false, false);
+ setStateBundle(true, false, false);
+ checker.checkBlockedEntitlement(subscription);
+ checker.checkBlockedBilling(subscription);
+ try {
+ checker.checkBlockedChange(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateBundle(false, true, false);
+ checker.checkBlockedChange(subscription);
+ checker.checkBlockedBilling(subscription);
+ try {
+ checker.checkBlockedEntitlement(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateBundle(false, false, true);
+ checker.checkBlockedChange(subscription);
+ checker.checkBlockedEntitlement(subscription);
+ try {
+ checker.checkBlockedBilling(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+
+ //BLOCKED Account
+ setStateSubscription(false, false, false);
+ setStateBundle(false, false, false);
+ setStateAccount(true, false, false);
+ checker.checkBlockedEntitlement(subscription);
+ checker.checkBlockedBilling(subscription);
+ try {
+ checker.checkBlockedChange(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateAccount(false, true, false);
+ checker.checkBlockedChange(subscription);
+ checker.checkBlockedBilling(subscription);
+ try {
+ checker.checkBlockedEntitlement(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateAccount(false, false, true);
+ checker.checkBlockedChange(subscription);
+ checker.checkBlockedEntitlement(subscription);
+ try {
+ checker.checkBlockedBilling(subscription);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+
+ }
+
+ @Test(groups={"fast"}, enabled = true)
+ public void testBundleChecker() throws Exception {
+ setStateAccount(false, false, false);
+ setStateBundle(false, false, false);
+ setStateSubscription(false, false, false);
+ checker.checkBlockedChange(bundle);
+ checker.checkBlockedEntitlement(bundle);
+ checker.checkBlockedBilling(bundle);
+
+ //BLOCKED BUNDLE
+ setStateSubscription(false, false, false);
+ setStateBundle(true, false, false);
+ checker.checkBlockedEntitlement(bundle);
+ checker.checkBlockedBilling(bundle);
+ try {
+ checker.checkBlockedChange(bundle);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateBundle(false, true, false);
+ checker.checkBlockedChange(bundle);
+ checker.checkBlockedBilling(bundle);
+ try {
+ checker.checkBlockedEntitlement(bundle);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateBundle(false, false, true);
+ checker.checkBlockedChange(bundle);
+ checker.checkBlockedEntitlement(bundle);
+ try {
+ checker.checkBlockedBilling(bundle);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+
+ //BLOCKED Account
+ setStateSubscription(false, false, false);
+ setStateBundle(false, false, false);
+ setStateAccount(true, false, false);
+ checker.checkBlockedEntitlement(bundle);
+ checker.checkBlockedBilling(bundle);
+ try {
+ checker.checkBlockedChange(bundle);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateAccount(false, true, false);
+ checker.checkBlockedChange(bundle);
+ checker.checkBlockedBilling(bundle);
+ try {
+ checker.checkBlockedEntitlement(bundle);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateAccount(false, false, true);
+ checker.checkBlockedChange(bundle);
+ checker.checkBlockedEntitlement(bundle);
+ try {
+ checker.checkBlockedBilling(bundle);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+
+ }
+
+ @Test(groups={"fast"}, enabled = true)
+ public void testAccountChecker() throws Exception {
+ setStateAccount(false, false, false);
+ setStateBundle(false, false, false);
+ setStateSubscription(false, false, false);
+ checker.checkBlockedChange(account);
+ checker.checkBlockedEntitlement(account);
+ checker.checkBlockedBilling(account);
+
+ //BLOCKED Account
+ setStateSubscription(false, false, false);
+ setStateBundle(false, false, false);
+ setStateAccount(true, false, false);
+ checker.checkBlockedEntitlement(account);
+ checker.checkBlockedBilling(account);
+ try {
+ checker.checkBlockedChange(account);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateAccount(false, true, false);
+ checker.checkBlockedChange(account);
+ checker.checkBlockedBilling(account);
+ try {
+ checker.checkBlockedEntitlement(account);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+ setStateAccount(false, false, true);
+ checker.checkBlockedChange(account);
+ checker.checkBlockedEntitlement(account);
+ try {
+ checker.checkBlockedBilling(account);
+ Assert.fail("The call should have been blocked!");
+ } catch (BlockingApiException e) {
+ //Expected behavior
+ }
+
+
+
+ }
+
+
+
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java b/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
new file mode 100644
index 0000000..084f30f
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
@@ -0,0 +1,133 @@
+/*
+ * 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.junction.dao;
+
+import java.io.IOException;
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import com.google.inject.Inject;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.MockModule;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.clock.ClockMock;
+
+@Guice(modules = {MockModule.class})
+public class TestBlockingDao {
+ private Logger log = LoggerFactory.getLogger(TestBlockingDao.class);
+
+ @Inject
+ private MysqlTestingHelper helper;
+
+ @Inject
+ private BlockingStateDao dao;
+
+ @BeforeClass(groups={"slow"})
+ public void setup() throws IOException {
+ log.info("Starting set up TestBlockingDao");
+
+ final String utilDdl = IOUtils.toString(TestBlockingDao.class.getResourceAsStream("/com/ning/billing/junction/ddl.sql"));
+
+ helper.startMysql();
+ helper.initDb(utilDdl);
+
+ }
+
+ @AfterClass(groups = "slow")
+ public void stopMysql()
+ {
+ helper.stopMysql();
+ }
+
+
+ @Test(groups={"slow"}, enabled=true)
+ public void testDao() {
+ ClockMock clock = new ClockMock();
+ UUID uuid = UUID.randomUUID();
+ String overdueStateName = "WayPassedItMan";
+ String service = "TEST";
+
+ boolean blockChange = true;
+ boolean blockEntitlement = false;
+ boolean blockBilling = false;
+
+ BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ dao.setBlockingState(state1, clock);
+ clock.setDeltaFromReality(1000 * 3600 * 24);
+
+ String overdueStateName2 = "NoReallyThisCantGoOn";
+ BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ dao.setBlockingState(state2, clock);
+
+ SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+ ((ZombieControl)bundle).addResult("getId", uuid);
+
+ Assert.assertEquals(dao.getBlockingStateFor(bundle).getStateName(), state2.getStateName());
+ Assert.assertEquals(dao.getBlockingStateFor(bundle.getId(), Blockable.Type.SUBSCRIPTION_BUNDLE).getStateName(), overdueStateName2);
+
+ }
+
+ @Test(groups={"slow"}, enabled=true)
+ public void testDaoHistory() throws Exception {
+ ClockMock clock = new ClockMock();
+ UUID uuid = UUID.randomUUID();
+ String overdueStateName = "WayPassedItMan";
+ String service = "TEST";
+
+ boolean blockChange = true;
+ boolean blockEntitlement = false;
+ boolean blockBilling = false;
+
+ BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ dao.setBlockingState(state1, clock);
+ clock.setDeltaFromReality(1000 * 3600 * 24);
+
+ String overdueStateName2 = "NoReallyThisCantGoOn";
+ BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+ dao.setBlockingState(state2, clock);
+
+ SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+ ((ZombieControl)bundle).addResult("getId", uuid);
+
+
+ SortedSet<BlockingState> history1 = dao.getBlockingHistoryFor(bundle);
+ SortedSet<BlockingState> history2 = dao.getBlockingHistoryForIdAndType(bundle.getId(), Blockable.Type.get(bundle));
+
+ Assert.assertEquals(history1.size(), 2);
+ Assert.assertEquals(history1.first().getStateName(), overdueStateName);
+ Assert.assertEquals(history1.last().getStateName(), overdueStateName2);
+
+ Assert.assertEquals(history2.size(), 2);
+ Assert.assertEquals(history2.first().getStateName(), overdueStateName);
+ Assert.assertEquals(history2.last().getStateName(), overdueStateName2);
+
+ }
+
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/MockBlockingModule.java b/junction/src/test/java/com/ning/billing/junction/MockBlockingModule.java
new file mode 100644
index 0000000..75814aa
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/MockBlockingModule.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.junction;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.dao.BlockingStateDao;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+
+public class MockBlockingModule extends AbstractModule {
+ public static final String CLEAR_STATE="Clear";
+
+ @Override
+ protected void configure() {
+ BlockingApi BlockingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BlockingApi.class);
+ ((ZombieControl) BlockingApi).addResult("getOverdueStateNameFor", MockBlockingModule.CLEAR_STATE);
+ bind(BlockingStateDao.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(BlockingStateDao.class));
+ bind(BlockingApi.class).toInstance(BlockingApi);
+ }
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/MockModule.java b/junction/src/test/java/com/ning/billing/junction/MockModule.java
new file mode 100644
index 0000000..1b95389
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/MockModule.java
@@ -0,0 +1,70 @@
+/*
+ * 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.junction;
+
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.IDBI;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.catalog.glue.CatalogModule;
+import com.ning.billing.dbi.DBIProvider;
+import com.ning.billing.dbi.DbiConfig;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.glue.JunctionModule;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+
+
+public class MockModule extends JunctionModule {
+ public static final String PLUGIN_NAME = "Booboo";
+
+ @Override
+ protected void configure() {
+ super.configure();
+ bind(Clock.class).to(ClockMock.class).asEagerSingleton();
+ bind(ClockMock.class).asEagerSingleton();
+ bind(CallContextFactory.class).to(DefaultCallContextFactory.class).asEagerSingleton();
+
+ final MysqlTestingHelper helper = new MysqlTestingHelper();
+ bind(MysqlTestingHelper.class).toInstance(helper);
+ if (helper.isUsingLocalInstance()) {
+ bind(IDBI.class).toProvider(DBIProvider.class).asEagerSingleton();
+ final DbiConfig config = new ConfigurationObjectFactory(System.getProperties()).build(DbiConfig.class);
+ bind(DbiConfig.class).toInstance(config);
+ } else {
+ final IDBI dbi = helper.getDBI();
+ bind(IDBI.class).toInstance(dbi);
+ }
+
+ install(new CatalogModule());
+ }
+
+ @Override
+ protected void installBillingApi() {
+ // no billinggApi
+ }
+
+ @Override
+ protected void installAccountUserApi() {
+
+ }
+
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestOverdueEventCalculator.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestOverdueEventCalculator.java
new file mode 100644
index 0000000..6134d04
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestOverdueEventCalculator.java
@@ -0,0 +1,722 @@
+/*
+ * 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.junction.plumbing.billing;
+
+
+public class TestOverdueEventCalculator {
+
+//MDW TODO
+// private static final String DISABLED_BUNDLE = "disabled-bundle";
+// private static final String CLEAR_BUNDLE = "clear-bundle";
+//
+//
+// private static final DefaultOverdueState<SubscriptionBundle> CLEAR_BUNDLE_STATE = new MockOverdueState<SubscriptionBundle>(CLEAR_BUNDLE, false, false);
+// private static final DefaultOverdueState<SubscriptionBundle> DISABLED_BUNDLE_STATE = new MockOverdueState<SubscriptionBundle>(DISABLED_BUNDLE, false, true);
+//
+// private OverdueAccessApi overdueAccessApi;
+// private Account account;
+// private Subscription subscription1;
+// private Subscription subscription2;
+// private Subscription subscription3;
+// private Subscription subscription4;
+// private UUID bundleId1 = UUID.randomUUID();
+// private UUID bundleId2 = UUID.randomUUID();
+// private Clock clock;
+// private OverdueEventCalculator odc;
+//
+// @BeforeClass
+// public void setUpBeforeClass() throws Exception {
+//
+// @SuppressWarnings("unchecked")
+// final OverdueStatesBundle bundleODS = new MockOverdueStatesBundle(new DefaultOverdueState[] {
+// CLEAR_BUNDLE_STATE, DISABLED_BUNDLE_STATE });
+//
+// clock = new ClockMock();
+//
+// Injector i = Guice.createInjector(new AbstractModule() {
+//
+// @Override
+// protected void configure() {
+// overdueAccessApi = BrainDeadProxyFactory.createBrainDeadProxyFor(OverdueAccessApi.class);
+// account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+// subscription1 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+// subscription2 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+// subscription3 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+// subscription4 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+// ((ZombieControl) subscription1).addResult("getBundleId", bundleId1);
+// ((ZombieControl) subscription2).addResult("getBundleId", bundleId1);
+// ((ZombieControl) subscription3).addResult("getBundleId", bundleId1);
+// ((ZombieControl) subscription4).addResult("getBundleId", bundleId2);
+// ((ZombieControl) subscription1).addResult("compareTo", 1);
+// ((ZombieControl) subscription2).addResult("compareTo", 1);
+// ((ZombieControl) subscription3).addResult("compareTo", 1);
+// ((ZombieControl) subscription4).addResult("compareTo", 1);
+// ((ZombieControl) subscription1).addResult("getId", UUID.randomUUID());
+// ((ZombieControl) subscription2).addResult("getId", UUID.randomUUID());
+// ((ZombieControl) subscription3).addResult("getId", UUID.randomUUID());
+// ((ZombieControl) subscription4).addResult("getId", UUID.randomUUID());
+//
+// // bind(OverdueChecker.class).to(DefaultOverdueChecker.class).asEagerSingleton();
+// CatalogService catalogService = BrainDeadProxyFactory.createBrainDeadProxyFor(CatalogService.class);
+// ((ZombieControl) catalogService).addResult("getCurrentCatalog", new MockCatalog() {
+//
+// @Override
+// public void setOverdueRules() {
+// OverdueRules overdueRules = new MockOverdueRules().setOverdueStatesBundle(bundleODS);
+// setOverdueRules(overdueRules);
+// }
+//
+// });
+// bind(CatalogService.class).toInstance(catalogService);
+//
+//
+// bind(OverdueAccessDao.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(OverdueAccessDao.class));
+// bind(OverdueAccessApi.class).toInstance(overdueAccessApi);
+//
+// }
+//
+// });
+// odc = i.getInstance(OverdueEventCalculator.class);
+//
+// }
+//
+// @Test
+// // S1-S2-S3 subscriptions in B1
+// // B1 -----[--------]
+// // S1 --A-------------------------------------
+// // S2 --B------C------------------------------
+// // S3 ------------------D---------------------
+//
+//
+// //Result
+// // S1 --A--[-------]--------------------------
+// // S2 --B--[-------]--------------------------
+// // S3 ------------------D---------------------
+//
+// public void testInsertOverdueEvents() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, null));
+// BillingEvent A = createRealEvent(now.minusDays(1).minusHours(1), subscription1);
+// BillingEvent B = createRealEvent(now.minusDays(1), subscription2);
+// BillingEvent C = createRealEvent(now.plusDays(1), subscription2);
+// BillingEvent D = createRealEvent(now.plusDays(3), subscription3);
+// billingEvents.add(A);
+// billingEvents.add(B);
+// billingEvents.add(C);
+// billingEvents.add(D);
+//
+// SortedSet<OverdueEvent> overdueBundleEvents = new TreeSet<OverdueEvent>();
+// overdueBundleEvents.add(new OverdueEvent(bundleId1,DISABLED_BUNDLE, Overdueable.Type.SUBSCRIPTION_BUNDLE, now));
+// overdueBundleEvents.add(new OverdueEvent(bundleId1,CLEAR_BUNDLE, Overdueable.Type.SUBSCRIPTION_BUNDLE, now.plusDays(2)));
+//
+// ((ZombieControl)overdueAccessApi).addResult("getOverdueHistory", overdueBundleEvents);
+//
+//
+// odc.insertOverdueEvents(billingEvents);
+//
+// assertEquals(billingEvents.size(), 7);
+//
+// SortedSet<BillingEvent> s1Events = odc.filter(billingEvents, subscription1);
+// Iterator<BillingEvent> it1 = s1Events.iterator();
+// assertEquals(it1.next(), A);
+// assertEquals(it1.next().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// assertEquals(it1.next().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+//
+// SortedSet<BillingEvent> s2Events = odc.filter(billingEvents, subscription2);
+// Iterator<BillingEvent> it2 = s2Events.iterator();
+// assertEquals(it2.next(), B);
+// assertEquals(it2.next().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// assertEquals(it2.next().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+//
+// SortedSet<BillingEvent> s3Events = odc.filter(billingEvents, subscription3);
+// Iterator<BillingEvent> it3 = s3Events.iterator();
+// assertEquals(it3.next(),D);
+// }
+//
+// // Open ended duration with a previous event
+// // --X--[----------------------------------
+// @Test
+// public void testEventsToRemoveOpenPrev() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, null));
+// billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 0);
+// }
+//
+// // Open with previous and following events
+// // --X--[----Y-----------------------------
+// @Test
+// public void testEventsToRemoveOpenPrevFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, null));
+// BillingEvent e1 = createRealEvent(now.minusDays(1), subscription1);
+// BillingEvent e2 = createRealEvent(now.plusDays(1), subscription1);
+// billingEvents.add(e1);
+// billingEvents.add(e2);
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.first(), e2);
+// }
+//
+// // Open with no previous event (only following)
+// // -----[----X-----------------------------
+// @Test
+// public void testEventsToRemoveOpenFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, null));
+// BillingEvent e1 = createRealEvent(now.plusDays(1), subscription1);
+// billingEvents.add(e1);
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.first(), e1);
+// }
+//
+// // Closed duration with a single previous event
+// // --X--[------------]---------------------
+// @Test
+// public void testEventsToRemoveClosedPrev() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// BillingEvent e1 = createRealEvent(now.minusDays(1), subscription1);
+// billingEvents.add(e1);
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 0);
+// }
+//
+// // Closed duration with a previous event and in-between event
+// // --X--[------Y-----]---------------------
+// @Test
+// public void testEventsToRemoveClosedPrevBetw() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+// billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 2);
+// assertEquals(results.first().getEffectiveDate(), now);
+// assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+// assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+// assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+// assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+// }
+//
+// // Closed duration with a previous event and in-between event and following
+// // --X--[------Y-----]-------Z-------------
+// @Test
+// public void testEventsToRemoveClosedPrevBetwNext() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// BillingEvent e1 = createRealEvent(now.minusDays(1), subscription1);
+// BillingEvent e2 = createRealEvent(now.plusDays(1), subscription1);
+// BillingEvent e3 = createRealEvent(now.plusDays(3), subscription1);
+// billingEvents.add(e1);
+// billingEvents.add(e2);
+// billingEvents.add(e3);
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.first(), e2);
+// }
+//
+// // Closed with no previous event but in-between events
+// // -----[------Y-----]---------------------
+// @Test
+// public void testEventsToRemoveClosedBetwn() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// BillingEvent e2 = createRealEvent(now.plusDays(1), subscription1);
+// billingEvents.add(e2);
+//
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.first(), e2);
+// }
+//
+// // Closed with no previous event but in-between events and following
+// // -----[------Y-----]-------Z-------------
+// @Test
+// public void testEventsToRemoveClosedBetweenFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+//
+// BillingEvent e2 = createRealEvent(now.plusDays(1), subscription1);
+// BillingEvent e3 = createRealEvent(now.plusDays(3), subscription1);
+// billingEvents.add(e2);
+// billingEvents.add(e3);
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.first(), e2);
+// }
+//
+// // Closed duration with only following
+// // -----[------------]-------Z-------------
+// @Test
+// public void testEventsToRemoveClosedFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+//
+// BillingEvent e3 = createRealEvent(now.plusDays(3), subscription1);
+//
+// billingEvents.add(e3);
+//
+// SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+//
+// assertEquals(results.size(), 0);
+// }
+//
+// // Open ended duration with a previous event
+// // --X--[----------------------------------
+// @Test
+// public void testCreateNewEventsOpenPrev() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, null));
+// billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.first().getEffectiveDate(), now);
+// assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+// assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// }
+//
+// // Open with previous and following events
+// // --X--[----Y-----------------------------
+// @Test
+// public void testCreateNewEventsOpenPrevFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, null));
+// billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+// billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.first().getEffectiveDate(), now);
+// assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+// assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// }
+//
+// // Open with no previous event (only following)
+// // -----[----X-----------------------------
+// @Test
+// public void testCreateNewEventsOpenFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, null));
+// billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 0);
+// }
+//
+// // Closed duration with a single previous event
+// // --X--[------------]---------------------
+// @Test
+// public void testCreateNewEventsClosedPrev() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 2);
+// assertEquals(results.first().getEffectiveDate(), now);
+// assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+// assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+// assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+// assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+// }
+//
+// // Closed duration with a previous event and in-between event
+// // --X--[------Y-----]---------------------
+// @Test
+// public void testCreateNewEventsClosedPrevBetw() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+// billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 2);
+// assertEquals(results.first().getEffectiveDate(), now);
+// assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+// assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+// assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+// assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+// }
+//
+// // Closed duration with a previous event and in-between event and following
+// // --X--[------Y-----]-------Z-------------
+// @Test
+// public void testCreateNewEventsClosedPrevBetwNext() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+// billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+// billingEvents.add(createRealEvent(now.plusDays(3), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 2);
+// assertEquals(results.first().getEffectiveDate(), now);
+// assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+// assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+// assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+// assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+// assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+// }
+//
+// // Closed with no previous event but in-between events
+// // -----[------Y-----]---------------------
+// @Test
+// public void testCreateNewEventsClosedBetwn() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+// assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+// assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+// }
+//
+// // Closed with no previous event but in-between events and following
+// // -----[------Y-----]-------Z-------------
+// @Test
+// public void testCreateNewEventsClosedBetweenFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 1);
+// assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+// assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+// assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+// }
+//
+// // Closed duration with only following
+// // -----[------------]-------Z-------------
+// @Test
+// public void testCreateNewEventsClosedFollow() {
+// DateTime now = clock.getUTCNow();
+// List<DisabledDuration> disabledDuration = new ArrayList<OverdueEventCalculator.DisabledDuration>();
+// SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+//
+// disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+// billingEvents.add(createRealEvent(now.plusDays(3), subscription1));
+//
+// SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents, account, subscription1);
+//
+// assertEquals(results.size(), 0);
+// }
+//
+// @Test
+// public void testPrecedingBillingEventForSubscription() {
+// DateTime now = new DateTime();
+//
+// SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+//
+// events.add(createRealEvent(now.minusDays(10), subscription1));
+// events.add(createRealEvent(now.minusDays(6), subscription1));
+// events.add(createRealEvent(now.minusDays(5), subscription1));
+// events.add(createRealEvent(now.minusDays(1), subscription1));
+//
+// BillingEvent minus11 = odc.precedingBillingEventForSubscription(now.minusDays(11), events, subscription1);
+// assertNull(minus11);
+//
+// BillingEvent minus5andAHalf= odc.precedingBillingEventForSubscription(now.minusDays(5).minusHours(12), events, subscription1);
+// assertNotNull(minus5andAHalf);
+// assertEquals(minus5andAHalf.getEffectiveDate(), now.minusDays(6));
+//
+//
+// }
+//
+// protected BillingEvent createRealEvent(DateTime effectiveDate, Subscription subscription) {
+// final Account account = this.account;
+// final int billCycleDay = 1;
+// final PlanPhase planPhase = new MockPlanPhase();
+// final Plan plan = new MockPlan();
+// final BigDecimal fixedPrice = BigDecimal.TEN;
+// final BigDecimal recurringPrice = BigDecimal.TEN;
+// final Currency currency = Currency.USD;
+// final String description = "";
+// final BillingModeType billingModeType = BillingModeType.IN_ADVANCE;
+// final BillingPeriod billingPeriod = BillingPeriod.MONTHLY;
+// final SubscriptionTransitionType type = SubscriptionTransitionType.CHANGE;
+// final Long totalOrdering = 0L; //TODO
+//
+// return new DefaultBillingEvent(account, subscription, effectiveDate, plan, planPhase,
+// fixedPrice, recurringPrice, currency,
+// billingPeriod, billCycleDay, billingModeType,
+// description, totalOrdering, type);
+// }
+//
+//
+// @Test
+// public void testFilter() {
+// SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+//
+// events.add(createBillingEvent(subscription1));
+// events.add(createBillingEvent(subscription1));
+// events.add(createBillingEvent(subscription1));
+// events.add(createBillingEvent(subscription2));
+//
+// SortedSet<BillingEvent> result1 = odc.filter(events, subscription1);
+// SortedSet<BillingEvent> result2 = odc.filter(events, subscription2);
+// SortedSet<BillingEvent> result3 = odc.filter(events, subscription3);
+//
+// assertEquals(result1.size(), 3);
+// assertEquals(result1.first().getSubscription(), subscription1);
+// assertEquals(result1.last().getSubscription(), subscription1);
+// assertEquals(result2.size(), 1);
+// assertEquals(result2.first().getSubscription(), subscription2);
+// assertEquals(result3.size(), 0);
+// }
+//
+// @Test
+// public void testCreateNewDisableEvent() {
+// DateTime now = clock.getUTCNow();
+// BillingEvent event = new MockBillingEvent();
+//
+// BillingEvent result = odc.createNewDisableEvent(now, event);
+// assertEquals(result.getBillCycleDay(),event.getBillCycleDay());
+// assertEquals(result.getEffectiveDate(), now);
+// assertEquals(result.getPlanPhase(), event.getPlanPhase());
+// assertEquals(result.getPlan(), event.getPlan());
+// assertEquals(result.getFixedPrice(),BigDecimal.ZERO);
+// assertEquals(result.getRecurringPrice(), BigDecimal.ZERO);
+// assertEquals(result.getCurrency(), event.getCurrency());
+// assertEquals(result.getDescription(), "");
+// assertEquals(result.getBillingMode(), event.getBillingMode());
+// assertEquals(result.getBillingPeriod(), event.getBillingPeriod());
+// assertEquals(result.getTransitionType(), SubscriptionTransitionType.CANCEL);
+// assertEquals(result.getTotalOrdering(), new Long(0));
+// }
+//
+// @Test
+// public void testCreateNewReenableEvent() {
+// DateTime now = clock.getUTCNow();
+// BillingEvent event = new MockBillingEvent();
+//
+// BillingEvent result = odc.createNewReenableEvent(now, event);
+// assertEquals(result.getBillCycleDay(),event.getBillCycleDay());
+// assertEquals(result.getEffectiveDate(), now);
+// assertEquals(result.getPlanPhase(), event.getPlanPhase());
+// assertEquals(result.getPlan(), event.getPlan());
+// assertEquals(result.getFixedPrice(),event.getFixedPrice());
+// assertEquals(result.getRecurringPrice(), event.getRecurringPrice());
+// assertEquals(result.getCurrency(), event.getCurrency());
+// assertEquals(result.getDescription(), "");
+// assertEquals(result.getBillingMode(), event.getBillingMode());
+// assertEquals(result.getBillingPeriod(), event.getBillingPeriod());
+// assertEquals(result.getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+// assertEquals(result.getTotalOrdering(), new Long(0));
+// }
+//
+// private class MockBillingEvent extends DefaultBillingEvent {
+// public MockBillingEvent() {
+// super(account, subscription1, clock.getUTCNow(), null, null, BigDecimal.ZERO, BigDecimal.TEN, Currency.USD, BillingPeriod.ANNUAL,
+// 4, BillingModeType.IN_ADVANCE, "", 3L, SubscriptionTransitionType.CREATE);
+// }
+// }
+//
+// @Test
+// public void testCreateBundleSubscriptionMap() {
+// SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+// events.add(createBillingEvent(subscription1));
+// events.add(createBillingEvent(subscription2));
+// events.add(createBillingEvent(subscription3));
+// events.add(createBillingEvent(subscription4));
+//
+// Hashtable<UUID,Set<Subscription>> map = odc.createBundleSubscriptionMap(events);
+//
+// assertNotNull(map);
+// assertEquals(map.keySet().size(),2);
+// assertEquals(map.get(bundleId1).size(), 3);
+// assertEquals(map.get(bundleId2).size(), 1);
+//
+// }
+//
+// private BillingEvent createBillingEvent(Subscription subscription) {
+// BillingEvent result = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingEvent.class, Comparable.class);
+// ((ZombieControl)result).addResult("getSubscription", subscription);
+// ((ZombieControl)result).addResult("compareTo", 1);
+// return result;
+// }
+//
+// @Test
+// public void testCreateDisablePairs() {
+// SortedSet<OverdueEvent> overdueBundleEvents;
+// UUID ovdId = UUID.randomUUID();
+// DateTime now = clock.getUTCNow();
+//
+// //simple events open clear -> disabled
+// overdueBundleEvents = new TreeSet<OverdueEvent>();
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(1)));
+//
+// List<DisabledDuration> pairs = odc.createDisablePairs(overdueBundleEvents);
+// assertEquals(pairs.size(), 1);
+// assertNotNull(pairs.get(0).getStart());
+// assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+// assertNull(pairs.get(0).getEnd());
+//
+// //simple events closed clear -> disabled
+// overdueBundleEvents = new TreeSet<OverdueEvent>();
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(1)));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(2)));
+//
+// pairs = odc.createDisablePairs(overdueBundleEvents);
+// assertEquals(pairs.size(), 1);
+// assertNotNull(pairs.get(0).getStart());
+// assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+// assertNotNull(pairs.get(0).getEnd());
+// assertEquals(pairs.get(0).getEnd(),now.plusDays(2));
+//
+// //simple BUNDLE events closed clear -> disabled
+// overdueBundleEvents = new TreeSet<OverdueEvent>();
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(1)));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(2)));
+//
+// pairs = odc.createDisablePairs(overdueBundleEvents);
+// assertEquals(pairs.size(), 1);
+// assertNotNull(pairs.get(0).getStart());
+// assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+// assertNotNull(pairs.get(0).getEnd());
+// assertEquals(pairs.get(0).getEnd(),now.plusDays(2));
+//
+//
+// //two or more disableds in a row
+// overdueBundleEvents = new TreeSet<OverdueEvent>();
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(1)));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(2)));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(3)));
+//
+// pairs = odc.createDisablePairs(overdueBundleEvents);
+// assertEquals(pairs.size(), 1);
+// assertNotNull(pairs.get(0).getStart());
+// assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+// assertNotNull(pairs.get(0).getEnd());
+// assertEquals(pairs.get(0).getEnd(),now.plusDays(3));
+//
+//
+// overdueBundleEvents = new TreeSet<OverdueEvent>();
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(1)));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(2)));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(3)));
+// overdueBundleEvents.add(new OverdueEvent(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,now.plusDays(4)));
+//
+// pairs = odc.createDisablePairs(overdueBundleEvents);
+// assertEquals(pairs.size(), 1);
+// assertNotNull(pairs.get(0).getStart());
+// assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+// assertNotNull(pairs.get(0).getEnd());
+// assertEquals(pairs.get(0).getEnd(),now.plusDays(4));
+//
+// }
+//
+// @Test
+// public void testIsDisableEvent() {
+// DateTime now = clock.getUTCNow();
+// assertTrue(!odc.isDisableEvent(new OverdueEvent(new UUID(0L,0L), CLEAR_BUNDLE, Overdueable.Type.SUBSCRIPTION_BUNDLE, now)));
+// assertTrue(odc.isDisableEvent(new OverdueEvent(new UUID(0L,0L), DISABLED_BUNDLE, Overdueable.Type.SUBSCRIPTION_BUNDLE, now)));
+// }
+//
+}
junction/src/test/resources/log4j.xml 40(+40 -0)
diff --git a/junction/src/test/resources/log4j.xml b/junction/src/test/resources/log4j.xml
new file mode 100644
index 0000000..ac530a1
--- /dev/null
+++ b/junction/src/test/resources/log4j.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%p %d{ISO8601} %X{trace} %t %c %m%n"/>
+ </layout>
+ </appender>
+
+
+ <logger name="com.ning.billing.entitlement">
+ <level value="info"/>
+ </logger>
+
+ <logger name="com.ning.billing.util.notificationq">
+ <level value="info"/>
+ </logger>
+
+ <root>
+ <priority value="info"/>
+ <appender-ref ref="stdout"/>
+ </root>
+</log4j:configuration>
diff --git a/junction/src/test/resources/resource.properties b/junction/src/test/resources/resource.properties
new file mode 100644
index 0000000..d63334b
--- /dev/null
+++ b/junction/src/test/resources/resource.properties
@@ -0,0 +1,7 @@
+killbill.catalog.uri=file:src/test/resources/catalogSample.xml
+killbill.entitlement.dao.claim.time=60000
+killbill.entitlement.dao.ready.max=1
+killbill.entitlement.engine.notifications.sleep=500
+user.timezone=UTC
+
+
overdue/pom.xml 138(+138 -0)
diff --git a/overdue/pom.xml b/overdue/pom.xml
new file mode 100644
index 0000000..b6f64a0
--- /dev/null
+++ b/overdue/pom.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ 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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill</artifactId>
+ <version>0.1.11-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>killbill-overdue</artifactId>
+ <name>killbill-overdue</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.skife.config</groupId>
+ <artifactId>config-magic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jdbi</groupId>
+ <artifactId>jdbi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!-- Check if we need this one -->
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj-db-files</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.jayway.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!-- Strangely this is needed in order to run the tests in local db mode -->
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <groups>fast,slow, stress</groups>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
new file mode 100644
index 0000000..ef4ec4f
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
@@ -0,0 +1,112 @@
+/*
+ * 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.ovedue.notification;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.ning.billing.config.NotificationConfig;
+import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.overdue.service.DefaultOverdueService;
+import com.ning.billing.util.notificationq.NotificationQueue;
+import com.ning.billing.util.notificationq.NotificationQueueService;
+import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
+import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueHandler;
+
+public class DefaultOverdueCheckNotifier implements OverdueCheckNotifier {
+
+ private final static Logger log = LoggerFactory.getLogger(DefaultOverdueCheckNotifier.class);
+
+ public static final String OVERDUE_CHECK_NOTIFIER_QUEUE = "overdue-check-queue";
+
+ private final NotificationQueueService notificationQueueService;
+ private final OverdueProperties config;
+
+ private NotificationQueue overdueQueue;
+ private final OverdueListener listener;
+
+ @Inject
+ public DefaultOverdueCheckNotifier(NotificationQueueService notificationQueueService,
+ OverdueProperties config, OverdueListener listener){
+ this.notificationQueueService = notificationQueueService;
+ this.config = config;
+ this.listener = listener;
+ }
+
+ @Override
+ public void initialize() {
+ try {
+ overdueQueue = notificationQueueService.createNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
+ OVERDUE_CHECK_NOTIFIER_QUEUE,
+ new NotificationQueueHandler() {
+ @Override
+ public void handleReadyNotification(String notificationKey, DateTime eventDate) {
+ try {
+ UUID key = UUID.fromString(notificationKey);
+ processEvent(key , eventDate);
+ } catch (IllegalArgumentException e) {
+ log.error("The key returned from the NextBillingNotificationQueue is not a valid UUID", e);
+ return;
+ }
+
+ }
+ },
+ new NotificationConfig() {
+ @Override
+ public boolean isNotificationProcessingOff() {
+ return config.isNotificationProcessingOff();
+ }
+ @Override
+ public long getNotificationSleepTimeMs() {
+ return config.getNotificationSleepTimeMs();
+ }
+ @Override
+ public int getDaoMaxReadyEvents() {
+ return config.getDaoMaxReadyEvents();
+ }
+ @Override
+ public long getDaoClaimTimeMs() {
+ return config.getDaoClaimTimeMs();
+ }
+ });
+ } catch (NotificationQueueAlreadyExists e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void start() {
+ overdueQueue.startQueue();
+ }
+
+ @Override
+ public void stop() {
+ if (overdueQueue != null) {
+ overdueQueue.stopQueue();
+ }
+ }
+
+ private void processEvent(UUID overdueableId, DateTime eventDateTime) {
+ listener.handleNextOverdueCheck(overdueableId, eventDateTime);
+ }
+
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
new file mode 100644
index 0000000..106a5c4
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
@@ -0,0 +1,73 @@
+/*
+ * 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.ovedue.notification;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.service.DefaultOverdueService;
+import com.ning.billing.util.notificationq.NotificationKey;
+import com.ning.billing.util.notificationq.NotificationQueue;
+import com.ning.billing.util.notificationq.NotificationQueueService;
+import com.ning.billing.util.notificationq.NotificationQueueService.NoSuchNotificationQueue;
+
+public class DefaultOverdueCheckPoster implements OverdueCheckPoster {
+ private final static Logger log = LoggerFactory.getLogger(DefaultOverdueCheckNotifier.class);
+
+ private final NotificationQueueService notificationQueueService;
+
+ @Inject
+ public DefaultOverdueCheckPoster(
+ NotificationQueueService notificationQueueService) {
+ super();
+ this.notificationQueueService = notificationQueueService;
+ }
+
+ @Override
+ public void insertOverdueCheckNotification(final Transmogrifier transactionalDao, final Blockable overdueable, final DateTime futureNotificationTime) {
+ NotificationQueue checkOverdueQueue;
+ try {
+ checkOverdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
+ DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
+ log.info("Queuing overdue check notification. id: {}, timestamp: {}", overdueable.getId().toString(), futureNotificationTime.toString());
+
+ checkOverdueQueue.recordFutureNotificationFromTransaction(transactionalDao, futureNotificationTime, new NotificationKey(){
+ @Override
+ public String toString() {
+ return overdueable.getId().toString();
+ }
+ });
+ } catch (NoSuchNotificationQueue e) {
+ log.error("Attempting to put items on a non-existent queue (DefaultOverdueCheck).", e);
+ }
+ }
+
+ public void clearNotificationEventsFor(final Blockable overdueable) {
+ NotificationQueue checkOverdueQueue;
+ try {
+ checkOverdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
+ DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
+ checkOverdueQueue.removeNotificationsByKey(overdueable.getId());
+ } catch (NoSuchNotificationQueue e) {
+ log.error("Attempting to clear items from a non-existent queue (DefaultOverdueCheck).", e);
+ }
+ }
+}
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotifier.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotifier.java
new file mode 100644
index 0000000..7ef6ab8
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotifier.java
@@ -0,0 +1,28 @@
+/*
+ * 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.ovedue.notification;
+
+
+public interface OverdueCheckNotifier {
+
+ public void initialize();
+
+ public void start();
+
+ public void stop();
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckPoster.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckPoster.java
new file mode 100644
index 0000000..8105bc7
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckPoster.java
@@ -0,0 +1,30 @@
+/*
+ * 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.ovedue.notification;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+
+import com.ning.billing.junction.api.Blockable;
+
+
+public interface OverdueCheckPoster {
+
+ void insertOverdueCheckNotification(Transmogrifier transactionalDao,
+ Blockable overdueable, DateTime futureNotificationTime);
+
+}
\ No newline at end of file
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueListener.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueListener.java
new file mode 100644
index 0000000..e3ddcf3
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueListener.java
@@ -0,0 +1,30 @@
+/*
+ * 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.ovedue.notification;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+public class OverdueListener {
+
+ public void handleNextOverdueCheck(UUID subscriptionId, DateTime eventDateTime) {
+ //TODO
+
+ }
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/OverdueProperties.java b/overdue/src/main/java/com/ning/billing/ovedue/OverdueProperties.java
new file mode 100644
index 0000000..956d957
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/ovedue/OverdueProperties.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ovedue;
+
+import org.skife.config.Config;
+import org.skife.config.Default;
+
+import com.ning.billing.config.KillbillConfig;
+import com.ning.billing.config.NotificationConfig;
+
+
+public interface OverdueProperties extends NotificationConfig, KillbillConfig {
+
+ @Override
+ @Config("killbill.overdue.dao.claim.time")
+ @Default("60000")
+ public long getDaoClaimTimeMs();
+
+ @Override
+ @Config("killbill.overdue.dao.ready.max")
+ @Default("10")
+ public int getDaoMaxReadyEvents();
+
+ @Override
+ @Config("killbill.overdue.engine.notifications.sleep")
+ @Default("500")
+ public long getNotificationSleepTimeMs();
+
+ @Override
+ @Config("killbill.notifications.off")
+ @Default("false")
+ public boolean isNotificationProcessingOff();
+
+ @Config("killbill.overdue.maxNumberOfMonthsInFuture")
+ @Default("36")
+ public int getNumberOfMonthsInFuture();
+
+ @Config("killbill.overdue.configUri")
+ @Default("jar:///com/ning/billing/irs/catalog/Catalog.xml")
+ public String getConfigURI();
+}
\ No newline at end of file
diff --git a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
new file mode 100644
index 0000000..092911d
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
@@ -0,0 +1,77 @@
+/*
+ * 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.overdue.api;
+
+import org.apache.commons.lang.NotImplementedException;
+
+import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.overdue.OverdueUserApi;
+import com.ning.billing.overdue.config.OverdueConfig;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueStateSet;
+import com.ning.billing.overdue.service.ExtendedOverdueService;
+import com.ning.billing.overdue.wrapper.OverdueWrapper;
+import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
+
+public class DefaultOverdueUserApi implements OverdueUserApi{
+
+
+ private final OverdueWrapperFactory factory;
+ private final BlockingApi accessApi;
+ private final OverdueConfig overdueConfig;
+
+ @Inject
+ public DefaultOverdueUserApi(OverdueWrapperFactory factory,BlockingApi accessApi, ExtendedOverdueService service, CatalogService catalogService) {
+ this.factory = factory;
+ this.accessApi = accessApi;
+ this.overdueConfig = service.getOverdueConfig();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Blockable> OverdueState<T> getOverdueStateFor(T overdueable) throws OverdueError {
+ try {
+ String stateName = accessApi.getBlockingStateFor(overdueable).getStateName();
+ OverdueStateSet<SubscriptionBundle> states = overdueConfig.getBundleStateSet();
+ return (OverdueState<T>) states.findState(stateName);
+ } catch (CatalogApiException e) {
+ throw new OverdueError(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED,overdueable.getId(), overdueable.getClass().getSimpleName());
+ }
+ }
+
+ @Override
+ public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueError, CatalogApiException {
+ OverdueWrapper<T> wrapper = factory.createOverdueWrapperFor(overdueable);
+ return wrapper.refresh();
+ }
+
+
+ @Override
+ public <T extends Blockable> void setOverrideBillingStateForAccount(
+ T overdueable, BillingState<T> state) {
+ throw new NotImplementedException();
+ }
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
new file mode 100644
index 0000000..f809788
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
@@ -0,0 +1,97 @@
+/*
+ * 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.overdue.applicator;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.joda.time.DateTime;
+
+import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.overdue.OverdueService;
+import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.overdue.config.api.OverdueError;
+
+public class OverdueStateApplicator<T extends Blockable>{
+
+ private final BlockingApi blockingApi;
+
+
+ @Inject
+ public OverdueStateApplicator(BlockingApi accessApi) {
+ this.blockingApi = accessApi;
+ }
+
+ public void apply(T overdueable, OverdueState<T> previousOverdueState, OverdueState<T> nextOverdueState, DateTime timeOfNextCheck) throws OverdueError {
+ if(previousOverdueState.getName().equals(nextOverdueState.getName())) {
+ return; // nothing to do
+ }
+
+ storeNewState(overdueable, nextOverdueState);
+
+ if(timeOfNextCheck != null && !nextOverdueState.isClearState()) {
+ createFutureNotification(overdueable, timeOfNextCheck);
+ }
+
+ if(nextOverdueState.isClearState()) {
+ clear(overdueable);
+ }
+
+ //If new state is clear state reset next events and override table
+ throw new NotImplementedException();
+ }
+
+
+ protected void storeNewState(T blockable, OverdueState<T> nextOverdueState) throws OverdueError {
+ try {
+ blockingApi.setBlockingState(new BlockingState(blockable.getId(), nextOverdueState.getName(), Blockable.Type.get(blockable),
+ OverdueService.OVERDUE_SERVICE_NAME, blockChanges(nextOverdueState), blockEntitlement(nextOverdueState), blockBilling(nextOverdueState)));
+ } catch (Exception e) {
+ throw new OverdueError(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED, blockable.getId(), blockable.getClass().getName());
+ }
+ }
+
+ private boolean blockChanges(OverdueState<T> nextOverdueState) {
+ return nextOverdueState.blockChanges();
+ }
+
+ private boolean blockBilling(OverdueState<T> nextOverdueState) {
+ return nextOverdueState.disableEntitlementAndChangesBlocked();
+ }
+
+ private boolean blockEntitlement(OverdueState<T> nextOverdueState) {
+ return nextOverdueState.disableEntitlementAndChangesBlocked();
+ }
+
+ protected void createFutureNotification(T overdueable,
+ DateTime timeOfNextCheck) {
+ // TODO MDW
+
+ }
+
+
+
+ protected void clear(T overdueable) {
+ //TODO MDW
+ // Clear future notification checks
+ // Clear any overrides
+
+ }
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
new file mode 100644
index 0000000..640ca9a
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
@@ -0,0 +1,80 @@
+/*
+ * 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.overdue.calculator;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.google.inject.Inject;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.util.clock.Clock;
+
+public abstract class BillingStateCalculator<T extends Blockable> {
+
+ private final InvoiceUserApi invoiceApi;
+ private final Clock clock;
+
+ protected class InvoiceDateComparator implements Comparator<Invoice> {
+ @Override
+ public int compare(Invoice i1, Invoice i2) {
+ DateTime d1 = i1.getInvoiceDate();
+ DateTime d2 = i2.getInvoiceDate();
+ if(d1.compareTo(d2) == 0) {
+ return i1.hashCode() - i2.hashCode(); // consistent (arbitrary) resolution for tied dates
+ }
+ return d1.compareTo(d2);
+ }
+ }
+
+ @Inject
+ public BillingStateCalculator(InvoiceUserApi invoiceApi, Clock clock) {
+ this.invoiceApi = invoiceApi;
+ this.clock = clock;
+ }
+
+ public abstract BillingState<T> calculateBillingState(T overdueable);
+
+ protected DateTime earliest(SortedSet<Invoice> unpaidInvoices) {
+ return unpaidInvoices.first().getInvoiceDate();
+ }
+
+ protected BigDecimal sumBalance(SortedSet<Invoice> unpaidInvoices) {
+ BigDecimal sum = BigDecimal.ZERO;
+ Iterator<Invoice> it = unpaidInvoices.iterator();
+ while(it.hasNext()) {
+ sum = sum.add(it.next().getBalance());
+ }
+ return sum;
+ }
+
+ protected SortedSet<Invoice> unpaidInvoicesForAccount(UUID accountId) {
+ Collection<Invoice> invoices = invoiceApi.getUnpaidInvoicesByAccountId(accountId, clock.getUTCNow());
+ SortedSet<Invoice> sortedInvoices = new TreeSet<Invoice>(new InvoiceDateComparator());
+ sortedInvoices.addAll(invoices);
+ return sortedInvoices;
+ }
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
new file mode 100644
index 0000000..544420f
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
@@ -0,0 +1,107 @@
+/*
+ * 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.overdue.calculator;
+
+import java.math.BigDecimal;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.overdue.config.api.BillingStateBundle;
+import com.ning.billing.overdue.config.api.PaymentResponse;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.tag.Tag;
+
+public class BillingStateCalculatorBundle extends BillingStateCalculator<SubscriptionBundle>{
+
+ private EntitlementUserApi entitlementApi;
+
+ @Inject
+ public BillingStateCalculatorBundle(EntitlementUserApi entitlementApi, InvoiceUserApi invoiceApi, Clock clock) {
+ super(invoiceApi, clock);
+ this.entitlementApi = entitlementApi;
+ }
+
+ @Override
+ public BillingStateBundle calculateBillingState(SubscriptionBundle bundle) {
+
+ SortedSet<Invoice> unpaidInvoices = unpaidInvoicesForBundle(bundle.getId(), bundle.getAccountId());
+
+ Subscription basePlan = entitlementApi.getBaseSubscription(bundle.getId());
+
+ UUID id = bundle.getId();
+ int numberOfUnpaidInvoices = unpaidInvoices.size();
+ BigDecimal unpaidInvoiceBalance = sumBalance(unpaidInvoices);
+ DateTime dateOfEarliestUnpaidInvoice = earliest(unpaidInvoices);
+ PaymentResponse responseForLastFailedPayment = PaymentResponse.INSUFFICIENT_FUNDS; //TODO MDW
+ Tag[] tags = new Tag[]{}; //TODO MDW
+ Product basePlanProduct = basePlan.getCurrentPlan().getProduct();
+ BillingPeriod basePlanBillingPeriod = basePlan.getCurrentPlan().getBillingPeriod();
+ PriceList basePlanPriceList = basePlan.getCurrentPriceList();
+ PhaseType basePlanPhaseType = basePlan.getCurrentPhase().getPhaseType();
+
+
+ return new BillingStateBundle(
+ id,
+ numberOfUnpaidInvoices,
+ unpaidInvoiceBalance,
+ dateOfEarliestUnpaidInvoice,
+ responseForLastFailedPayment,
+ tags,
+ basePlanProduct,
+ basePlanBillingPeriod,
+ basePlanPriceList,
+ basePlanPhaseType);
+
+ }
+
+ public SortedSet<Invoice> unpaidInvoicesForBundle(UUID bundleId, UUID accountId) {
+ SortedSet<Invoice> unpaidInvoices = unpaidInvoicesForAccount(accountId);
+ SortedSet<Invoice> result = new TreeSet<Invoice>(new InvoiceDateComparator());
+ result.addAll(unpaidInvoices);
+ for(Invoice invoice : unpaidInvoices) {
+ if(!invoiceHasAnItemFromBundle(invoice, bundleId)) {
+ result.remove(invoice);
+ }
+ }
+ return result;
+ }
+
+ private boolean invoiceHasAnItemFromBundle(Invoice invoice, UUID bundleId) {
+ for(InvoiceItem item : invoice.getInvoiceItems()) {
+ if(item.getBundleId().equals(bundleId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/Condition.java b/overdue/src/main/java/com/ning/billing/overdue/config/Condition.java
new file mode 100644
index 0000000..6fc8564
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/Condition.java
@@ -0,0 +1,30 @@
+/*
+ * 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.overdue.config;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.config.api.BillingState;
+
+
+
+public interface Condition<T extends Blockable> {
+
+ public boolean evaluate(BillingState state, DateTime now);
+
+}
\ No newline at end of file
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
new file mode 100644
index 0000000..08c13a9
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
@@ -0,0 +1,93 @@
+/*
+ * 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.overdue.config;
+
+import java.math.BigDecimal;
+import java.net.URI;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.overdue.config.api.PaymentResponse;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
+
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class DefaultCondition<T extends Blockable> extends ValidatingConfig<OverdueConfig> implements Condition<T> {
+ @XmlElement(required=false, name="numberOfUnpaidInvoicesEqualsOrExceeds")
+ private Integer numberOfUnpaidInvoicesEqualsOrExceeds;
+
+ @XmlElement(required=false, name="totalUnpaidInvoiceBalanceEqualsOrExceeds")
+ private BigDecimal totalUnpaidInvoiceBalanceEqualsOrExceeds;
+
+ @XmlElement(required=false, name="timeSinceEarliestUnpaidInvoiceEqualsOrExceeds")
+ private DefaultDuration timeSinceEarliestUnpaidInvoiceEqualsOrExceeds;
+
+ @XmlElementWrapper(required=false, name="responseForLastFailedPaymentIn")
+ @XmlElement(required=false, name="response")
+ private PaymentResponse[] responseForLastFailedPayment;
+
+ @XmlElement(required=false, name="controlTag")
+ private ControlTagType controlTag;
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.overdue.Condition#evaluate(com.ning.billing.catalog.api.overdue.BillingState, org.joda.time.DateTime)
+ */
+ @Override
+ public boolean evaluate(BillingState state, DateTime now) {
+ return
+ (numberOfUnpaidInvoicesEqualsOrExceeds == null || state.getNumberOfUnpaidInvoices() >= numberOfUnpaidInvoicesEqualsOrExceeds.intValue() ) &&
+ (totalUnpaidInvoiceBalanceEqualsOrExceeds == null || totalUnpaidInvoiceBalanceEqualsOrExceeds.compareTo(state.getBalanceOfUnpaidInvoices()) <= 0) &&
+ (timeSinceEarliestUnpaidInvoiceEqualsOrExceeds == null || !timeSinceEarliestUnpaidInvoiceEqualsOrExceeds.addToDateTime(state.getDateOfEarliestUnpaidInvoice()).isAfter(now)) &&
+ (responseForLastFailedPayment == null || responseIsIn(state.getResponseForLastFailedPayment(), responseForLastFailedPayment)) &&
+ (controlTag == null || isTagIn(controlTag, state.getTags()));
+ }
+
+ private boolean responseIsIn(PaymentResponse actualResponse,
+ PaymentResponse[] responseForLastFailedPayment) {
+ for(PaymentResponse response: responseForLastFailedPayment) {
+ if(response.equals(actualResponse)) return true;
+ }
+ return false;
+ }
+
+ private boolean isTagIn(ControlTagType tag, Tag[] tags) {
+ for(Tag t : tags) {
+ if (t.getTagDefinitionName().equals(tag.toString())) return true;
+ }
+ return false;
+ }
+
+ @Override
+ public ValidationErrors validate(OverdueConfig root,
+ ValidationErrors errors) {
+ return errors;
+ }
+
+ @Override
+ public void initialize(OverdueConfig root, URI uri) {
+ }
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultDuration.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultDuration.java
new file mode 100644
index 0000000..90d3670
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultDuration.java
@@ -0,0 +1,89 @@
+/*
+ * 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.overdue.config;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.TimeUnit;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class DefaultDuration extends ValidatingConfig<OverdueConfig> implements Duration {
+ @XmlElement(required=true)
+ private TimeUnit unit;
+
+ @XmlElement(required=false)
+ private Integer number = -1;
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.IDuration#getUnit()
+ */
+ @Override
+ public TimeUnit getUnit() {
+ return unit;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.IDuration#getLength()
+ */
+ @Override
+ public int getNumber() {
+ return number;
+ }
+
+ @Override
+ public DateTime addToDateTime(DateTime dateTime) {
+ if (number == null) {return dateTime;}
+
+ switch (unit) {
+ case DAYS:
+ return dateTime.plusDays(number);
+ case MONTHS:
+ return dateTime.plusMonths(number);
+ case YEARS:
+ return dateTime.plusYears(number);
+ case UNLIMITED:
+ return dateTime.plusYears(100);
+ default:
+ return dateTime;
+ }
+ }
+
+ @Override
+ public ValidationErrors validate(OverdueConfig catalog, ValidationErrors errors) {
+ //TODO MDW - Validation TimeUnit UNLIMITED iff number == -1
+ return errors;
+ }
+
+ protected DefaultDuration setUnit(TimeUnit unit) {
+ this.unit = unit;
+ return this;
+ }
+
+ protected DefaultDuration setNumber(Integer number) {
+ this.number = number;
+ return this;
+ }
+
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
new file mode 100644
index 0000000..1d76d72
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
@@ -0,0 +1,145 @@
+/*
+ * 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.overdue.config;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlID;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
+import com.ning.billing.util.config.ValidationErrors;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<OverdueConfig> implements OverdueState<T> {
+
+ private static final int MAX_NAME_LENGTH = 50;
+
+ @XmlElement(required=false, name="condition")
+ private DefaultCondition<T> condition;
+
+ @XmlAttribute(required=true, name="name")
+ @XmlID
+ private String name;
+
+ @XmlElement(required=false, name="externalMessage")
+ private String externalMessage = "";
+
+ @XmlElement(required=false, name="disableEntitlementAndChangesBlocked")
+ private Boolean disableEntitlement = false;
+
+ @XmlElement(required=false, name="blockChanges")
+ private Boolean blockChanges = false;
+
+ @XmlElement(required=false, name="daysBetweenPaymentRetries")
+ private Integer daysBetweenPaymentRetries = 8;
+
+ @XmlElement(required=false, name="isClearState")
+ private Boolean isClearState = false;
+
+ //Other actions could include
+ // - send email
+ // - trigger payment retry?
+ // - add tags to bundle/account
+ // - set payment failure email template
+ // - set payment retry interval
+ // - backup payment mechanism?
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.overdue.OverdueState#getStageName()
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.overdue.OverdueState#getExternalMessage()
+ */
+ @Override
+ public String getExternalMessage() {
+ return externalMessage;
+ }
+
+ @Override
+ public boolean blockChanges() {
+ return blockChanges || disableEntitlement;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.overdue.OverdueState#applyCancel()
+ */
+ @Override
+ public boolean disableEntitlementAndChangesBlocked() {
+ return disableEntitlement;
+ }
+
+
+ protected DefaultCondition<T> getCondition() {
+ return condition;
+ }
+
+ protected DefaultOverdueState<T> setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ protected DefaultOverdueState<T> setExternalMessage(String externalMessage) {
+ this.externalMessage = externalMessage;
+ return this;
+ }
+
+ protected DefaultOverdueState<T> setDisableEntitlement(boolean cancel) {
+ this.disableEntitlement = cancel;
+ return this;
+ }
+
+ protected DefaultOverdueState<T> setBlockChanges(boolean cancel) {
+ this.blockChanges = cancel;
+ return this;
+ }
+
+ protected DefaultOverdueState<T> setCondition(DefaultCondition<T> condition) {
+ this.condition = condition;
+ return this;
+ }
+
+ @Override
+ public boolean isClearState() {
+ return isClearState;
+ }
+
+ @Override
+ public ValidationErrors validate(OverdueConfig root,
+ ValidationErrors errors) {
+ if(name.length() > MAX_NAME_LENGTH) {
+ errors.add(new ValidationError(String.format("Name of state '%s' exceeds the maximum length of %d",name,MAX_NAME_LENGTH),root.getURI(), DefaultOverdueState.class, name));
+ }
+ return errors;
+ }
+
+ @Override
+ public int getDaysBetweenPaymentRetries() {
+ return daysBetweenPaymentRetries;
+ }
+
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueStateSet.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueStateSet.java
new file mode 100644
index 0000000..bbda620
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueStateSet.java
@@ -0,0 +1,105 @@
+/*
+ * 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.overdue.config;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.joda.time.DateTime;
+
+import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.overdue.config.api.OverdueStateSet;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public abstract class DefaultOverdueStateSet<T extends Blockable> extends ValidatingConfig<OverdueConfig> implements OverdueStateSet<T> {
+ private DefaultOverdueState<T> clearState;
+
+ protected abstract DefaultOverdueState<T>[] getStates();
+
+ private DefaultOverdueState<T> getClearState() throws CatalogApiException {
+ for(DefaultOverdueState<T> overdueState : getStates()) {
+ if(overdueState.isClearState()) {
+ return overdueState;
+ }
+ }
+ throw new CatalogApiException(ErrorCode.CAT_MISSING_CLEAR_STATE);
+ }
+
+ @Override
+ public OverdueState<T> findState(String stateName) throws CatalogApiException {
+ for(DefaultOverdueState<T> state: getStates()) {
+ if(state.getName().equals(stateName) ) { return state; }
+ }
+ throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_OVEDUE_STATE, stateName);
+ }
+
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.overdue.OverdueBillingState#findClearState()
+ */
+ @Override
+ public DefaultOverdueState<T> findClearState() throws CatalogApiException {
+ if (clearState != null) {
+ clearState = getClearState();
+ }
+ return clearState;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.overdue.OverdueBillingState#calculateOverdueState(com.ning.billing.catalog.api.overdue.BillingState, org.joda.time.DateTime)
+ */
+ @Override
+ public DefaultOverdueState<T> calculateOverdueState(BillingState<T> billingState, DateTime now) throws CatalogApiException {
+ for(DefaultOverdueState<T> overdueState : getStates()) {
+ if(overdueState.getCondition().evaluate(billingState, now)) {
+ return overdueState;
+ }
+ }
+ return findClearState();
+ }
+
+ @Override
+ public DateTime dateOfNextCheck(BillingState<T> billingState, DateTime now) {
+ throw new NotImplementedException();
+ }
+
+
+ @Override
+ public ValidationErrors validate(OverdueConfig root,
+ ValidationErrors errors) {
+ for(DefaultOverdueState<T> state: getStates()) {
+ state.validate(root, errors);
+ }
+ try {
+ getClearState();
+ } catch (CatalogApiException e) {
+ if(e.getCode() == ErrorCode.CAT_MISSING_CLEAR_STATE.getCode()) {
+ errors.add("Overdue state set is missing a clear state.",
+ root.getURI(), this.getClass(), "");
+ }
+ }
+
+ return errors;
+ }
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/OverdueConfig.java b/overdue/src/main/java/com/ning/billing/overdue/config/OverdueConfig.java
new file mode 100644
index 0000000..1217122
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/OverdueConfig.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.config;
+
+import java.net.URI;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
+
+@XmlRootElement(name="overdueConfig")
+@XmlAccessorType(XmlAccessType.NONE)
+public class OverdueConfig extends ValidatingConfig<OverdueConfig> {
+
+ @XmlElement(required=true, name="bundleOverdueStates")
+ private OverdueStatesBundle bundleOverdueStates;
+
+ public DefaultOverdueStateSet<SubscriptionBundle> getBundleStateSet() {
+ return bundleOverdueStates;
+ }
+
+
+ @Override
+ public ValidationErrors validate(OverdueConfig root,
+ ValidationErrors errors) {
+ return bundleOverdueStates.validate(root, errors);
+ }
+
+ public OverdueConfig setOverdueStatesBundle(OverdueStatesBundle bundleODS) {
+ this.bundleOverdueStates = bundleODS;
+ return this;
+ }
+
+
+ public URI getURI() {
+ return null;
+ }
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/OverdueStatesBundle.java b/overdue/src/main/java/com/ning/billing/overdue/config/OverdueStatesBundle.java
new file mode 100644
index 0000000..50d000b
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/OverdueStatesBundle.java
@@ -0,0 +1,37 @@
+/*
+ * 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.overdue.config;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+
+public class OverdueStatesBundle extends DefaultOverdueStateSet<SubscriptionBundle>{
+
+ @XmlElement(required=true, name="state")
+ private DefaultOverdueState<SubscriptionBundle>[] bundleOverdueStates;
+
+ @Override
+ protected DefaultOverdueState<SubscriptionBundle>[] getStates() {
+ return bundleOverdueStates;
+ }
+
+ protected OverdueStatesBundle setBundleOverdueStates(DefaultOverdueState<SubscriptionBundle>[] bundleOverdueStates) {
+ this.bundleOverdueStates = bundleOverdueStates;
+ return this;
+ }
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/exceptions/OverdueError.java b/overdue/src/main/java/com/ning/billing/overdue/exceptions/OverdueError.java
new file mode 100644
index 0000000..3959408
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/exceptions/OverdueError.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.exceptions;
+
+public class OverdueError extends Error {
+
+ private static final long serialVersionUID = 131398536;
+
+ public OverdueError() {
+ super();
+ }
+
+ public OverdueError(String msg, Throwable arg1) {
+ super(msg, arg1);
+ }
+
+ public OverdueError(String msg) {
+ super(msg);
+ }
+
+ public OverdueError(Throwable msg) {
+ super(msg);
+ }
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
new file mode 100644
index 0000000..8b0b15e
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.glue;
+
+import org.skife.config.ConfigurationObjectFactory;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.ovedue.OverdueProperties;
+
+
+public class OverdueModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ final OverdueProperties config = new ConfigurationObjectFactory(System.getProperties()).build(OverdueProperties.class);
+ bind(OverdueProperties.class).toInstance(config);
+ }
+
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java b/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
new file mode 100644
index 0000000..e405fcc
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
@@ -0,0 +1,73 @@
+/*
+ * 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.overdue.service;
+
+import java.net.URI;
+
+import com.google.inject.Inject;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
+import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.overdue.OverdueUserApi;
+import com.ning.billing.overdue.config.OverdueConfig;
+import com.ning.billing.util.config.XMLLoader;
+
+public class DefaultOverdueService implements ExtendedOverdueService {
+ public static final String OVERDUE_SERVICE_NAME = "overdue-service";
+ private OverdueUserApi userApi;
+ private OverdueConfig overdueConfig;
+ private OverdueProperties properties;
+
+ private boolean isInitialized;
+
+ @Inject
+ public DefaultOverdueService(OverdueUserApi userApi, OverdueProperties properties){
+ this.userApi = userApi;
+ this.properties = properties;
+ }
+
+ @Override
+ public String getName() {
+ return OVERDUE_SERVICE_NAME;
+ }
+
+ @Override
+ public OverdueUserApi getUserApi() {
+ return userApi;
+ }
+
+ @Override
+ public OverdueConfig getOverdueConfig() {
+ return overdueConfig;
+ }
+
+ @LifecycleHandlerType(LifecycleLevel.INIT_SERVICE)
+ public synchronized void loadConfig() throws ServiceException {
+ if (!isInitialized) {
+ try {
+ System.out.println("Overdue config URI" + properties.getConfigURI());
+ URI u = new URI(properties.getConfigURI());
+ overdueConfig = XMLLoader.getObjectFromUri(u, OverdueConfig.class);
+
+ isInitialized = true;
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+ }
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/service/ExtendedOverdueService.java b/overdue/src/main/java/com/ning/billing/overdue/service/ExtendedOverdueService.java
new file mode 100644
index 0000000..abcb38a
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/service/ExtendedOverdueService.java
@@ -0,0 +1,26 @@
+/*
+ * 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.overdue.service;
+
+import com.ning.billing.overdue.OverdueService;
+import com.ning.billing.overdue.config.OverdueConfig;
+
+public interface ExtendedOverdueService extends OverdueService {
+
+ public OverdueConfig getOverdueConfig();
+
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
new file mode 100644
index 0000000..892ad05
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
@@ -0,0 +1,62 @@
+/*
+ * 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.overdue.wrapper;
+
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.overdue.applicator.OverdueStateApplicator;
+import com.ning.billing.overdue.calculator.BillingStateCalculator;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.config.api.OverdueStateSet;
+import com.ning.billing.util.clock.Clock;
+
+public class OverdueWrapper<T extends Blockable> {
+ private final T overdueable;
+ private final BlockingApi api;
+ private final Clock clock;
+ private final OverdueStateSet<T> overdueStateSet;
+ private final BillingStateCalculator<T> billingStateCalcuator;
+ private final OverdueStateApplicator<T> overdueStateApplicator;
+
+ public OverdueWrapper(T overdueable, BlockingApi api,
+ OverdueStateSet<T> overdueStateSet,
+ Clock clock,
+ BillingStateCalculator<T> billingStateCalcuator,
+ OverdueStateApplicator<T> overdueStateApplicator) {
+ this.overdueable = overdueable;
+ this.overdueStateSet = overdueStateSet;
+ this.api = api;
+ this.clock = clock;
+ this.billingStateCalcuator = billingStateCalcuator;
+ this.overdueStateApplicator = overdueStateApplicator;
+ }
+
+ public OverdueState<T> refresh() throws OverdueError, CatalogApiException {
+ OverdueState<T> nextOverdueState;
+ BillingState<T> billingState = billingStateCalcuator.calculateBillingState(overdueable);
+ String previousOverdueStateName = api.getBlockingStateFor(overdueable).getStateName();
+ nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getUTCNow());
+ if(!previousOverdueStateName.equals(nextOverdueState.getName())) {
+ overdueStateApplicator.apply(overdueable, nextOverdueState, nextOverdueState, overdueStateSet.dateOfNextCheck(billingState, clock.getUTCNow()));
+ }
+
+ return nextOverdueState;
+ }
+}
\ No newline at end of file
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
new file mode 100644
index 0000000..d542e24
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.overdue.wrapper;
+
+import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.overdue.applicator.OverdueStateApplicator;
+import com.ning.billing.overdue.calculator.BillingStateCalculatorBundle;
+import com.ning.billing.overdue.config.OverdueConfig;
+import com.ning.billing.overdue.config.api.OverdueError;
+import com.ning.billing.overdue.service.ExtendedOverdueService;
+import com.ning.billing.util.clock.Clock;
+
+public class OverdueWrapperFactory {
+
+ private final OverdueConfig overdueConfig;
+ private final BillingStateCalculatorBundle billingStateCalcuatorBundle;
+ private final OverdueStateApplicator<SubscriptionBundle> overdueStateApplicatorBundle;
+ private final BlockingApi api;
+ private final Clock clock;
+
+ @Inject
+ public OverdueWrapperFactory(BlockingApi api, ExtendedOverdueService service, Clock clock,
+ BillingStateCalculatorBundle billingStateCalcuatorBundle, OverdueStateApplicator<SubscriptionBundle> overdueStateApplicatorBundle) {
+ this.billingStateCalcuatorBundle = billingStateCalcuatorBundle;
+ this.overdueStateApplicatorBundle = overdueStateApplicatorBundle;
+ this.overdueConfig = service.getOverdueConfig();
+ this.api = api;
+ this.clock = clock;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(T bloackable) throws OverdueError {
+ if(bloackable instanceof SubscriptionBundle) {
+ return (OverdueWrapper<T>)new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle)bloackable, api, overdueConfig.getBundleStateSet(),
+ clock, billingStateCalcuatorBundle, overdueStateApplicatorBundle );
+ } else {
+ throw new OverdueError(ErrorCode.OVERDUE_TYPE_NOT_SUPPORTED, bloackable.getId(), bloackable.getClass());
+ }
+ }
+
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculator.java b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculator.java
new file mode 100644
index 0000000..db9ab74
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculator.java
@@ -0,0 +1,102 @@
+/*
+ * 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.overdue.calculator;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+
+public class TestBillingStateCalculator {
+ Clock clock = new ClockMock();
+ InvoiceUserApi invoiceApi = BrainDeadProxyFactory.createBrainDeadProxyFor(InvoiceUserApi.class);
+ private int hash = 0;
+ DateTime now;
+
+ public BillingStateCalculator<SubscriptionBundle> createBSCalc() {
+ now = new DateTime();
+ Collection<Invoice> invoices = new ArrayList<Invoice>();
+ invoices.add(createInvoice(now, BigDecimal.ZERO, null));
+ invoices.add(createInvoice(now.plusDays(1), BigDecimal.TEN, null));
+ invoices.add(createInvoice(now.plusDays(2), new BigDecimal("100.0"), null));
+
+ ((ZombieControl)invoiceApi).addResult("getUnpaidInvoicesByAccountId", invoices);
+
+ return new BillingStateCalculator<SubscriptionBundle>(invoiceApi, clock) {
+ @Override
+ public BillingState<SubscriptionBundle> calculateBillingState(
+ SubscriptionBundle overdueable) {
+ return null;
+ }};
+ }
+
+ public Invoice createInvoice(DateTime date, BigDecimal balance, List<InvoiceItem> invoiceItems) {
+ Invoice invoice = BrainDeadProxyFactory.createBrainDeadProxyFor(Invoice.class);
+ ((ZombieControl)invoice).addResult("getBalance", balance);
+ ((ZombieControl)invoice).addResult("getInvoiceDate", date);
+ ((ZombieControl)invoice).addResult("hashCode", hash++);
+ ((ZombieControl)invoice).addResult("getInvoiceItems", invoiceItems);
+
+ return invoice;
+ }
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testUnpaidInvoices() {
+ BillingStateCalculator<SubscriptionBundle> calc = createBSCalc();
+ SortedSet<Invoice> invoices = calc.unpaidInvoicesForAccount(new UUID(0L,0L));
+
+ Assert.assertEquals(invoices.size(), 3);
+ Assert.assertEquals(BigDecimal.ZERO.compareTo(invoices.first().getBalance()), 0);
+ Assert.assertEquals(new BigDecimal("100.0").compareTo(invoices.last().getBalance()), 0);
+ }
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testSum() {
+
+ BillingStateCalculator<SubscriptionBundle> calc = createBSCalc();
+ SortedSet<Invoice> invoices = calc.unpaidInvoicesForAccount(new UUID(0L,0L));
+ Assert.assertEquals(new BigDecimal("110.0").compareTo(calc.sumBalance(invoices)), 0);
+ }
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testEarliest() {
+
+ BillingStateCalculator<SubscriptionBundle> calc = createBSCalc();
+ SortedSet<Invoice> invoices = calc.unpaidInvoicesForAccount(new UUID(0L,0L));
+ Assert.assertEquals(calc.earliest(invoices), now);
+ }
+
+
+
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
new file mode 100644
index 0000000..3d5b855
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
@@ -0,0 +1,143 @@
+/*
+ * 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.overdue.calculator;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.MockPlan;
+import com.ning.billing.catalog.MockPriceList;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.overdue.config.api.BillingStateBundle;
+import com.ning.billing.overdue.config.api.PaymentResponse;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+
+public class TestBillingStateCalculatorBundle extends TestBillingStateCalculator {
+
+
+ private List<InvoiceItem> createInvoiceItems(UUID[] bundleIds) {
+ List<InvoiceItem> result = new ArrayList<InvoiceItem> ();
+ for (UUID id : bundleIds) {
+ InvoiceItem ii = BrainDeadProxyFactory.createBrainDeadProxyFor(InvoiceItem.class);
+ ((ZombieControl)ii).addResult("getBundleId", id);
+ result.add(ii);
+ }
+ return result;
+ }
+
+ @Test(groups = {"fast"}, enabled=true)
+ public void testUnpaidInvoiceForBundle() {
+ UUID thisBundleId = new UUID(0L,0L);
+ UUID thatBundleId = new UUID(0L,1L);
+
+ now = new DateTime();
+ List<Invoice> invoices = new ArrayList<Invoice>(5);
+ invoices.add(createInvoice(now, BigDecimal.ZERO, createInvoiceItems(new UUID[]{thisBundleId,thatBundleId})));
+ invoices.add(createInvoice(now, BigDecimal.TEN, createInvoiceItems(new UUID[]{thatBundleId})));
+ invoices.add(createInvoice(now, new BigDecimal("100.00"), createInvoiceItems(new UUID[]{thatBundleId,thisBundleId,thatBundleId})));
+ invoices.add(createInvoice(now, new BigDecimal("1000.00"), createInvoiceItems(new UUID[]{thisBundleId})));
+ invoices.add(createInvoice(now, new BigDecimal("10000.00"), createInvoiceItems(new UUID[]{thatBundleId, thisBundleId})));
+
+
+ Clock clock = new ClockMock();
+ InvoiceUserApi invoiceApi = BrainDeadProxyFactory.createBrainDeadProxyFor(InvoiceUserApi.class);
+ EntitlementUserApi entitlementApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+ ((ZombieControl)invoiceApi).addResult("getUnpaidInvoicesByAccountId", invoices);
+
+
+ BillingStateCalculatorBundle calc = new BillingStateCalculatorBundle(entitlementApi, invoiceApi, clock);
+ SortedSet<Invoice> resultinvoices = calc.unpaidInvoicesForBundle(thisBundleId, new UUID(0L,0L));
+
+ Assert.assertEquals(resultinvoices.size(), 4);
+ Assert.assertEquals(BigDecimal.ZERO.compareTo(resultinvoices.first().getBalance()), 0);
+ Assert.assertEquals(new BigDecimal("10000.0").compareTo(resultinvoices.last().getBalance()), 0);
+
+ }
+
+ @Test(groups = {"fast"}, enabled=true)
+ public void testcalculateBillingStateForBundle() {
+ UUID thisBundleId = new UUID(0L,0L);
+ UUID thatBundleId = new UUID(0L,1L);
+
+ now = new DateTime();
+ List<Invoice> invoices = new ArrayList<Invoice>(5);
+ invoices.add(createInvoice(now.minusDays(5), BigDecimal.ZERO, createInvoiceItems(new UUID[]{thisBundleId,thatBundleId})));
+ invoices.add(createInvoice(now.minusDays(4), BigDecimal.TEN, createInvoiceItems(new UUID[]{thatBundleId})));
+ invoices.add(createInvoice(now.minusDays(3), new BigDecimal("100.00"), createInvoiceItems(new UUID[]{thatBundleId,thisBundleId,thatBundleId})));
+ invoices.add(createInvoice(now.minusDays(2), new BigDecimal("1000.00"), createInvoiceItems(new UUID[]{thisBundleId})));
+ invoices.add(createInvoice(now.minusDays(1), new BigDecimal("10000.00"), createInvoiceItems(new UUID[]{thatBundleId, thisBundleId})));
+
+
+ Clock clock = new ClockMock();
+ InvoiceUserApi invoiceApi = BrainDeadProxyFactory.createBrainDeadProxyFor(InvoiceUserApi.class);
+ ((ZombieControl)invoiceApi).addResult("getUnpaidInvoicesByAccountId", invoices);
+
+ SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+ ((ZombieControl)bundle).addResult("getId", thisBundleId);
+ ((ZombieControl)bundle).addResult("getAccountId", UUID.randomUUID());
+
+ EntitlementUserApi entitlementApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+ Subscription subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
+ ((ZombieControl)entitlementApi).addResult("getBaseSubscription",subscription);
+
+ Plan plan = MockPlan.createBicycleNoTrialEvergreen1USD();
+ PriceList pricelist = new MockPriceList();
+ ((ZombieControl)subscription).addResult("getCurrentPlan", plan);
+ ((ZombieControl)subscription).addResult("getCurrentPriceList", pricelist);
+ ((ZombieControl)subscription).addResult("getCurrentPhase", plan.getFinalPhase());
+
+ BillingStateCalculatorBundle calc = new BillingStateCalculatorBundle(entitlementApi, invoiceApi, clock);
+
+ BillingStateBundle state = calc.calculateBillingState(bundle);
+
+ Assert.assertEquals(state.getNumberOfUnpaidInvoices(),4);
+ Assert.assertEquals(state.getBalanceOfUnpaidInvoices().intValue(), 11100);
+ Assert.assertEquals(state.getDateOfEarliestUnpaidInvoice().compareTo(now.minusDays(5)), 0);
+ Assert.assertEquals(state.getResponseForLastFailedPayment(),PaymentResponse.INSUFFICIENT_FUNDS); //TODO needs more when implemented
+ Assert.assertEquals(state.getTags().length,0);//TODO needs more when implemented
+ Assert.assertEquals(state.getBasePlanBillingPeriod(), plan.getBillingPeriod());
+ Assert.assertEquals(state.getBasePlanPhaseType(), plan.getFinalPhase().getPhaseType());
+ Assert.assertEquals(state.getBasePlanPriceList(), pricelist);
+ Assert.assertEquals(state.getBasePlanProduct(), plan.getProduct());
+
+ }
+
+
+
+
+
+
+
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/CreateOverdueConfigSchema.java b/overdue/src/test/java/com/ning/billing/overdue/config/CreateOverdueConfigSchema.java
new file mode 100644
index 0000000..bbd4b18
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/CreateOverdueConfigSchema.java
@@ -0,0 +1,43 @@
+/*
+ * 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.overdue.config;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+
+import com.ning.billing.util.config.XMLSchemaGenerator;
+
+public class CreateOverdueConfigSchema {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) throws Exception {
+ if(args.length != 1) {
+ System.err.println("Usage: <filepath>");
+ System.exit(0);
+ }
+
+ File f = new File(args[0]);
+ Writer w = new FileWriter(f);
+ w.write(XMLSchemaGenerator.xmlSchemaAsString(OverdueConfig.class));
+ w.close();
+
+ }
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/io/TestReadConfig.java b/overdue/src/test/java/com/ning/billing/overdue/config/io/TestReadConfig.java
new file mode 100644
index 0000000..8208a73
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/io/TestReadConfig.java
@@ -0,0 +1,31 @@
+/*
+ * 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.overdue.config.io;
+
+import org.testng.annotations.Test;
+
+import com.google.common.io.Resources;
+import com.ning.billing.overdue.config.OverdueConfig;
+import com.ning.billing.util.config.XMLLoader;
+
+public class TestReadConfig {
+ @Test(enabled=true)
+ public void testConfigLoad() throws Exception {
+ XMLLoader.getObjectFromString(Resources.getResource("OverdueConfig.xml").toExternalForm(), OverdueConfig.class);
+ }
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueRules.java b/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueRules.java
new file mode 100644
index 0000000..3095296
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueRules.java
@@ -0,0 +1,33 @@
+/*
+ * 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.overdue.config;
+
+
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.MockBlockingModule;
+
+
+public class MockOverdueRules extends OverdueConfig {
+
+ @SuppressWarnings("unchecked")
+ public MockOverdueRules() {
+ OverdueStatesBundle bundleODS = new OverdueStatesBundle();
+ bundleODS.setBundleOverdueStates(new DefaultOverdueState[] { new DefaultOverdueState<SubscriptionBundle>().setName(MockBlockingModule.CLEAR_STATE) });
+ setOverdueStatesBundle(bundleODS);
+
+ }
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueState.java b/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueState.java
new file mode 100644
index 0000000..606556f
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueState.java
@@ -0,0 +1,33 @@
+/*
+ * 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.overdue.config;
+
+import com.ning.billing.junction.MockBlockingModule;
+import com.ning.billing.junction.api.Blockable;
+
+public class MockOverdueState<T extends Blockable> extends DefaultOverdueState<T> {
+
+ public MockOverdueState() {
+ setName(MockBlockingModule.CLEAR_STATE);
+ }
+
+ public MockOverdueState(String name, boolean blockChanges, boolean disableEntitlementAndBlockChanges) {
+ setName(name);
+ setBlockChanges(blockChanges);
+ setDisableEntitlement(disableEntitlementAndBlockChanges);
+ }
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueStatesBundle.java b/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueStatesBundle.java
new file mode 100644
index 0000000..f1020b2
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/MockOverdueStatesBundle.java
@@ -0,0 +1,31 @@
+/*
+ * 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.overdue.config;
+
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+
+public class MockOverdueStatesBundle extends OverdueStatesBundle {
+
+ public MockOverdueStatesBundle() {
+
+ }
+
+ public MockOverdueStatesBundle(DefaultOverdueState<SubscriptionBundle>[] states) {
+ setBundleOverdueStates(states);
+ }
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/TestCondition.java b/overdue/src/test/java/com/ning/billing/overdue/config/TestCondition.java
new file mode 100644
index 0000000..1e5f1e0
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/TestCondition.java
@@ -0,0 +1,147 @@
+/*
+00 * 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.overdue.config;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.config.api.BillingState;
+import com.ning.billing.overdue.config.api.PaymentResponse;
+import com.ning.billing.util.config.XMLLoader;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.DefaultControlTag;
+import com.ning.billing.util.tag.DescriptiveTag;
+import com.ning.billing.util.tag.Tag;
+
+public class TestCondition {
+
+ @XmlRootElement(name="condition")
+ private static class MockCondition extends DefaultCondition<Blockable> {}
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testNumberOfUnpaidInvoicesEqualsOrExceeds() throws Exception {
+ String xml =
+ "<condition>" +
+ " <numberOfUnpaidInvoicesEqualsOrExceeds>1</numberOfUnpaidInvoicesEqualsOrExceeds>" +
+ "</condition>";
+ InputStream is = new ByteArrayInputStream(xml.getBytes());
+ MockCondition c = XMLLoader.getObjectFromStreamNoValidation(is, MockCondition.class);
+
+ BillingState<Blockable> state0 = new BillingState<Blockable>(new UUID(0L,1L), 0, BigDecimal.ZERO, new DateTime(), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+ BillingState<Blockable> state1 = new BillingState<Blockable>(new UUID(0L,1L), 1, BigDecimal.ZERO, new DateTime(), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+ BillingState<Blockable> state2 = new BillingState<Blockable>(new UUID(0L,1L), 2, BigDecimal.ZERO, new DateTime(), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+
+ Assert.assertTrue(!c.evaluate(state0, new DateTime()));
+ Assert.assertTrue(c.evaluate(state1, new DateTime()));
+ Assert.assertTrue(c.evaluate(state2, new DateTime()));
+ }
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testTotalUnpaidInvoiceBalanceEqualsOrExceeds() throws Exception {
+ String xml =
+ "<condition>" +
+ " <totalUnpaidInvoiceBalanceEqualsOrExceeds>100.00</totalUnpaidInvoiceBalanceEqualsOrExceeds>" +
+ "</condition>";
+ InputStream is = new ByteArrayInputStream(xml.getBytes());
+ MockCondition c = XMLLoader.getObjectFromStreamNoValidation(is, MockCondition.class);
+
+ BillingState<Blockable> state0 = new BillingState<Blockable>(new UUID(0L,1L), 0, BigDecimal.ZERO, new DateTime(), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+ BillingState<Blockable> state1 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("100.00"), new DateTime(), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+ BillingState<Blockable> state2 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("200.00"), new DateTime(), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+
+ Assert.assertTrue(!c.evaluate(state0, new DateTime()));
+ Assert.assertTrue(c.evaluate(state1, new DateTime()));
+ Assert.assertTrue(c.evaluate(state2, new DateTime()));
+ }
+
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testTimeSinceEarliestUnpaidInvoiceEqualsOrExceeds() throws Exception {
+ String xml =
+ "<condition>" +
+ " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds><unit>DAYS</unit><number>10</number></timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ "</condition>";
+ InputStream is = new ByteArrayInputStream(xml.getBytes());
+ MockCondition c = XMLLoader.getObjectFromStreamNoValidation(is, MockCondition.class);
+
+ DateTime now = new DateTime();
+
+ BillingState<Blockable> state0 = new BillingState<Blockable>(new UUID(0L,1L), 0, BigDecimal.ZERO, now, PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+ BillingState<Blockable> state1 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("100.00"), now.minusDays(10), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+ BillingState<Blockable> state2 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("200.00"), now.minusDays(20), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+
+ Assert.assertTrue(!c.evaluate(state0, now));
+ Assert.assertTrue(c.evaluate(state1, now));
+ Assert.assertTrue(c.evaluate(state2, now));
+ }
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testResponseForLastFailedPaymentIn() throws Exception {
+ String xml =
+ "<condition>" +
+ " <responseForLastFailedPaymentIn><response>INSUFFICIENT_FUNDS</response><response>DO_NOT_HONOR</response></responseForLastFailedPaymentIn>" +
+ "</condition>";
+ InputStream is = new ByteArrayInputStream(xml.getBytes());
+ MockCondition c = XMLLoader.getObjectFromStreamNoValidation(is, MockCondition.class);
+
+ DateTime now = new DateTime();
+
+ BillingState<Blockable> state0 = new BillingState<Blockable>(new UUID(0L,1L), 0, BigDecimal.ZERO, now, PaymentResponse.LOST_OR_STOLEN_CARD, new Tag[]{});
+ BillingState<Blockable> state1 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("100.00"), now.minusDays(10), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{});
+ BillingState<Blockable> state2 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("200.00"), now.minusDays(20), PaymentResponse.DO_NOT_HONOR , new Tag[]{});
+
+ Assert.assertTrue(!c.evaluate(state0, now));
+ Assert.assertTrue(c.evaluate(state1, now));
+ Assert.assertTrue(c.evaluate(state2, now));
+ }
+
+ @Test(groups={"fast"}, enabled=true)
+ public void testHasControlTag() throws Exception {
+ String xml =
+ "<condition>" +
+ " <controlTag>OVERDUE_ENFORCEMENT_OFF</controlTag>" +
+ "</condition>";
+ InputStream is = new ByteArrayInputStream(xml.getBytes());
+ MockCondition c = XMLLoader.getObjectFromStreamNoValidation(is, MockCondition.class);
+
+ DateTime now = new DateTime();
+
+ BillingState<Blockable> state0 = new BillingState<Blockable>(new UUID(0L,1L), 0, BigDecimal.ZERO, now, PaymentResponse.LOST_OR_STOLEN_CARD, new Tag[]{new DefaultControlTag(ControlTagType.AUTO_INVOICING_OFF),new DescriptiveTag("Tag")});
+ BillingState<Blockable> state1 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("100.00"), now.minusDays(10), PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{new DefaultControlTag(ControlTagType.OVERDUE_ENFORCEMENT_OFF)});
+ BillingState<Blockable> state2 = new BillingState<Blockable>(new UUID(0L,1L), 1, new BigDecimal("200.00"), now.minusDays(20),
+ PaymentResponse.DO_NOT_HONOR,
+ new Tag[]{new DefaultControlTag(ControlTagType.OVERDUE_ENFORCEMENT_OFF),
+ new DefaultControlTag(ControlTagType.AUTO_INVOICING_OFF),
+ new DescriptiveTag("Tag")});
+
+ Assert.assertTrue(!c.evaluate(state0, now));
+ Assert.assertTrue(c.evaluate(state1, now));
+ Assert.assertTrue(c.evaluate(state2, now));
+ }
+
+
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/TestOverdue.java b/overdue/src/test/java/com/ning/billing/overdue/config/TestOverdue.java
new file mode 100644
index 0000000..6d0a45d
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/TestOverdue.java
@@ -0,0 +1,21 @@
+/*
+ * 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.overdue.config;
+
+public class TestOverdue {
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckNotifier.java b/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckNotifier.java
new file mode 100644
index 0000000..a427ddb
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckNotifier.java
@@ -0,0 +1,36 @@
+/*
+ * 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.overdue.notification;
+
+import com.ning.billing.ovedue.notification.OverdueCheckNotifier;
+
+public class MockOverdueCheckNotifier implements OverdueCheckNotifier {
+ @Override
+ public void initialize() {
+ // do nothing
+ }
+
+ @Override
+ public void start() {
+ // do nothing
+ }
+
+ @Override
+ public void stop() {
+ // do nothing
+ }
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckPoster.java b/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckPoster.java
new file mode 100644
index 0000000..29d30ca
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckPoster.java
@@ -0,0 +1,33 @@
+/*
+ * 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.overdue.notification;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.ovedue.notification.OverdueCheckPoster;
+
+public class MockOverdueCheckPoster implements OverdueCheckPoster {
+
+ @Override
+ public void insertOverdueCheckNotification(Transmogrifier transactionalDao, Blockable overdueable,
+ DateTime futureNotificationTime) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
new file mode 100644
index 0000000..e98e9b1
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
@@ -0,0 +1,222 @@
+/*
+ * 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.overdue.notification;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static java.util.concurrent.TimeUnit.MINUTES;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.catalog.DefaultCatalogService;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.config.CatalogConfig;
+import com.ning.billing.config.InvoiceConfig;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.ovedue.notification.DefaultOverdueCheckNotifier;
+import com.ning.billing.ovedue.notification.DefaultOverdueCheckPoster;
+import com.ning.billing.ovedue.notification.OverdueCheckPoster;
+import com.ning.billing.ovedue.notification.OverdueListener;
+import com.ning.billing.overdue.glue.OverdueModule;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.bus.InMemoryBus;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.customfield.dao.AuditedCustomFieldDao;
+import com.ning.billing.util.customfield.dao.CustomFieldDao;
+import com.ning.billing.util.globallocker.GlobalLocker;
+import com.ning.billing.util.globallocker.MySqlGlobalLocker;
+import com.ning.billing.util.notificationq.DefaultNotificationQueueService;
+import com.ning.billing.util.notificationq.DummySqlTest;
+import com.ning.billing.util.notificationq.NotificationQueueService;
+import com.ning.billing.util.notificationq.dao.NotificationSqlDao;
+import com.ning.billing.util.tag.dao.AuditedTagDao;
+import com.ning.billing.util.tag.dao.TagDao;
+
+public class TestOverdueCheckNotifier {
+ private Clock clock;
+ private DefaultOverdueCheckNotifier notifier;
+ private DummySqlTest dao;
+ private Bus eventBus;
+ private MysqlTestingHelper helper;
+ private OverdueListenerMock listener;
+ private NotificationQueueService notificationQueueService;
+
+ private static final class OverdueListenerMock extends OverdueListener {
+ int eventCount = 0;
+ UUID latestSubscriptionId = null;
+
+ public OverdueListenerMock() {
+ super();
+ }
+
+ @Override
+ public void handleNextOverdueCheck(UUID subscriptionId, DateTime eventDateTime) {
+ eventCount++;
+ latestSubscriptionId=subscriptionId;
+ }
+
+ public int getEventCount() {
+ return eventCount;
+ }
+
+ public UUID getLatestSubscriptionId(){
+ return latestSubscriptionId;
+ }
+
+ }
+
+
+ @BeforeClass(groups={"slow"})
+ public void setup() throws ServiceException, IOException, ClassNotFoundException, SQLException {
+ //TestApiBase.loadSystemPropertiesFromClasspath("/entitlement.properties");
+ final Injector g = Guice.createInjector(Stage.PRODUCTION, new OverdueModule() {
+
+ protected void configure() {
+ super.configure();
+ bind(Clock.class).to(ClockMock.class).asEagerSingleton();
+ bind(CallContextFactory.class).to(DefaultCallContextFactory.class).asEagerSingleton();
+ bind(Bus.class).to(InMemoryBus.class).asEagerSingleton();
+ bind(NotificationQueueService.class).to(DefaultNotificationQueueService.class).asEagerSingleton();
+ final InvoiceConfig invoiceConfig = new ConfigurationObjectFactory(System.getProperties()).build(InvoiceConfig.class);
+ bind(InvoiceConfig.class).toInstance(invoiceConfig);
+ final CatalogConfig catalogConfig = new ConfigurationObjectFactory(System.getProperties()).build(CatalogConfig.class);
+ bind(CatalogConfig.class).toInstance(catalogConfig);
+ bind(CatalogService.class).to(DefaultCatalogService.class).asEagerSingleton();
+ final MysqlTestingHelper helper = new MysqlTestingHelper();
+ bind(MysqlTestingHelper.class).toInstance(helper);
+ IDBI dbi = helper.getDBI();
+ bind(IDBI.class).toInstance(dbi);
+ bind(TagDao.class).to(AuditedTagDao.class).asEagerSingleton();
+ bind(CustomFieldDao.class).to(AuditedCustomFieldDao.class).asEagerSingleton();
+ bind(GlobalLocker.class).to(MySqlGlobalLocker.class).asEagerSingleton();
+ bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
+ bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
+ bind(ChargeThruApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class));
+ bind(EntitlementUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class));
+ }
+ });
+
+ clock = g.getInstance(Clock.class);
+ IDBI dbi = g.getInstance(IDBI.class);
+ dao = dbi.onDemand(DummySqlTest.class);
+ eventBus = g.getInstance(Bus.class);
+ helper = g.getInstance(MysqlTestingHelper.class);
+ notificationQueueService = g.getInstance(NotificationQueueService.class);
+
+ OverdueProperties properties = g.getInstance(OverdueProperties.class);
+
+ Subscription subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
+ EntitlementUserApi entitlementUserApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+ ((ZombieControl) entitlementUserApi).addResult("getSubscriptionFromId", subscription);
+
+// CallContextFactory factory = new DefaultCallContextFactory(clock);
+ listener = new OverdueListenerMock();
+ notifier = new DefaultOverdueCheckNotifier(notificationQueueService,
+ properties, listener);
+
+ startMysql();
+ eventBus.start();
+ notifier.initialize();
+ notifier.start();
+
+ }
+
+ private void startMysql() throws IOException, ClassNotFoundException, SQLException {
+ final String ddl = IOUtils.toString(NotificationSqlDao.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
+ final String testDdl = IOUtils.toString(NotificationSqlDao.class.getResourceAsStream("/com/ning/billing/util/ddl_test.sql"));
+
+ helper.startMysql();
+ helper.initDb(ddl);
+ helper.initDb(testDdl);
+ }
+
+ @Test(enabled=true, groups="slow")
+ public void test() throws Exception {
+ final UUID subscriptionId = new UUID(0L,1L);
+ final Blockable blockable = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
+ ((ZombieControl)blockable).addResult("getId", subscriptionId);
+ final DateTime now = new DateTime();
+ final DateTime readyTime = now.plusMillis(2000);
+ final OverdueCheckPoster poster = new DefaultOverdueCheckPoster(notificationQueueService);
+
+
+
+ dao.inTransaction(new Transaction<Void, DummySqlTest>() {
+ @Override
+ public Void inTransaction(DummySqlTest transactional,
+ TransactionStatus status) throws Exception {
+
+ poster.insertOverdueCheckNotification(transactional, blockable, readyTime);
+ return null;
+ }
+ });
+
+
+ // Move time in the future after the notification effectiveDate
+ ((ClockMock) clock).setDeltaFromReality(3000);
+
+
+ await().atMost(1, MINUTES).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return listener.getEventCount() == 1;
+ }
+ });
+
+ Assert.assertEquals(listener.getEventCount(), 1);
+ Assert.assertEquals(listener.getLatestSubscriptionId(), subscriptionId);
+
+ }
+
+ @AfterClass(groups="slow")
+ public void tearDown() {
+ eventBus.stop();
+ notifier.stop();
+ helper.stopMysql();
+ }
+
+}
overdue/src/test/resources/log4j.xml 40(+40 -0)
diff --git a/overdue/src/test/resources/log4j.xml b/overdue/src/test/resources/log4j.xml
new file mode 100644
index 0000000..ac530a1
--- /dev/null
+++ b/overdue/src/test/resources/log4j.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%p %d{ISO8601} %X{trace} %t %c %m%n"/>
+ </layout>
+ </appender>
+
+
+ <logger name="com.ning.billing.entitlement">
+ <level value="info"/>
+ </logger>
+
+ <logger name="com.ning.billing.util.notificationq">
+ <level value="info"/>
+ </logger>
+
+ <root>
+ <priority value="info"/>
+ <appender-ref ref="stdout"/>
+ </root>
+</log4j:configuration>
overdue/src/test/resources/OverdueConfig.xml 20(+20 -0)
diff --git a/overdue/src/test/resources/OverdueConfig.xml b/overdue/src/test/resources/OverdueConfig.xml
new file mode 100644
index 0000000..e58ccc1
--- /dev/null
+++ b/overdue/src/test/resources/OverdueConfig.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ 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. -->
+
+<overdueConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="CatalogSchema.xsd ">
+ <bundleOverdueStates>
+ <state name="Clear">
+ <isClearState>true</isClearState>
+ </state>
+ </bundleOverdueStates>
+</overdueConfig>
+
+
\ No newline at end of file
overdue/src/test/resources/OverdueConfigSchema.xsd 106(+106 -0)
diff --git a/overdue/src/test/resources/OverdueConfigSchema.xsd b/overdue/src/test/resources/OverdueConfigSchema.xsd
new file mode 100644
index 0000000..256da08
--- /dev/null
+++ b/overdue/src/test/resources/OverdueConfigSchema.xsd
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
+<xs:element name="overdueConfig" type="overdueConfig"/>
+<xs:complexType name="overdueConfig">
+<xs:complexContent>
+<xs:extension base="validatingConfig">
+<xs:sequence>
+<xs:element name="bundleOverdueStates" type="overdueStatesBundle"/>
+</xs:sequence>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
+<xs:complexType abstract="true" name="validatingConfig">
+<xs:sequence/>
+</xs:complexType>
+<xs:complexType name="overdueStatesBundle">
+<xs:complexContent>
+<xs:extension base="defaultOverdueStateSet">
+<xs:sequence>
+<xs:element maxOccurs="unbounded" name="state" type="defaultOverdueState"/>
+</xs:sequence>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
+<xs:complexType abstract="true" name="defaultOverdueStateSet">
+<xs:complexContent>
+<xs:extension base="validatingConfig">
+<xs:sequence/>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
+<xs:complexType name="defaultOverdueState">
+<xs:complexContent>
+<xs:extension base="validatingConfig">
+<xs:sequence>
+<xs:element minOccurs="0" name="condition" type="defaultCondition"/>
+<xs:element minOccurs="0" name="externalMessage" type="xs:string"/>
+<xs:element minOccurs="0" name="disableEntitlementAndChangesBlocked" type="xs:boolean"/>
+<xs:element minOccurs="0" name="blockChanges" type="xs:boolean"/>
+<xs:element minOccurs="0" name="daysBetweenPaymentRetries" type="xs:int"/>
+<xs:element minOccurs="0" name="isClearState" type="xs:boolean"/>
+</xs:sequence>
+<xs:attribute name="name" type="xs:ID" use="required"/>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
+<xs:complexType name="defaultCondition">
+<xs:complexContent>
+<xs:extension base="validatingConfig">
+<xs:sequence>
+<xs:element minOccurs="0" name="numberOfUnpaidInvoicesEqualsOrExceeds" type="xs:int"/>
+<xs:element minOccurs="0" name="totalUnpaidInvoiceBalanceEqualsOrExceeds" type="xs:decimal"/>
+<xs:element minOccurs="0" name="timeSinceEarliestUnpaidInvoiceEqualsOrExceeds" type="defaultDuration"/>
+<xs:element minOccurs="0" name="responseForLastFailedPaymentIn">
+<xs:complexType>
+<xs:sequence>
+<xs:element maxOccurs="unbounded" minOccurs="0" name="response" type="paymentResponse"/>
+</xs:sequence>
+</xs:complexType>
+</xs:element>
+<xs:element minOccurs="0" name="controlTag" type="controlTagType"/>
+</xs:sequence>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
+<xs:complexType name="defaultDuration">
+<xs:complexContent>
+<xs:extension base="validatingConfig">
+<xs:sequence>
+<xs:element name="unit" type="timeUnit"/>
+<xs:element minOccurs="0" name="number" type="xs:int"/>
+</xs:sequence>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
+<xs:simpleType name="timeUnit">
+<xs:restriction base="xs:string">
+<xs:enumeration value="DAYS"/>
+<xs:enumeration value="MONTHS"/>
+<xs:enumeration value="YEARS"/>
+<xs:enumeration value="UNLIMITED"/>
+</xs:restriction>
+</xs:simpleType>
+<xs:simpleType name="paymentResponse">
+<xs:restriction base="xs:string">
+<xs:enumeration value="INVALID_CARD"/>
+<xs:enumeration value="EXPIRED_CARD"/>
+<xs:enumeration value="LOST_OR_STOLEN_CARD"/>
+<xs:enumeration value="DO_NOT_HONOR"/>
+<xs:enumeration value="INSUFFICIENT_FUNDS"/>
+<xs:enumeration value="DECLINE"/>
+<xs:enumeration value="PROCESSING_ERROR"/>
+<xs:enumeration value="INVALID_AMOUNT"/>
+<xs:enumeration value="DUPLICATE_TRANSACTION"/>
+<xs:enumeration value="OTHER"/>
+</xs:restriction>
+</xs:simpleType>
+<xs:simpleType name="controlTagType">
+<xs:restriction base="xs:string">
+<xs:enumeration value="AUTO_PAY_OFF"/>
+<xs:enumeration value="AUTO_INVOICING_OFF"/>
+<xs:enumeration value="OVERDUE_ENFORCEMENT_OFF"/>
+<xs:enumeration value="WRITTEN_OFF"/>
+</xs:restriction>
+</xs:simpleType>
+</xs:schema>
diff --git a/overdue/src/test/resources/resource.properties b/overdue/src/test/resources/resource.properties
new file mode 100644
index 0000000..d63334b
--- /dev/null
+++ b/overdue/src/test/resources/resource.properties
@@ -0,0 +1,7 @@
+killbill.catalog.uri=file:src/test/resources/catalogSample.xml
+killbill.entitlement.dao.claim.time=60000
+killbill.entitlement.dao.ready.max=1
+killbill.entitlement.engine.notifications.sleep=500
+user.timezone=UTC
+
+
payment/pom.xml 5(+5 -0)
diff --git a/payment/pom.xml b/payment/pom.xml
index d55d8d9..cb39ebf 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -37,6 +37,11 @@
<artifactId>killbill-util</artifactId>
</dependency>
<dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>provided</scope>
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestMockPaymentApi.java b/payment/src/test/java/com/ning/billing/payment/api/TestMockPaymentApi.java
index 7c005ee..833f926 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestMockPaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestMockPaymentApi.java
@@ -16,16 +16,17 @@
package com.ning.billing.payment.api;
-import com.google.inject.Inject;
-import com.ning.billing.util.clock.Clock;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
+import com.google.inject.Inject;
import com.ning.billing.account.glue.AccountModuleWithMocks;
import com.ning.billing.invoice.glue.InvoiceModuleWithMocks;
+import com.ning.billing.mock.glue.MockJunctionModule;
import com.ning.billing.payment.setup.PaymentTestModuleWithMocks;
+import com.ning.billing.util.clock.Clock;
-@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class })
+@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class, MockJunctionModule.class })
@Test(groups = "fast")
public class TestMockPaymentApi extends TestPaymentApi {
@Inject
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
index ac2b9f3..1c2a712 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
@@ -27,11 +27,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.DefaultCallContext;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.clock.Clock;
import org.apache.commons.lang.RandomStringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
@@ -49,6 +44,11 @@ import com.ning.billing.invoice.model.RecurringInvoiceItem;
import com.ning.billing.payment.TestHelper;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContext;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.entity.EntityPersistenceException;
public abstract class TestPaymentApi {
@@ -83,9 +83,11 @@ public abstract class TestPaymentApi {
final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD);
final BigDecimal amount = new BigDecimal("10.0011");
final UUID subscriptionId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
invoice.addInvoiceItem(new RecurringInvoiceItem(invoice.getId(), account.getId(),
subscriptionId,
+ bundleId,
"test plan", "test phase",
now,
now.plusMonths(1),
@@ -109,7 +111,7 @@ public abstract class TestPaymentApi {
assertNotNull(paymentAttempt);
assertNotNull(paymentAttempt.getPaymentAttemptId());
assertEquals(paymentAttempt.getInvoiceId(), invoice.getId());
- assertTrue(paymentAttempt.getAmount().compareTo(amount) == 0);
+ assertTrue(paymentAttempt.getAmount().compareTo(amount.setScale(2, RoundingMode.HALF_EVEN)) == 0);
assertEquals(paymentAttempt.getCurrency(), Currency.USD);
assertEquals(paymentAttempt.getPaymentId(), paymentInfo.getPaymentId());
DateTime nowTruncated = now.withMillisOfSecond(0).withSecondOfMinute(0);
@@ -168,7 +170,7 @@ public abstract class TestPaymentApi {
public void testCreatePaypalPaymentMethod() throws AccountApiException, EntityPersistenceException {
PaymentProviderAccount account = setupAccountWithPaypalPaymentMethod();
assertNotNull(account);
- Either<PaymentErrorEvent, List<PaymentMethodInfo>> paymentMethodsOrError = paymentApi.getPaymentMethods(account.getAccountKey());
+ paymentApi.getPaymentMethods(account.getAccountKey());
}
@Test(enabled=true)
diff --git a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
index 8faf1f3..cf56d78 100644
--- a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
+++ b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
@@ -20,8 +20,10 @@ import org.apache.commons.collections.MapUtils;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provider;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.user.DefaultAccountUserApi;
import com.ning.billing.config.PaymentConfig;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.junction.api.BillingApi;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
import com.ning.billing.util.bus.Bus;
@@ -30,10 +32,10 @@ import com.ning.billing.util.notificationq.DefaultNotificationQueueService;
import com.ning.billing.util.notificationq.NotificationQueueService;
public class PaymentTestModuleWithEmbeddedDb extends PaymentModule {
- public static class MockProvider implements Provider<EntitlementBillingApi> {
+ public static class MockProvider implements Provider<BillingApi> {
@Override
- public EntitlementBillingApi get() {
- return BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
+ public BillingApi get() {
+ return BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
}
}
@@ -51,7 +53,6 @@ public class PaymentTestModuleWithEmbeddedDb extends PaymentModule {
protected void configure() {
super.configure();
bind(Bus.class).to(InMemoryBus.class).asEagerSingleton();
- bind(EntitlementBillingApi.class).toProvider(MockProvider.class);
bind(NotificationQueueService.class).to(DefaultNotificationQueueService.class).asEagerSingleton();
}
}
diff --git a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
index b0999da..17383ee 100644
--- a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
+++ b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
@@ -20,12 +20,14 @@ import org.apache.commons.collections.MapUtils;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provider;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.user.DefaultAccountUserApi;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.MockAccountDao;
import com.ning.billing.config.PaymentConfig;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.invoice.dao.InvoiceDao;
import com.ning.billing.invoice.dao.MockInvoiceDao;
+import com.ning.billing.junction.api.BillingApi;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.payment.dao.MockPaymentDao;
import com.ning.billing.payment.dao.PaymentDao;
@@ -36,10 +38,10 @@ import com.ning.billing.util.notificationq.MockNotificationQueueService;
import com.ning.billing.util.notificationq.NotificationQueueService;
public class PaymentTestModuleWithMocks extends PaymentModule {
- public static class MockProvider implements Provider<EntitlementBillingApi> {
+ public static class MockProvider implements Provider<BillingApi> {
@Override
- public EntitlementBillingApi get() {
- return BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
+ public BillingApi get() {
+ return BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
}
}
@@ -64,11 +66,9 @@ public class PaymentTestModuleWithMocks extends PaymentModule {
protected void configure() {
super.configure();
bind(Bus.class).to(InMemoryBus.class).asEagerSingleton();
- bind(MockAccountDao.class).asEagerSingleton();
- bind(AccountDao.class).to(MockAccountDao.class);
+
bind(MockInvoiceDao.class).asEagerSingleton();
bind(InvoiceDao.class).to(MockInvoiceDao.class);
- bind(EntitlementBillingApi.class).toProvider( MockProvider.class );
bind(NotificationQueueService.class).to(MockNotificationQueueService.class).asEagerSingleton();
}
}
diff --git a/payment/src/test/java/com/ning/billing/payment/TestHelper.java b/payment/src/test/java/com/ning/billing/payment/TestHelper.java
index 6112fc2..f856de7 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestHelper.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestHelper.java
@@ -19,34 +19,35 @@ package com.ning.billing.payment;
import java.math.BigDecimal;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.CallContextFactory;
-import com.ning.billing.util.entity.EntityPersistenceException;
import org.apache.commons.lang.RandomStringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import com.google.inject.Inject;
import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.account.api.user.AccountBuilder;
-import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.dao.InvoiceDao;
import com.ning.billing.invoice.model.DefaultInvoice;
import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.entity.EntityPersistenceException;
public class TestHelper {
- protected final AccountDao accountDao;
+ protected final AccountUserApi accountUserApi;
protected final InvoiceDao invoiceDao;
private final CallContext context;
@Inject
- public TestHelper(CallContextFactory factory, AccountDao accountDao, InvoiceDao invoiceDao) {
- this.accountDao = accountDao;
+ public TestHelper(CallContextFactory factory, AccountUserApi accountUserApi, InvoiceDao invoiceDao) {
+ this.accountUserApi = accountUserApi;
this.invoiceDao = invoiceDao;
context = factory.createCallContext("Princess Buttercup", CallOrigin.TEST, UserType.TEST);
}
@@ -63,7 +64,8 @@ public class TestHelper {
.currency(Currency.USD)
.billingCycleDay(1)
.build();
- accountDao.create(account, context);
+ ((ZombieControl)accountUserApi).addResult("getAccountById", account);
+ ((ZombieControl)accountUserApi).addResult("getAccountByKey", account);
return account;
}
@@ -78,7 +80,8 @@ public class TestHelper {
.currency(Currency.USD)
.billingCycleDay(1)
.build();
- accountDao.create(account, context);
+ ((ZombieControl)accountUserApi).addResult("getAccountById", account);
+ ((ZombieControl)accountUserApi).addResult("getAccountByKey", account);
return account;
}
@@ -93,6 +96,7 @@ public class TestHelper {
RecurringInvoiceItem recurringInvoiceItem = (RecurringInvoiceItem) item;
invoice.addInvoiceItem(new RecurringInvoiceItem(invoice.getId(),
account.getId(),
+ recurringInvoiceItem.getBundleId(),
recurringInvoiceItem.getSubscriptionId(),
recurringInvoiceItem.getPlanName(),
recurringInvoiceItem.getPhaseName(),
@@ -110,10 +114,13 @@ public class TestHelper {
public Invoice createTestInvoice(Account account) {
final DateTime now = new DateTime(DateTimeZone.UTC);
final UUID subscriptionId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
final BigDecimal amount = new BigDecimal("10.00");
- final InvoiceItem item = new RecurringInvoiceItem(null, account.getId(), subscriptionId, "test plan", "test phase", now, now.plusMonths(1),
+
+ final InvoiceItem item = new RecurringInvoiceItem(null, account.getId(), bundleId, subscriptionId, "test plan", "test phase", now, now.plusMonths(1),
amount, new BigDecimal("1.0"), Currency.USD);
+
return createTestInvoice(account, now, Currency.USD, item);
}
}
diff --git a/payment/src/test/java/com/ning/billing/payment/TestNotifyInvoicePaymentApi.java b/payment/src/test/java/com/ning/billing/payment/TestNotifyInvoicePaymentApi.java
index 80bdd82..bf3fbb2 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestNotifyInvoicePaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestNotifyInvoicePaymentApi.java
@@ -20,10 +20,8 @@ import static org.testng.Assert.assertNotNull;
import java.util.UUID;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.TestCallContext;
-import com.ning.billing.util.entity.EntityPersistenceException;
import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
@@ -31,18 +29,25 @@ import org.testng.annotations.Test;
import com.google.inject.Inject;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.account.glue.AccountModuleWithMocks;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoicePayment;
import com.ning.billing.invoice.api.InvoicePaymentApi;
import com.ning.billing.invoice.glue.InvoiceModuleWithMocks;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.mock.glue.MockJunctionModule;
import com.ning.billing.payment.api.PaymentAttempt;
import com.ning.billing.payment.setup.PaymentTestModuleWithMocks;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TestCallContext;
+import com.ning.billing.util.entity.EntityPersistenceException;
@Test
-@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class })
+@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class, MockJunctionModule.class})
public class TestNotifyInvoicePaymentApi {
@Inject
private Bus eventBus;
@@ -52,9 +57,16 @@ public class TestNotifyInvoicePaymentApi {
private InvoicePaymentApi invoicePaymentApi;
@Inject
private TestHelper testHelper;
+ @Inject
+ private AccountUserApi accountApi;
private CallContext context = new TestCallContext("Payment Api Tests");
+ @BeforeClass(alwaysRun = true)
+ public void setUpClass() {
+ ((ZombieControl)accountApi).addResult("getAccountById", BrainDeadProxyFactory.ZOMBIE_VOID);
+ }
+
@BeforeMethod(alwaysRun = true)
public void setUp() throws EventBusException {
eventBus.start();
diff --git a/payment/src/test/java/com/ning/billing/payment/TestPaymentInvoiceIntegration.java b/payment/src/test/java/com/ning/billing/payment/TestPaymentInvoiceIntegration.java
index d30ec44..e2133c4 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestPaymentInvoiceIntegration.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestPaymentInvoiceIntegration.java
@@ -26,8 +26,6 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.Callable;
-import com.ning.billing.account.glue.AccountModuleWithMocks;
-import com.ning.billing.util.glue.CallContextModule;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.IDBI;
@@ -43,11 +41,11 @@ import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.ning.billing.account.api.Account;
-import com.ning.billing.account.glue.AccountModule;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoicePaymentApi;
import com.ning.billing.invoice.glue.InvoiceModuleWithMocks;
+import com.ning.billing.mock.glue.MockJunctionModule;
import com.ning.billing.payment.api.PaymentApi;
import com.ning.billing.payment.api.PaymentAttempt;
import com.ning.billing.payment.api.PaymentErrorEvent;
@@ -56,7 +54,7 @@ import com.ning.billing.payment.setup.PaymentTestModuleWithEmbeddedDb;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
import com.ning.billing.util.clock.MockClockModule;
-import com.ning.billing.util.notificationq.NotificationQueueService;
+import com.ning.billing.util.glue.CallContextModule;
public class TestPaymentInvoiceIntegration {
// create payment for received invoice and save it -- positive and negative
@@ -72,14 +70,12 @@ public class TestPaymentInvoiceIntegration {
private PaymentApi paymentApi;
@Inject
private TestHelper testHelper;
- @Inject
- private NotificationQueueService notificationQueueService;
private MockPaymentInfoReceiver paymentInfoReceiver;
private IDBI dbi;
private MysqlTestingHelper helper;
-
+
@BeforeClass(alwaysRun = true)
public void startMysql() throws IOException {
final String accountddl = IOUtils.toString(MysqlTestingHelper.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
@@ -101,11 +97,13 @@ public class TestPaymentInvoiceIntegration {
@BeforeMethod(alwaysRun = true)
public void setUp() throws EventBusException {
Injector injector = Guice.createInjector(new PaymentTestModuleWithEmbeddedDb(),
- new AccountModuleWithMocks(),
new InvoiceModuleWithMocks(),
new CallContextModule(),
new MockClockModule(),
- new AbstractModule() {
+ new MockJunctionModule(),
+ new AbstractModule()
+
+ {
@Override
protected void configure() {
bind(IDBI.class).toInstance(dbi);
diff --git a/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java b/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java
index 983fc3b..6ffeb74 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java
@@ -34,13 +34,14 @@ import com.google.inject.Inject;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.glue.AccountModuleWithMocks;
import com.ning.billing.invoice.glue.InvoiceModuleWithMocks;
+import com.ning.billing.mock.glue.MockJunctionModule;
import com.ning.billing.payment.api.PaymentErrorEvent;
import com.ning.billing.payment.api.PaymentInfoEvent;
import com.ning.billing.payment.setup.PaymentTestModuleWithMocks;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
-@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class })
+@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class, MockJunctionModule.class })
public class TestPaymentProvider {
@Inject
private Bus eventBus;
diff --git a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
index 1fe2cc4..aa9a664 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
@@ -45,6 +45,7 @@ import com.ning.billing.config.PaymentConfig;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.glue.InvoiceModuleWithMocks;
import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.mock.glue.MockJunctionModule;
import com.ning.billing.payment.api.Either;
import com.ning.billing.payment.api.PaymentApi;
import com.ning.billing.payment.api.PaymentAttempt;
@@ -62,7 +63,7 @@ import com.ning.billing.util.notificationq.MockNotificationQueue;
import com.ning.billing.util.notificationq.Notification;
import com.ning.billing.util.notificationq.NotificationQueueService;
-@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class })
+@Guice(modules = { PaymentTestModuleWithMocks.class, AccountModuleWithMocks.class, InvoiceModuleWithMocks.class, MockJunctionModule.class })
@Test(groups = "fast")
public class TestRetryService {
@Inject
@@ -116,12 +117,14 @@ public class TestRetryService {
final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCNow(), Currency.USD);
final BigDecimal amount = new BigDecimal("10.00");
final UUID subscriptionId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
final DateTime startDate = clock.getUTCNow();
final DateTime endDate = startDate.plusMonths(1);
invoice.addInvoiceItem(new RecurringInvoiceItem(invoice.getId(),
account.getId(),
subscriptionId,
+ bundleId,
"test plan", "test phase",
startDate,
endDate,
@@ -157,12 +160,14 @@ public class TestRetryService {
final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCNow(), Currency.USD);
final BigDecimal amount = new BigDecimal("10.00");
final UUID subscriptionId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
final DateTime now = clock.getUTCNow();
invoice.addInvoiceItem(new RecurringInvoiceItem(invoice.getId(),
account.getId(),
subscriptionId,
+ bundleId,
"test plan", "test phase",
now,
now.plusMonths(1),
pom.xml 17(+17 -0)
diff --git a/pom.xml b/pom.xml
index 3ab59e6..23f47f2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,6 +44,8 @@
<module>catalog</module>
<module>entitlement</module>
<module>invoice</module>
+ <module>junction</module>
+ <module>overdue</module>
<module>payment</module>
<module>util</module>
<module>jaxrs</module>
@@ -109,6 +111,18 @@
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-junction</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
<artifactId>killbill-entitlement</artifactId>
<version>${project.version}</version>
</dependency>
@@ -407,6 +421,7 @@
<exclude>**/.project</exclude>
<exclude>.git/**</exclude>
<exclude>.gitignore</exclude>
+ <exclude>**/.classpath</exclude>
<exclude>ignore/**</exclude>
<exclude>API.txt</exclude>
<exclude>RELEASE.sh</exclude>
@@ -428,6 +443,8 @@
<exclude>**/*.dont-let-git-remove-this-directory</exclude>
<exclude>**/test-output/**</exclude>
<exclude>**/bin/**</exclude>
+ <exclude>**/target/**</exclude>
+ <exclude>**/.settings/**</exclude>
<exclude>.travis.yml</exclude>
<!-- until we merge from server branch we disable rat for those -->
<exclude>jaxrs/**</exclude>
diff --git a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
index a33ac8a..2cdced0 100644
--- a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
+++ b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
@@ -16,6 +16,10 @@
package com.ning.billing.server.modules;
+import org.skife.jdbi.v2.DBI;
+import org.skife.jdbi.v2.IDBI;
+
+import com.google.inject.AbstractModule;
import com.ning.billing.account.glue.AccountModule;
import com.ning.billing.analytics.setup.AnalyticsModule;
import com.ning.billing.beatrix.glue.BeatrixModule;
@@ -38,10 +42,6 @@ import com.ning.billing.util.glue.NotificationQueueModule;
import com.ning.billing.util.glue.TagStoreModule;
import com.ning.jetty.jdbi.guice.providers.DBIProvider;
-import com.google.inject.AbstractModule;
-import org.skife.jdbi.v2.DBI;
-import org.skife.jdbi.v2.IDBI;
-
public class KillbillServerModule extends AbstractModule
{
@Override
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index a9fba1e..76eb9f7 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -61,6 +61,7 @@ import com.ning.billing.jaxrs.json.AccountJson;
import com.ning.billing.jaxrs.json.BundleJson;
import com.ning.billing.jaxrs.json.SubscriptionJson;
import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+import com.ning.billing.junction.glue.JunctionModule;
import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
import com.ning.billing.payment.setup.PaymentModule;
import com.ning.billing.server.listeners.KillbillGuiceListener;
@@ -188,6 +189,7 @@ public class TestJaxrsBase {
install(new AnalyticsModule());
install(new PaymentMockModule());
install(new BeatrixModule());
+ install(new JunctionModule());
installClock();
}
diff --git a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
index d0487b8..9d35352 100644
--- a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
+++ b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
@@ -71,6 +71,18 @@ public class XMLLoader {
return null;
}
}
+
+ public static <T> T getObjectFromStreamNoValidation(InputStream stream, Class<T> clazz) throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException {
+ Object o = unmarshaller(clazz).unmarshal(stream);
+ if (clazz.isInstance(o)) {
+ @SuppressWarnings("unchecked")
+ T castObject = (T)o;
+ return castObject;
+ } else {
+ return null;
+ }
+ }
+
public static <T extends ValidatingConfig<T>> void validate(URI uri, T c) throws ValidationException {
c.initialize(c, uri);
diff --git a/util/src/main/java/com/ning/billing/util/glue/RealImplementation.java b/util/src/main/java/com/ning/billing/util/glue/RealImplementation.java
new file mode 100644
index 0000000..773a9ea
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/RealImplementation.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.glue;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+
+import com.google.inject.BindingAnnotation;
+
+/**
+ * This annotation is used to bing classes that are being intercepted in junction.
+ *
+ * The real implementation of the class is bound in Guice with this parameter, the Blocking implementation
+ * is let unannotated.
+ *
+ */
+@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
+public @interface RealImplementation {
+
+}
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java b/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
index 3d0a8b1..bb97dd7 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
@@ -58,6 +58,9 @@ public interface NotificationSqlDao extends Transactional<NotificationSqlDao>, C
public void clearNotification(@Bind("id") long id, @Bind("owner") String owner);
@SqlUpdate
+ public void removeNotificationsByKey(@Bind("notification_key") String key);
+
+ @SqlUpdate
public void insertNotification(@Bind(binder = NotificationSqlDaoBinder.class) Notification evt);
@SqlUpdate
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
index e12b8a7..392a218 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
@@ -19,6 +19,7 @@ package com.ning.billing.util.notificationq;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.UUID;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.IDBI;
@@ -119,4 +120,10 @@ public class DefaultNotificationQueue extends NotificationQueueBase {
log.debug(String.format("Thread %d [queue = %s] %s", Thread.currentThread().getId(), getFullQName(), realDebug));
}
}
+
+ @Override
+ public void removeNotificationsByKey(UUID key) {
+ dao.removeNotificationsByKey(key.toString());
+
+ }
}
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationLifecycle.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationLifecycle.java
index 3200424..32cba9d 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationLifecycle.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationLifecycle.java
@@ -24,7 +24,8 @@ public interface NotificationLifecycle {
public enum NotificationLifecycleState {
AVAILABLE,
IN_PROCESSING,
- PROCESSED
+ PROCESSED,
+ REMOVED
}
public String getOwner();
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java
index fb88d4c..14b68e0 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java
@@ -16,6 +16,8 @@
package com.ning.billing.util.notificationq;
+import java.util.UUID;
+
import org.joda.time.DateTime;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
@@ -44,6 +46,13 @@ public interface NotificationQueue {
final DateTime futureNotificationTime, final NotificationKey notificationKey);
/**
+ * Remove all notifications associated with this key
+ *
+ * @param key
+ */
+ public void removeNotificationsByKey(UUID key);
+
+ /**
* This is only valid when the queue has been configured with isNotificationProcessingOff is true
* In which case, it will callback users for all the ready notifications.
*
@@ -71,4 +80,6 @@ public interface NotificationQueue {
*/
public String getFullQName();
+
+
}
diff --git a/util/src/main/resources/com/ning/billing/util/ddl.sql b/util/src/main/resources/com/ning/billing/util/ddl.sql
index 486a031..5ee4089 100644
--- a/util/src/main/resources/com/ning/billing/util/ddl.sql
+++ b/util/src/main/resources/com/ning/billing/util/ddl.sql
@@ -119,3 +119,5 @@ CREATE TABLE audit_log (
user_token char(36),
PRIMARY KEY(id)
) ENGINE=innodb;
+
+
diff --git a/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg
index 7a7ecab..899e828 100644
--- a/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg
@@ -16,6 +16,7 @@ getReadyNotifications(now, max) ::= <<
effective_dt \<= :now
and queue_name = :queue_name
and processing_state != 'PROCESSED'
+ and processing_state != 'REMOVED'
and (processing_owner IS NULL OR processing_available_dt \<= :now)
order by
effective_dt asc
@@ -35,6 +36,7 @@ claimNotification(owner, next_available, id, now) ::= <<
where
id = :id
and processing_state != 'PROCESSED'
+ and processing_state != 'REMOVED'
and (processing_owner IS NULL OR processing_available_dt \<= :now)
;
>>
@@ -48,6 +50,16 @@ clearNotification(id, owner) ::= <<
;
>>
+removeNotificationsByKey(notification_key) ::= <<
+ update notifications
+ set
+ processing_state = 'REMOVED'
+ where
+ notification_key = :notification_key
+ ;
+>>
+
+
insertNotification() ::= <<
insert into notifications (
notification_id
diff --git a/util/src/test/java/com/ning/billing/mock/BrainDeadProxyFactory.java b/util/src/test/java/com/ning/billing/mock/BrainDeadProxyFactory.java
index 7404331..7a3d28f 100644
--- a/util/src/test/java/com/ning/billing/mock/BrainDeadProxyFactory.java
+++ b/util/src/test/java/com/ning/billing/mock/BrainDeadProxyFactory.java
@@ -19,12 +19,15 @@ package com.ning.billing.mock;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import bsh.This;
+
public class BrainDeadProxyFactory {
private static final Logger log = LoggerFactory.getLogger(BrainDeadProxyFactory.class);
@@ -39,9 +42,12 @@ public class BrainDeadProxyFactory {
}
@SuppressWarnings("unchecked")
- public static <T> T createBrainDeadProxyFor(final Class<T> clazz) {
+ public static <T> T createBrainDeadProxyFor(final Class<T> clazz, final Class<?> ... others) {
+ Class<?>[] clazzes = Arrays.copyOf(others, others.length + 2);
+ clazzes[others.length] = ZombieControl.class;
+ clazzes[others.length + 1] = clazz;
return (T) Proxy.newProxyInstance(clazz.getClassLoader(),
- new Class[] { clazz , ZombieControl.class},
+ clazzes,
new InvocationHandler() {
private final Map<String,Object> results = new HashMap<String,Object>();
@@ -68,6 +74,8 @@ public class BrainDeadProxyFactory {
throw ((Throwable) result);
}
return result;
+ } else if (method.getName().equals("equals")){
+ return proxy == args[0];
} else {
log.error(String.format("No result for Method: '%s' on Class '%s'",method.getName(), method.getDeclaringClass().getName()));
throw new UnsupportedOperationException();
diff --git a/util/src/test/java/com/ning/billing/mock/glue/MockJunctionModule.java b/util/src/test/java/com/ning/billing/mock/glue/MockJunctionModule.java
new file mode 100644
index 0000000..2df0094
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/mock/glue/MockJunctionModule.java
@@ -0,0 +1,49 @@
+/*
+ * 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.mock.glue;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+
+public class MockJunctionModule extends AbstractModule {
+ private BillingApi billingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
+ private BlockingApi blockingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BlockingApi.class);
+ private AccountUserApi userApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+
+ @Override
+ protected void configure() {
+ installBlockingApi();
+ installAccountUserApi();
+ installBillingApi();
+ }
+
+ protected void installBillingApi() {
+ bind(BillingApi.class).toInstance(billingApi);
+ }
+
+
+ protected void installAccountUserApi() {
+ bind(AccountUserApi.class).toInstance(userApi);
+ }
+
+ protected void installBlockingApi() {
+ bind(BlockingApi.class).toInstance(blockingApi);
+ }
+}
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
index ae66819..a9cd1db 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
@@ -21,6 +21,7 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
+import java.util.UUID;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
@@ -110,4 +111,20 @@ public class MockNotificationQueue extends NotificationQueueBase implements Noti
}
return result;
}
+
+ @Override
+ public void removeNotificationsByKey(UUID key) {
+ List<Notification> toClearNotifications = new ArrayList<Notification>();
+ for (Notification notification : notifications) {
+ if (notification.getNotificationKey().equals(key.toString())) {
+ toClearNotifications.add(notification);
+ }
+ }
+ synchronized(notifications) {
+ if (toClearNotifications.size() > 0) {
+ notifications.removeAll(toClearNotifications);
+ }
+ }
+
+ }
}
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java b/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
index e2718a9..1a9654c 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
@@ -109,6 +109,7 @@ public class TestNotificationQueue {
});
// Reset time to real value
((ClockMock) clock).resetDeltaFromReality();
+ eventsReceived=0;
}
@@ -407,6 +408,82 @@ public class TestNotificationQueue {
}
};
}
+
+
+ @Test(groups="slow")
+ public void testRemoveNotifications() throws InterruptedException {
+
+ final UUID key = UUID.randomUUID();
+ final NotificationKey notificationKey = new NotificationKey() {
+ @Override
+ public String toString() {
+ return key.toString();
+ }
+ };
+ final UUID key2 = UUID.randomUUID();
+ final NotificationKey notificationKey2 = new NotificationKey() {
+ @Override
+ public String toString() {
+ return key2.toString();
+ }
+ };
+
+ final DefaultNotificationQueue queue = new DefaultNotificationQueue(dbi, clock, "test-svc", "many",
+ new NotificationQueueHandler() {
+ @Override
+ public void handleReadyNotification(String key, DateTime eventDateTime) {
+ if(key.equals(notificationKey) || key.equals(notificationKey2)) { //ig nore stray events from other tests
+ log.info("Received notification with key: " + notificationKey);
+ eventsReceived++;
+ }
+ }
+ },
+ getNotificationConfig(false, 100, 10, 10000));
+
+
+ queue.startQueue();
+
+ final DateTime start = clock.getUTCNow().plusHours(1);
+ final int nextReadyTimeIncrementMs = 1000;
+
+ // add 3 events
+
+ dao.inTransaction(new Transaction<Void, DummySqlTest>() {
+ @Override
+ public Void inTransaction(DummySqlTest transactional,
+ TransactionStatus status) throws Exception {
+
+ queue.recordFutureNotificationFromTransaction(transactional,
+ start.plus(nextReadyTimeIncrementMs), notificationKey);
+ queue.recordFutureNotificationFromTransaction(transactional,
+ start.plus(2 *nextReadyTimeIncrementMs), notificationKey);
+ queue.recordFutureNotificationFromTransaction(transactional,
+ start.plus(3 * nextReadyTimeIncrementMs), notificationKey2);
+ return null;
+ }
+ });
+
+
+ queue.removeNotificationsByKey(key); // should remove 2 of the 3
+
+ // Move time in the future after the notification effectiveDate
+ ((ClockMock) clock).setDeltaFromReality(4000000 + nextReadyTimeIncrementMs * 3 );
+
+ try {
+ await().atMost(10, TimeUnit.SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return eventsReceived >= 2;
+ }
+ });
+ Assert.fail("There should only have been only one event left in the queue we got: " + eventsReceived);
+ } catch (Exception e) {
+ // expected behavior
+ }
+ log.info("Received " + eventsReceived + " events");
+ queue.stopQueue();
+ }
+
public static class TestNotificationQueueModule extends AbstractModule {