killbill-memoizeit
Changes
account/pom.xml 2(+1 -1)
account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java 93(+93 -0)
analytics/pom.xml 2(+1 -1)
analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java 12(+6 -6)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java 6(+1 -5)
api/pom.xml 2(+1 -1)
api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.java 73(+73 -0)
api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApiException.java 41(+11 -30)
beatrix/pom.xml 2(+1 -1)
catalog/pom.xml 2(+1 -1)
entitlement/pom.xml 2(+1 -1)
entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java 209(+209 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java 8(+6 -2)
entitlement/src/main/java/com/ning/billing/entitlement/api/migration/AccountMigrationData.java 80(+80 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java 188(+188 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java 9(+4 -5)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java 32(+14 -18)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java 155(+76 -79)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java 6(+1 -5)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java 7(+3 -4)
entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java 23(+9 -14)
entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java 6(+3 -3)
entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java 101(+84 -17)
entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java 24(+13 -11)
entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg 6(+6 -0)
entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg 6(+6 -0)
entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java 371(+371 -0)
entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationMemory.java 55(+55 -0)
entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java 56(+56 -0)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java 15(+9 -6)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java 16(+9 -7)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java 22(+13 -9)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java 21(+13 -8)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java 14(+7 -7)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java 18(+11 -7)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java 19(+9 -10)
entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java 6(+3 -3)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java 78(+61 -17)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java 12(+4 -8)
invoice/pom.xml 38(+37 -1)
invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java 39(+22 -17)
invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java 64(+64 -0)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java 4(+2 -2)
invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java 4(+2 -2)
payment/pom.xml 2(+1 -1)
pom.xml 2(+1 -1)
util/pom.xml 2(+1 -1)
Details
account/pom.xml 2(+1 -1)
diff --git a/account/pom.xml b/account/pom.xml
index 6808744..2107a34 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
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
new file mode 100644
index 0000000..1c7a397
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -0,0 +1,163 @@
+/*
+ * 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 java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.customfield.CustomizableEntityBase;
+import com.ning.billing.util.tag.DefaultTag;
+import com.ning.billing.util.tag.DefaultTagStore;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDescription;
+
+public class DefaultAccount extends CustomizableEntityBase implements Account {
+ public final static String OBJECT_TYPE = "Account";
+
+ private final String externalKey;
+ private final String email;
+ private final String name;
+ private final int firstNameLength;
+ private final String phone;
+ private final Currency currency;
+ private final int billCycleDay;
+ private final String paymentProviderName;
+ private final BigDecimal balance;
+ private final DefaultTagStore tags;
+
+ public DefaultAccount(AccountData data) {
+ this(UUID.randomUUID(), data.getExternalKey(), data.getEmail(), data.getName(),
+ data.getFirstNameLength(), data.getPhone(), data.getCurrency(), data.getBillCycleDay(),
+ data.getPaymentProviderName(), BigDecimal.ZERO);
+ }
+
+ public DefaultAccount(UUID id, AccountData data) {
+ this(id, data.getExternalKey(), data.getEmail(), data.getName(),
+ data.getFirstNameLength(), data.getPhone(), data.getCurrency(), data.getBillCycleDay(),
+ data.getPaymentProviderName(), BigDecimal.ZERO);
+ }
+
+ public DefaultAccount(UUID id, String externalKey, String email, String name, int firstNameLength,
+ String phone, Currency currency, int billCycleDay, String paymentProviderName,
+ BigDecimal balance) {
+ super(id);
+ this.externalKey = externalKey;
+ this.email = email;
+ this.name = name;
+ this.firstNameLength = firstNameLength;
+ this.phone = phone;
+ this.currency = currency;
+ this.billCycleDay = billCycleDay;
+ this.paymentProviderName = paymentProviderName;
+ this.balance = balance;
+
+ this.tags = new DefaultTagStore(id, getObjectName());
+ }
+
+ @Override
+ public String getObjectName() {
+ return OBJECT_TYPE;
+ }
+
+ @Override
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getEmail() {
+ return email;
+ }
+
+ @Override
+ public int getFirstNameLength() {
+ return firstNameLength;
+ }
+
+ @Override
+ public String getPhone() {
+ return phone;
+ }
+
+ @Override
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ @Override
+ public int getBillCycleDay() {
+ return billCycleDay;
+ }
+
+ @Override
+ public String getPaymentProviderName() {
+ return paymentProviderName;
+ }
+
+ @Override
+ public List<Tag> getTagList() {
+ return tags.getEntityList();
+ }
+
+ @Override
+ public boolean hasTag(String tagName) {
+ return tags.containsTag(tagName);
+ }
+
+ @Override
+ public void addTag(TagDescription description, String addedBy, DateTime dateAdded) {
+ Tag tag = new DefaultTag(description, addedBy, dateAdded);
+ tags.add(tag) ;
+ }
+
+ @Override
+ public void addTags(List<Tag> tags) {
+ this.tags.add(tags);
+ }
+
+ @Override
+ public void clearTags() {
+ this.tags.clear();
+ }
+
+ @Override
+ public void removeTag(TagDescription description) {
+ tags.remove(description.getName());
+ }
+
+ @Override
+ public boolean generateInvoice() {
+ return tags.generateInvoice();
+ }
+
+ @Override
+ public boolean processPayment() {
+ return tags.processPayment();
+ }
+
+ @Override
+ public BigDecimal getBalance() {
+ return balance;
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java b/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java
new file mode 100644
index 0000000..c97a894
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.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.account.api;
+
+import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+
+public class DefaultChangedField implements ChangedField {
+ private final String fieldName;
+ private final String oldValue;
+ private final String newValue;
+ private final DateTime changeDate;
+
+ public DefaultChangedField(String fieldName, String oldValue, String newValue) {
+ this.changeDate = new DefaultClock().getUTCNow();
+ this.fieldName = fieldName;
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ }
+
+ @Override
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ @Override
+ public String getOldValue() {
+ return oldValue;
+ }
+
+ @Override
+ public String getNewValue() {
+ return newValue;
+ }
+
+ @Override
+ public DateTime getChangeDate() {
+ return changeDate;
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/AccountBuilder.java b/account/src/main/java/com/ning/billing/account/api/user/AccountBuilder.java
new file mode 100644
index 0000000..e05e967
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/user/AccountBuilder.java
@@ -0,0 +1,94 @@
+/*
+ * 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.user;
+
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.catalog.api.Currency;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+public class AccountBuilder {
+ private UUID id;
+ private String externalKey;
+ private String email;
+ private String name;
+ private int firstNameLength;
+ private String phone;
+ private Currency currency;
+ private int billingCycleDay;
+ private String paymentProviderName;
+ private BigDecimal balance;
+
+ public AccountBuilder() {
+ this(UUID.randomUUID());
+ }
+
+ public AccountBuilder(UUID id) {
+ this.id = id;
+ }
+
+ public AccountBuilder externalKey(String externalKey) {
+ this.externalKey = externalKey;
+ return this;
+ }
+
+ public AccountBuilder email(String email) {
+ this.email = email;
+ return this;
+ }
+
+ public AccountBuilder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public AccountBuilder firstNameLength(int firstNameLength) {
+ this.firstNameLength = firstNameLength;
+ return this;
+ }
+
+ public AccountBuilder phone(String phone) {
+ this.phone = phone;
+ return this;
+ }
+
+ public AccountBuilder billingCycleDay(int billingCycleDay) {
+ this.billingCycleDay = billingCycleDay;
+ return this;
+ }
+
+ public AccountBuilder currency(Currency currency) {
+ this.currency = currency;
+ return this;
+ }
+
+ public AccountBuilder paymentProviderName(String paymentProviderName) {
+ this.paymentProviderName = paymentProviderName;
+ return this;
+ }
+
+ public AccountBuilder balance(BigDecimal balance) {
+ this.balance = balance;
+ return this;
+ }
+
+ public DefaultAccount build() {
+ return new DefaultAccount(id, externalKey, email, name, firstNameLength,
+ phone, currency, billingCycleDay, paymentProviderName, balance);
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java
new file mode 100644
index 0000000..178100f
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.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.account.api.user;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountChangeNotification;
+import com.ning.billing.account.api.ChangedField;
+import com.ning.billing.account.api.DefaultChangedField;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class DefaultAccountChangeNotification implements AccountChangeNotification {
+ private final List<ChangedField> changedFields;
+ private final UUID id;
+
+ public DefaultAccountChangeNotification(UUID id, Account oldData, Account newData) {
+ this.id = id;
+ this.changedFields = calculateChangedFields(oldData, newData);
+ }
+
+ @Override
+ public UUID getAccountId() {
+ return id;
+ }
+
+ @Override
+ public List<ChangedField> getChangedFields() {
+ return changedFields;
+ }
+
+ @Override
+ public boolean hasChanges() {
+ return (changedFields.size() > 0);
+ }
+
+ private List<ChangedField> calculateChangedFields(Account oldData, Account newData) {
+
+ List<ChangedField> tmpChangedFields = new ArrayList<ChangedField>();
+
+ addIfValueChanged(tmpChangedFields, "externalKey",
+ oldData.getExternalKey(), newData.getExternalKey());
+
+ addIfValueChanged(tmpChangedFields, "email",
+ oldData.getEmail(), newData.getEmail());
+
+ addIfValueChanged(tmpChangedFields, "firstName",
+ oldData.getName(), newData.getName());
+
+ addIfValueChanged(tmpChangedFields, "phone",
+ oldData.getPhone(), newData.getPhone());
+
+ addIfValueChanged(tmpChangedFields, "currency",
+ (oldData.getCurrency() != null) ? oldData.getCurrency().toString() : null,
+ (newData.getCurrency() != null) ? newData.getCurrency().toString() : null);
+
+ addIfValueChanged(tmpChangedFields,
+ "billCycleDay",
+ Integer.toString(oldData.getBillCycleDay()), Integer.toString(newData.getBillCycleDay()));
+
+ addIfValueChanged(tmpChangedFields,"paymentProviderName",
+ oldData.getPaymentProviderName(), newData.getPaymentProviderName());
+ return tmpChangedFields;
+ }
+
+ private void addIfValueChanged(List<ChangedField> inputList, String key, String oldData, String newData) {
+ // If both null => no changes
+ if (newData == null && oldData == null) {
+ return;
+ // If only one is null
+ } else if (newData == null || oldData == null) {
+ inputList.add(new DefaultChangedField(key, oldData, newData));
+ // If non are null we can safely compare values
+ } else if (!newData.equals(oldData)) {
+ inputList.add(new DefaultChangedField(key, oldData, newData));
+ }
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
new file mode 100644
index 0000000..91d9b82
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.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.account.api.user;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountCreationNotification;
+import com.ning.billing.account.api.AccountData;
+
+import java.util.UUID;
+
+public class DefaultAccountCreationEvent implements AccountCreationNotification {
+ private final UUID id;
+ private final AccountData data;
+
+ public DefaultAccountCreationEvent(Account data) {
+ this.id = data.getId();
+ this.data = data;
+ }
+
+ @Override
+ public UUID getId() {
+ return id;
+ }
+
+ @Override
+ public AccountData getData() {
+ return data;
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
index 15bf60f..04b50e3 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
@@ -16,53 +16,12 @@
package com.ning.billing.account.dao;
-import com.google.inject.Inject;
-import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountData;
-import org.skife.jdbi.v2.IDBI;
-
-import java.util.List;
import java.util.UUID;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.util.entity.EntityDao;
-public class AccountDao implements IAccountDao {
-
- private final IAccountDaoSql dao;
-
- @Inject
- public AccountDao(IDBI dbi) {
- this.dao = dbi.onDemand(IAccountDaoSql.class);
- }
-
- @Override
- public IAccount createAccount(IAccountData input) {
- IAccount result = new Account().withKey(input.getKey());
- dao.insertAccount(result);
- return result;
- }
-
- @Override
- public IAccount getAccountByKey(String key) {
- return dao.getAccountByKey(key);
- }
-
- @Override
- public IAccount getAccountById(UUID uid) {
- return dao.getAccountFromId(uid.toString());
- }
-
- @Override
- public List<IAccount> getAccounts() {
- return dao.getAccounts();
- }
-
- @Override
- public void test() {
- dao.test();
- }
+public interface AccountDao extends EntityDao<Account> {
+ public Account getAccountByKey(String key);
- @Override
- public void save(IAccount account) {
- dao.insertAccount(account);
- }
+ public UUID getIdFromKey(String externalKey);
}
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
new file mode 100644
index 0000000..20eb90b
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.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.account.dao;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.user.AccountBuilder;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.UuidMapper;
+import com.ning.billing.util.entity.EntityDao;
+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.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+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.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.UUID;
+
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper({UuidMapper.class, AccountSqlDao.AccountMapper.class})
+public interface AccountSqlDao extends EntityDao<Account>, Transactional<AccountSqlDao>, Transmogrifier {
+ @SqlQuery
+ public Account getAccountByKey(@Bind("externalKey") final String key);
+
+ @SqlQuery
+ public UUID getIdFromKey(@Bind("externalKey") final String key);
+
+ @Override
+ @SqlUpdate
+ public void save(@AccountBinder Account account);
+
+ public static class AccountMapper implements ResultSetMapper<Account> {
+ @Override
+ public Account map(int index, ResultSet result, StatementContext context) throws SQLException {
+ UUID id = UUID.fromString(result.getString("id"));
+ String externalKey = result.getString("external_key");
+ String email = result.getString("email");
+ String name = result.getString("name");
+ int firstNameLength = result.getInt("first_name_length");
+ String phone = result.getString("phone");
+ int billingCycleDay = result.getInt("billing_cycle_day");
+ String currencyString = result.getString("currency");
+ Currency currency = (currencyString == null) ? null : Currency.valueOf(currencyString);
+ String paymentProviderName = result.getString("payment_provider_name");
+
+ return new AccountBuilder(id).externalKey(externalKey).email(email)
+ .name(name).firstNameLength(firstNameLength)
+ .phone(phone).currency(currency)
+ .billingCycleDay(billingCycleDay)
+ .paymentProviderName(paymentProviderName)
+ .build();
+ }
+ }
+
+ @BindingAnnotation(AccountBinder.AccountBinderFactory.class)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.PARAMETER})
+ public @interface AccountBinder {
+ public static class AccountBinderFactory implements BinderFactory {
+ public Binder build(Annotation annotation) {
+ return new Binder<AccountBinder, Account>() {
+ public void bind(SQLStatement q, AccountBinder bind, Account account) {
+ q.bind("id", account.getId().toString());
+ q.bind("externalKey", account.getExternalKey());
+ q.bind("email", account.getEmail());
+ q.bind("name", account.getName());
+ q.bind("firstNameLength", account.getFirstNameLength());
+ q.bind("phone", account.getPhone());
+ Currency currency = account.getCurrency();
+ q.bind("currency", (currency == null) ? null : currency.toString());
+ q.bind("billingCycleDay", account.getBillCycleDay());
+ q.bind("paymentProviderName", account.getPaymentProviderName());
+ }
+ };
+ }
+ }
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java b/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
new file mode 100644
index 0000000..c108bb4
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
@@ -0,0 +1,157 @@
+/*
+ * 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.dao;
+
+import java.util.List;
+import java.util.UUID;
+import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountChangeNotification;
+import com.ning.billing.account.api.AccountCreationNotification;
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.account.api.user.DefaultAccountChangeNotification;
+import com.ning.billing.account.api.user.DefaultAccountCreationEvent;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.customfield.dao.FieldStoreDao;
+import com.ning.billing.util.eventbus.EventBus;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.dao.TagStoreDao;
+
+public class DefaultAccountDao implements AccountDao {
+ private final AccountSqlDao accountDao;
+ private final EventBus eventBus;
+
+ @Inject
+ public DefaultAccountDao(IDBI dbi, EventBus eventBus) {
+ this.eventBus = eventBus;
+ this.accountDao = dbi.onDemand(AccountSqlDao.class);
+ }
+
+ @Override
+ public Account getAccountByKey(final String key) {
+ return accountDao.inTransaction(new Transaction<Account, AccountSqlDao>() {
+ @Override
+ public Account inTransaction(AccountSqlDao accountSqlDao, TransactionStatus status) throws Exception {
+ Account account = accountSqlDao.getAccountByKey(key);
+
+ if (account != null) {
+ FieldStoreDao fieldStoreDao = accountSqlDao.become(FieldStoreDao.class);
+ List<CustomField> fields = fieldStoreDao.load(account.getId().toString(), account.getObjectName());
+
+ account.clearFields();
+ if (fields != null) {
+ for (CustomField field : fields) {
+ account.setFieldValue(field.getName(), field.getValue());
+ }
+ }
+
+ TagStoreDao tagStoreDao = fieldStoreDao.become(TagStoreDao.class);
+ List<Tag> tags = tagStoreDao.load(account.getId().toString(), account.getObjectName());
+ account.clearTags();
+
+ if (tags != null) {
+ account.addTags(tags);
+ }
+ }
+
+ return account;
+ }
+ });
+ }
+
+ @Override
+ public UUID getIdFromKey(final String externalKey) {
+ return accountDao.getIdFromKey(externalKey);
+ }
+
+ @Override
+ public Account getById(final String id) {
+ return accountDao.inTransaction(new Transaction<Account, AccountSqlDao>() {
+ @Override
+ public Account inTransaction(AccountSqlDao accountSqlDao, TransactionStatus status) throws Exception {
+ Account account = accountSqlDao.getById(id);
+
+ if (account != null) {
+ FieldStoreDao fieldStoreDao = accountSqlDao.become(FieldStoreDao.class);
+ List<CustomField> fields = fieldStoreDao.load(account.getId().toString(), account.getObjectName());
+
+ account.clearFields();
+ if (fields != null) {
+ for (CustomField field : fields) {
+ account.setFieldValue(field.getName(), field.getValue());
+ }
+ }
+
+ TagStoreDao tagStoreDao = fieldStoreDao.become(TagStoreDao.class);
+ List<Tag> tags = tagStoreDao.load(account.getId().toString(), account.getObjectName());
+ account.clearTags();
+
+ if (tags != null) {
+ account.addTags(tags);
+ }
+ }
+
+ return account;
+ }
+ });
+ }
+
+ @Override
+ public List<Account> get() {
+ return accountDao.get();
+ }
+
+ @Override
+ public void test() {
+ accountDao.test();
+ }
+
+ @Override
+ public void save(final Account account) {
+ final String accountId = account.getId().toString();
+ final String objectType = DefaultAccount.OBJECT_TYPE;
+
+ accountDao.inTransaction(new Transaction<Void, AccountSqlDao>() {
+ @Override
+ public Void inTransaction(AccountSqlDao accountDao, TransactionStatus status) throws Exception {
+ Account currentAccount = accountDao.getById(accountId);
+ accountDao.save(account);
+
+ FieldStoreDao fieldStoreDao = accountDao.become(FieldStoreDao.class);
+ fieldStoreDao.save(accountId, objectType, account.getFieldList());
+
+ TagStoreDao tagStoreDao = fieldStoreDao.become(TagStoreDao.class);
+ tagStoreDao.save(accountId, objectType, account.getTagList());
+
+ if (currentAccount == null) {
+ AccountCreationNotification creationEvent = new DefaultAccountCreationEvent(account);
+ eventBus.post(creationEvent);
+ } else {
+ AccountChangeNotification changeEvent = new DefaultAccountChangeNotification(account.getId(), currentAccount, account);
+ if (changeEvent.hasChanges()) {
+ eventBus.post(changeEvent);
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+}
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 b4583ec..345e2a1 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
@@ -19,52 +19,37 @@ package com.ning.billing.account.glue;
import com.google.inject.AbstractModule;
import com.ning.billing.account.api.AccountService;
import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.account.api.IAccountService;
-import com.ning.billing.account.api.IAccountUserApi;
+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.FieldStoreDao;
-import com.ning.billing.account.dao.IAccountDao;
-import com.ning.billing.account.dao.IFieldStoreDao;
-
+import com.ning.billing.account.dao.AccountSqlDao;
+import com.ning.billing.account.dao.DefaultAccountDao;
import org.skife.config.ConfigurationObjectFactory;
public class AccountModule extends AbstractModule {
- protected void installConfig() {
- final IAccountConfig config = new ConfigurationObjectFactory(System.getProperties()).build(IAccountConfig.class);
- bind(IAccountConfig.class).toInstance(config);
- }
-
- protected void installAccountDao() {
- bind(IAccountDao.class).to(AccountDao.class).asEagerSingleton();
-// bind(IAccountDaoSql.class).to(IAccountDaoSql.class).asEagerSingleton();
- }
-
- protected void installAccountUserApi() {
- bind(IAccountUserApi.class).to(AccountUserApi.class).asEagerSingleton();
+ private void installConfig() {
+ final AccountConfig config = new ConfigurationObjectFactory(System.getProperties()).build(AccountConfig.class);
+ bind(AccountConfig.class).toInstance(config);
}
- protected void installAccountService() {
- bind(IAccountService.class).to(AccountService.class).asEagerSingleton();
+ private void installAccountDao() {
+ bind(AccountDao.class).to(DefaultAccountDao.class).asEagerSingleton();
}
- protected void installFieldStore() {
- bind(IFieldStoreDao.class).to(FieldStoreDao.class).asEagerSingleton();
+ private void installAccountUserApi() {
+ bind(AccountUserApi.class).to(DefaultAccountUserApi.class).asEagerSingleton();
}
- protected void installInjectorMagic() {
- bind(InjectorMagic.class).asEagerSingleton();
+ private void installAccountService() {
+ bind(AccountService.class).to(DefaultAccountService.class).asEagerSingleton();
}
-
@Override
protected void configure() {
installConfig();
installAccountDao();
- installAccountUserApi();
installAccountService();
- installFieldStore();
- installInjectorMagic();
+ installAccountUserApi();
}
-
}
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
new file mode 100644
index 0000000..3e0ebdd
--- /dev/null
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
@@ -0,0 +1,41 @@
+group AccountDaoSql;
+
+save() ::= <<
+ INSERT INTO accounts
+ (id, external_key, email, name, first_name_length, phone, currency, billing_cycle_day, payment_provider_name)
+ VALUES
+ (:id, :externalKey, :email, :name, :firstNameLength, :phone, :currency, :billingCycleDay, :paymentProviderName)
+ ON DUPLICATE KEY UPDATE
+ external_key = :externalKey, email = :email, name = :name, first_name_length = :firstNameLength,
+ phone = :phone, currency = :currency, payment_provider_name = :paymentProviderName;
+>>
+
+getAccountByKey() ::= <<
+ select id, external_key, email, name, first_name_length, phone, currency, billing_cycle_day, payment_provider_name
+ from accounts
+ where external_key = :externalKey;
+>>
+
+getById() ::= <<
+ select
+ a.id, a.external_key, a.email, a.name, a.first_name_length,
+ a.phone, a.currency, a.billing_cycle_day, a.payment_provider_name
+ from accounts a
+ where a.id = :id;
+>>
+
+get() ::= <<
+ select id, external_key, email, name, first_name_length, phone, currency, billing_cycle_day, payment_provider_name
+ from accounts;
+>>
+
+getIdFromKey() ::= <<
+ select id
+ from accounts
+ where external_key = :externalKey;
+>>
+
+test() ::= <<
+ select 1 from accounts;
+>>
+;
\ No newline at end of file
diff --git a/account/src/main/resources/com/ning/billing/account/ddl.sql b/account/src/main/resources/com/ning/billing/account/ddl.sql
index 92f6bd0..acca205 100644
--- a/account/src/main/resources/com/ning/billing/account/ddl.sql
+++ b/account/src/main/resources/com/ning/billing/account/ddl.sql
@@ -1,10 +1,18 @@
DROP TABLE IF EXISTS accounts;
CREATE TABLE accounts (
id char(36) NOT NULL,
- key_name varchar(128) NOT NULL,
-
+ external_key varchar(128) NULL,
+ email varchar(50) NOT NULL,
+ name varchar(100) NOT NULL,
+ first_name_length int NOT NULL,
+ phone varchar(13) DEFAULT NULL,
+ currency char(3) DEFAULT NULL,
+ billing_cycle_day int DEFAULT NULL,
+ payment_provider_name varchar(20) DEFAULT NULL,
PRIMARY KEY(id)
) ENGINE=innodb;
+CREATE UNIQUE INDEX accounts_external_key ON accounts(external_key);
+CREATE UNIQUE INDEX accounts_email ON accounts(email);
DROP TABLE IF EXISTS custom_fields;
CREATE TABLE custom_fields (
@@ -15,5 +23,31 @@ CREATE TABLE custom_fields (
field_value varchar(255) NOT NULL,
PRIMARY KEY(id)
) ENGINE=innodb;
+CREATE INDEX custom_fields_object_id_object_type ON custom_fields(object_id, object_type);
+CREATE UNIQUE INDEX custom_fields_unique ON custom_fields(object_id, object_type, field_name);
+
+DROP TABLE IF EXISTS tag_descriptions;
+CREATE TABLE tag_descriptions (
+ id char(36) NOT NULL,
+ name varchar(20) NOT NULL,
+ created_by varchar(50) NOT NULL,
+ creation_date datetime NOT NULL,
+ description varchar(200) NOT NULL,
+ generate_invoice boolean DEFAULT false,
+ process_payment boolean DEFAULT false,
+ PRIMARY KEY(id)
+) ENGINE=innodb;
+CREATE UNIQUE INDEX tag_descriptions_name ON tag_descriptions(name);
-CREATE INDEX custom_fields_object_id_object_type ON custom_fields(object_id, object_type);
\ No newline at end of file
+DROP TABLE IF EXISTS tags;
+CREATE TABLE tags (
+ id char(36) NOT NULL,
+ tag_description_id char(36) NOT NULL,
+ object_id char(36) NOT NULL,
+ object_type varchar(30) NOT NULL,
+ date_added datetime NOT NULL,
+ added_by varchar(50) NOT NULL,
+ PRIMARY KEY(id)
+) ENGINE = innodb;
+CREATE INDEX tags_by_object ON tags(object_id);
+CREATE UNIQUE INDEX tags_unique ON tags(tag_description_id, object_id);
\ No newline at end of file
diff --git a/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
new file mode 100644
index 0000000..77efe00
--- /dev/null
+++ b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
@@ -0,0 +1,69 @@
+/*
+ * 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.dao;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.account.glue.AccountModuleMock;
+import com.ning.billing.util.eventbus.DefaultEventBusService;
+import com.ning.billing.util.eventbus.EventBusService;
+import org.apache.commons.io.IOUtils;
+import org.skife.jdbi.v2.IDBI;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+
+import java.io.IOException;
+
+import static org.testng.Assert.fail;
+
+public abstract class AccountDaoTestBase {
+ protected AccountModuleMock module;
+ protected AccountDao accountDao;
+ protected IDBI dbi;
+
+ @BeforeClass(alwaysRun = true)
+ protected void setup() throws IOException {
+ // Healthcheck test to make sure MySQL is setup properly
+ try {
+ module = new AccountModuleMock();
+ final String accountDdl = IOUtils.toString(AccountSqlDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
+ final String invoiceDdl = IOUtils.toString(AccountSqlDao.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
+ module.startDb();
+ module.initDb(accountDdl);
+ module.initDb(invoiceDdl);
+
+ final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
+ dbi = injector.getInstance(IDBI.class);
+
+ accountDao = injector.getInstance(AccountDao.class);
+ accountDao.test();
+
+ EventBusService busService = injector.getInstance(EventBusService.class);
+ ((DefaultEventBusService) busService).startBus();
+ }
+ catch (Throwable t) {
+ fail(t.toString());
+ }
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void stopMysql()
+ {
+ module.stopDb();
+ }
+}
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java b/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java
new file mode 100644
index 0000000..fa84b54
--- /dev/null
+++ b/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import java.util.UUID;
+import org.testng.annotations.Test;
+import com.ning.billing.util.customfield.DefaultFieldStore;
+import com.ning.billing.util.customfield.FieldStore;
+import com.ning.billing.util.customfield.dao.FieldStoreDao;
+
+import static org.testng.Assert.assertEquals;
+
+@Test(groups={"account-dao"})
+public class TestFieldStore extends AccountDaoTestBase {
+ @Test
+ public void testFieldStore() {
+ UUID id = UUID.randomUUID();
+ String objectType = "Test widget";
+
+ FieldStore fieldStore = new DefaultFieldStore(id, objectType);
+
+ String fieldName = "TestField1";
+ String fieldValue = "Kitty Hawk";
+ fieldStore.setValue(fieldName, fieldValue);
+
+ FieldStoreDao fieldStoreDao = dbi.onDemand(FieldStoreDao.class);
+ fieldStoreDao.save(id.toString(), objectType, fieldStore.getEntityList());
+
+ fieldStore = DefaultFieldStore.create(id, objectType);
+ fieldStore.add(fieldStoreDao.load(id.toString(), objectType));
+
+ assertEquals(fieldStore.getValue(fieldName), fieldValue);
+
+ fieldValue = "Cape Canaveral";
+ fieldStore.setValue(fieldName, fieldValue);
+ assertEquals(fieldStore.getValue(fieldName), fieldValue);
+ fieldStoreDao.save(id.toString(), objectType, fieldStore.getEntityList());
+
+ fieldStore = DefaultFieldStore.create(id, objectType);
+ assertEquals(fieldStore.getValue(fieldName), null);
+ fieldStore.add(fieldStoreDao.load(id.toString(), objectType));
+
+ assertEquals(fieldStore.getValue(fieldName), fieldValue);
+ }
+}
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
index 3b4a687..7a82f98 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
@@ -16,95 +16,183 @@
package com.ning.billing.account.dao;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Stage;
-import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.glue.AccountModuleMock;
-import com.ning.billing.account.glue.InjectorMagic;
-import org.apache.commons.io.IOUtils;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import java.io.IOException;
import java.util.List;
import java.util.UUID;
-
-import static org.testng.Assert.*;
-
-@Test(groups = {"Account", "Account-DAO"})
-public class TestSimpleAccountDao {
- private IAccountDao dao;
- private InjectorMagic injectorMagic;
-
- @BeforeClass(alwaysRun = true)
- private void setup() throws IOException {
- AccountModuleMock module = new AccountModuleMock();
- final String ddl = IOUtils.toString(IAccountDaoSql.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
- module.createDb(ddl);
-
- // Healthcheck test to make sure MySQL is setup properly
- try {
- final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
-
- injectorMagic = injector.getInstance(InjectorMagic.class);
- dao = injector.getInstance(IAccountDao.class);
- dao.test();
- }
- catch (Throwable t) {
- fail(t.toString());
- }
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.util.tag.DefaultTagDescription;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDescription;
+import com.ning.billing.account.api.user.AccountBuilder;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.clock.DefaultClock;
+import com.ning.billing.util.tag.dao.TagDescriptionDao;
+import com.ning.billing.util.tag.dao.TagDescriptionDao;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = {"account-dao"})
+public class TestSimpleAccountDao extends AccountDaoTestBase {
+ private final String key = "test1234";
+ private final String firstName = "Wesley";
+ private final String email = "me@me.com";
+
+ private DefaultAccount createTestAccount() {
+ String thisKey = key + UUID.randomUUID().toString();
+ String lastName = UUID.randomUUID().toString();
+ String thisEmail = email + " " + UUID.randomUUID();
+ String name = firstName + " " + lastName;
+ String phone = "123-456-7890";
+
+ int firstNameLength = firstName.length();
+ return new AccountBuilder().externalKey(thisKey).name(name).phone(phone).firstNameLength(firstNameLength)
+ .email(thisEmail).currency(Currency.USD).build();
}
- @Test(enabled=true, groups={"Account-DAO"})
public void testBasic() {
- IAccount a = new Account().withKey("foo");
- dao.createAccount(a);
+ Account a = createTestAccount();
+ accountDao.save(a);
+ String key = a.getExternalKey();
- IAccount r = dao.getAccountByKey("foo");
+ Account r = accountDao.getAccountByKey(key);
assertNotNull(r);
- assertEquals(r.getKey(), a.getKey());
+ assertEquals(r.getExternalKey(), a.getExternalKey());
- r = dao.getAccountById(r.getId());
+ r = accountDao.getById(r.getId().toString());
assertNotNull(r);
- assertEquals(r.getKey(), a.getKey());
+ assertEquals(r.getExternalKey(), a.getExternalKey());
- List<IAccount> all = dao.getAccounts();
+ List<Account> all = accountDao.get();
assertNotNull(all);
assertTrue(all.size() >= 1);
}
@Test
public void testGetById() {
- String key = "test1234";
-
- IAccount account = Account.create().withKey(key);
+ Account account = createTestAccount();
UUID id = account.getId();
+ String key = account.getExternalKey();
+ String name = account.getName();
+ int firstNameLength = account.getFirstNameLength();
- account.save();
+ accountDao.save(account);
- account = Account.loadAccount(id);
+ account = accountDao.getById(id.toString());
assertNotNull(account);
assertEquals(account.getId(), id);
- assertEquals(account.getKey(), key);
+ assertEquals(account.getExternalKey(), key);
+ assertEquals(account.getName(), name);
+ assertEquals(account.getFirstNameLength(), firstNameLength);
+
}
@Test
public void testCustomFields() {
- String key = "test45678";
- IAccount account = Account.create().withKey(key);
-
+ Account account = createTestAccount();
String fieldName = "testField1";
String fieldValue = "testField1_value";
account.setFieldValue(fieldName, fieldValue);
- account.save();
+ accountDao.save(account);
+
+ Account thisAccount = accountDao.getAccountByKey(account.getExternalKey());
+ assertNotNull(thisAccount);
+ assertEquals(thisAccount.getExternalKey(), account.getExternalKey());
+ assertEquals(thisAccount.getFieldValue(fieldName), fieldValue);
+ }
+
+ @Test
+ public void testTags() {
+ Account account = createTestAccount();
+ TagDescription description = new DefaultTagDescription("Test Tag", "For testing only", true, true, "Test System", new DateTime());
+ TagDescriptionDao tagDescriptionDao = dbi.onDemand(TagDescriptionDao.class);
+ tagDescriptionDao.save(description);
+
+ String addedBy = "testTags()";
+ DateTime dateAdded = new DefaultClock().getUTCNow();
+ account.addTag(description, addedBy, dateAdded);
+ assertEquals(account.getTagList().size(), 1);
+ accountDao.save(account);
+
+ Account thisAccount = accountDao.getById(account.getId().toString());
+ List<Tag> tagList = thisAccount.getTagList();
+ assertEquals(tagList.size(), 1);
+ Tag tag = tagList.get(0);
+ assertEquals(tag.getName(), description.getName());
+ assertEquals(tag.getGenerateInvoice(), description.getGenerateInvoice());
+ assertEquals(tag.getProcessPayment(), description.getProcessPayment());
+ assertEquals(tag.getTagDescriptionId(), description.getId());
+ assertEquals(tag.getAddedBy(), addedBy);
+ assertEquals(tag.getDateAdded().compareTo(dateAdded), 0);
+ }
+
+ @Test
+ public void testGetIdFromKey() {
+ Account account = createTestAccount();
+ accountDao.save(account);
+
+ UUID accountId = accountDao.getIdFromKey(account.getExternalKey());
+ assertEquals(accountId, account.getId());
+ }
+
+ @Test
+ public void testUpdate() {
+ final Account account = createTestAccount();
+ accountDao.save(account);
+
+ AccountData accountData = new AccountData() {
+ @Override
+ public String getExternalKey() {
+ return account.getExternalKey();
+ }
+ @Override
+ public String getName() {
+ return "Jane Doe";
+ }
+ @Override
+ public int getFirstNameLength() {
+ return 4;
+ }
+ @Override
+ public String getEmail() {
+ return account.getEmail();
+ }
+ @Override
+ public String getPhone() {
+ return account.getPhone();
+ }
+ @Override
+ public int getBillCycleDay() {
+ return account.getBillCycleDay();
+ }
+ @Override
+ public Currency getCurrency() {
+ return account.getCurrency();
+ }
+ @Override
+ public String getPaymentProviderName() {
+ return account.getPaymentProviderName();
+ }
+ };
+
+ Account updatedAccount = new DefaultAccount(account.getId(), accountData);
+ accountDao.save(updatedAccount);
+
+ Account savedAccount = accountDao.getAccountByKey(account.getExternalKey());
+
+ assertNotNull(savedAccount);
+ assertEquals(savedAccount.getName(), updatedAccount.getName());
+ assertEquals(savedAccount.getEmail(), updatedAccount.getEmail());
+ assertEquals(savedAccount.getPhone(), updatedAccount.getPhone());
+ assertEquals(savedAccount.getPaymentProviderName(), updatedAccount.getPaymentProviderName());
+ assertEquals(savedAccount.getBillCycleDay(), updatedAccount.getBillCycleDay());
+ assertEquals(savedAccount.getFirstNameLength(), updatedAccount.getFirstNameLength());
- account = Account.loadAccount(key);
- assertNotNull(account);
- assertEquals(account.getKey(), key);
- assertEquals(account.getFieldValue(fieldName), fieldValue);
}
}
diff --git a/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java b/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java
index 7f92ad2..1123059 100644
--- a/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java
+++ b/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java
@@ -17,6 +17,7 @@
package com.ning.billing.account.glue;
import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.util.glue.EventBusModule;
import org.skife.jdbi.v2.IDBI;
import java.io.IOException;
@@ -24,14 +25,22 @@ import java.io.IOException;
public class AccountModuleMock extends AccountModule {
private final MysqlTestingHelper helper = new MysqlTestingHelper();
- public void createDb(String ddl) throws IOException {
+ public void startDb() throws IOException {
helper.startMysql();
+ }
+
+ public void initDb(String ddl) throws IOException {
helper.initDb(ddl);
}
+ public void stopDb() {
+ helper.stopMysql();
+ }
+
@Override
protected void configure() {
bind(IDBI.class).toInstance(helper.getDBI());
super.configure();
+ install(new EventBusModule());
}
}
analytics/pom.xml 2(+1 -1)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index 5bd608a..03e7d72 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-analytics</artifactId>
diff --git a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
index ba7a707..262e9d9 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
@@ -18,6 +18,8 @@ package com.ning.billing.analytics;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Inject;
+import com.ning.billing.account.api.AccountChangeNotification;
+import com.ning.billing.account.api.AccountCreationNotification;
import com.ning.billing.entitlement.api.user.SubscriptionTransition;
public class AnalyticsListener
@@ -36,9 +38,12 @@ public class AnalyticsListener
public void handleSubscriptionTransitionChange(final SubscriptionTransition event)
{
switch (event.getTransitionType()) {
+ case MIGRATE_ENTITLEMENT:
+ // TODO do nothing for now
+ break;
case CREATE:
bstRecorder.subscriptionCreated(event);
- break;
+ break;
case CANCEL:
bstRecorder.subscriptionCancelled(event);
break;
@@ -62,7 +67,18 @@ public class AnalyticsListener
}
@Subscribe
- public void handleAccountChange(final Object event)
+ public void handleAccountCreation(final AccountCreationNotification event)
{
+ bacRecorder.accountCreated(event.getData());
+ }
+
+ @Subscribe
+ public void handleAccountChange(final AccountChangeNotification event)
+ {
+ if (!event.hasChanges()) {
+ return;
+ }
+
+ bacRecorder.accountUpdated(event.getAccountId(), event.getChangedFields());
}
}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
index 7c5a6da..23fbcf4 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
@@ -17,31 +17,62 @@
package com.ning.billing.analytics;
import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.ChangedField;
import com.ning.billing.analytics.dao.BusinessAccountDao;
+import com.ning.billing.util.tag.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
public class BusinessAccountRecorder
{
private static final Logger log = LoggerFactory.getLogger(BusinessAccountRecorder.class);
private final BusinessAccountDao dao;
- private final IAccountUserApi accountApi;
+ private final AccountUserApi accountApi;
@Inject
- public BusinessAccountRecorder(final BusinessAccountDao dao, final IAccountUserApi accountApi)
+ public BusinessAccountRecorder(final BusinessAccountDao dao, final AccountUserApi accountApi)
{
this.dao = dao;
this.accountApi = accountApi;
}
- public void subscriptionCreated(final IAccount created)
+ public void accountCreated(final AccountData data)
{
+ final Account account = accountApi.getAccountByKey(data.getExternalKey());
+
+ final List<String> tags = new ArrayList<String>();
+ for (final Tag tag : account.getTagList()) {
+ tags.add(tag.getName());
+ }
+
+ // TODO Need payment and invoice api to fill most fields
+ final BusinessAccount bac = new BusinessAccount(
+ account.getExternalKey(),
+ null, // TODO
+ tags,
+ null, // TODO
+ null, // TODO
+ null, // TODO
+ null, // TODO
+ null, // TODO
+ null // TODO
+ );
+
+ log.info("ACCOUNT CREATION " + bac);
+ dao.createAccount(bac);
}
- public void subscriptionUpdated(final IAccount updated)
+ public void accountUpdated(final UUID accountId, final List<ChangedField> changedFields)
{
+ // None of the fields updated interest us so far - see DefaultAccountChangeNotification
+ // TODO We'll need notifications for tags changes eventually
}
}
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..baacad8 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
@@ -17,14 +17,7 @@
package com.ning.billing.analytics;
import com.ning.billing.analytics.utils.Rounder;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.catalog.api.TimeUnit;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.api.user.Subscription;
import org.joda.time.DateTime;
import org.slf4j.Logger;
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 e55bc8c..33b8f4d 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
@@ -17,8 +17,8 @@
package com.ning.billing.analytics;
import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDao;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
@@ -36,10 +36,10 @@ public class BusinessSubscriptionTransitionRecorder
private final BusinessSubscriptionTransitionDao dao;
private final EntitlementUserApi entitlementApi;
- private final IAccountUserApi accountApi;
+ private final AccountUserApi accountApi;
@Inject
- public BusinessSubscriptionTransitionRecorder(final BusinessSubscriptionTransitionDao dao, final EntitlementUserApi entitlementApi, final IAccountUserApi accountApi)
+ public BusinessSubscriptionTransitionRecorder(final BusinessSubscriptionTransitionDao dao, final EntitlementUserApi entitlementApi, final AccountUserApi accountApi)
{
this.dao = dao;
this.entitlementApi = entitlementApi;
@@ -93,9 +93,9 @@ public class BusinessSubscriptionTransitionRecorder
if (bundle != null) {
transitionKey = bundle.getKey();
- final IAccount account = accountApi.getAccountFromId(bundle.getAccountId());
+ final Account account = accountApi.getAccountById(bundle.getAccountId());
if (account != null) {
- accountKey = account.getKey();
+ accountKey = account.getExternalKey();
currency = account.getCurrency();
}
}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountBinder.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountBinder.java
index 6a3e218..6478536 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountBinder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountBinder.java
@@ -30,6 +30,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.sql.Types;
@BindingAnnotation(BusinessAccountBinder.BacBinderFactory.class)
@Retention(RetentionPolicy.RUNTIME)
@@ -59,7 +60,12 @@ public @interface BusinessAccountBinder
q.bind("account_key", account.getKey());
q.bind("balance", account.getRoundedBalance());
q.bind("tags", joiner.join(account.getTags()));
- q.bind("last_invoice_date", account.getLastInvoiceDate().getMillis());
+ if (account.getLastInvoiceDate() != null) {
+ q.bind("last_invoice_date", account.getLastInvoiceDate().getMillis());
+ }
+ else {
+ q.bindNull("last_invoice_date", Types.BIGINT);
+ }
q.bind("total_invoice_balance", account.getRoundedTotalInvoiceBalance());
q.bind("last_payment_status", account.getLastPaymentStatus());
q.bind("payment_method", account.getPaymentMethod());
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
index 374f296..9db1b75 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
@@ -23,11 +23,7 @@ import org.skife.jdbi.v2.sqlobject.Binder;
import org.skife.jdbi.v2.sqlobject.BinderFactory;
import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
import java.sql.Types;
@BindingAnnotation(BusinessSubscriptionTransitionBinder.BstBinderFactory.class)
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 03e102d..3c3de7e 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
@@ -22,6 +22,7 @@ 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.glue.EventBusModule;
+import com.ning.billing.util.glue.TagStoreModule;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.IDBI;
@@ -37,6 +38,7 @@ public class AnalyticsTestModule extends AnalyticsModule
install(new CatalogModule());
install(new EventBusModule());
install(new EntitlementModule());
+ install(new TagStoreModule());
// 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 d3563c6..03a27d0 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -17,8 +17,10 @@
package com.ning.billing.analytics.api;
import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountCreationNotification;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.user.DefaultAccountCreationEvent;
import com.ning.billing.analytics.AnalyticsTestModule;
import com.ning.billing.analytics.BusinessSubscription;
import com.ning.billing.analytics.BusinessSubscriptionEvent;
@@ -28,16 +30,17 @@ import com.ning.billing.analytics.MockDuration;
import com.ning.billing.analytics.MockPhase;
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.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.Product;
-import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
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.entitlement.api.user.SubscriptionTransition;
@@ -45,6 +48,8 @@ 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.util.eventbus.EventBus;
+import com.ning.billing.util.tag.DefaultTagDescription;
+import com.ning.billing.util.tag.dao.TagDescriptionDao;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
@@ -63,21 +68,29 @@ public class TestAnalyticsService
{
private static final String KEY = "1234";
private static final String ACCOUNT_KEY = "pierre-1234";
+ private static final DefaultTagDescription TAG_ONE = new DefaultTagDescription("batch20", "something", false, false, "pierre", new DateTime(DateTimeZone.UTC));
+ private static final DefaultTagDescription TAG_TWO = new DefaultTagDescription("awesome", "something", false, false, "pierre", new DateTime(DateTimeZone.UTC));
@Inject
- private IAccountUserApi accountApi;
+ private AccountUserApi accountApi;
@Inject
private EntitlementUserApi entitlementApi;
@Inject
+ private TagDescriptionDao tagDao;
+
+ @Inject
private AnalyticsService service;
@Inject
private EventBus bus;
@Inject
- private BusinessSubscriptionTransitionDao dao;
+ private BusinessSubscriptionTransitionDao subscriptionDao;
+
+ @Inject
+ private BusinessAccountDao accountDao;
@Inject
private MysqlTestingHelper helper;
@@ -85,11 +98,33 @@ public class TestAnalyticsService
private SubscriptionTransition transition;
private BusinessSubscriptionTransition expectedTransition;
+ private AccountCreationNotification accountCreationNotification;
+
@BeforeClass(alwaysRun = true)
public void startMysql() throws IOException, ClassNotFoundException, SQLException, EntitlementUserApiException
{
+ // Killbill generic setup
+ setupBusAndMySQL();
+
+ tagDao.save(TAG_ONE);
+ tagDao.save(TAG_TWO);
+
+ final MockAccount account = new MockAccount(UUID.randomUUID(), ACCOUNT_KEY, Currency.USD);
+ final Account storedAccount = accountApi.createAccount(account);
+ storedAccount.addTag(TAG_ONE, "pierre", new DateTime(DateTimeZone.UTC));
+ storedAccount.addTag(TAG_TWO, "pierre", new DateTime(DateTimeZone.UTC));
+ accountApi.saveAccount(storedAccount);
+
+ // Create events for the bus and expected results
+ createSubscriptionTransitionEvent(storedAccount);
+ createAccountCreationEvent(storedAccount);
+ }
+
+ private void setupBusAndMySQL() throws IOException
+ {
+ bus.start();
+
final String analyticsDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/analytics/ddl.sql"));
- // For bundles
final String accountDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
final String entitlementDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/entitlement/ddl.sql"));
@@ -97,24 +132,25 @@ public class TestAnalyticsService
helper.initDb(analyticsDdl);
helper.initDb(accountDdl);
helper.initDb(entitlementDdl);
+ }
- // We need a bundle to retrieve the event key
- final MockAccount account = new MockAccount(UUID.randomUUID(), ACCOUNT_KEY, Currency.USD);
- final IAccount storedAccount = accountApi.createAccount(account);
- final SubscriptionBundle bundle = entitlementApi.createBundleForAccount(storedAccount, KEY);
+ private void createSubscriptionTransitionEvent(final Account account) throws EntitlementUserApiException
+ {
+ final SubscriptionBundle bundle = entitlementApi.createBundleForAccount(account.getId(), KEY);
// Verify we correctly initialized the account subsystem
Assert.assertNotNull(bundle);
Assert.assertEquals(bundle.getKey(), KEY);
- // Create a subscription transition
- final Product product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
+ // Create a subscription transition event
+ final Product product = new MockProduct("platinum", "subscription", ProductCategory.BASE);
final Plan plan = new MockPlan("platinum-monthly", product);
final PlanPhase phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
final UUID subscriptionId = UUID.randomUUID();
final DateTime effectiveTransitionTime = new DateTime(DateTimeZone.UTC);
final DateTime requestedTransitionTime = new DateTime(DateTimeZone.UTC);
final String priceList = "something";
+
transition = new SubscriptionTransitionData(
UUID.randomUUID(),
subscriptionId,
@@ -138,10 +174,15 @@ public class TestAnalyticsService
requestedTransitionTime,
BusinessSubscriptionEvent.subscriptionCreated(plan),
null,
- new BusinessSubscription(priceList, plan, phase, null, effectiveTransitionTime, Subscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
+ new BusinessSubscription(priceList, plan, phase, Currency.USD, effectiveTransitionTime, Subscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
);
}
+ private void createAccountCreationEvent(final Account account)
+ {
+ accountCreationNotification = new DefaultAccountCreationEvent(account);
+ }
+
@AfterClass(alwaysRun = true)
public void stopMysql()
{
@@ -156,18 +197,24 @@ public class TestAnalyticsService
// Test the bus and make sure we can register our service
try {
- bus.start();
service.registerForNotifications();
}
catch (Throwable t) {
Assert.fail("Unable to start the bus or service! " + t);
}
- // Send an event to the bus and make sure our Dao got it
+ // Send events and wait for the async part...
bus.post(transition);
+ bus.post(accountCreationNotification);
Thread.sleep(1000);
- Assert.assertEquals(dao.getTransitions(KEY).size(), 1);
- Assert.assertEquals(dao.getTransitions(KEY).get(0), expectedTransition);
+
+ Assert.assertEquals(subscriptionDao.getTransitions(KEY).size(), 1);
+ Assert.assertEquals(subscriptionDao.getTransitions(KEY).get(0), expectedTransition);
+
+ Assert.assertEquals(accountDao.getAccount(ACCOUNT_KEY).getKey(), ACCOUNT_KEY);
+ Assert.assertEquals(accountDao.getAccount(ACCOUNT_KEY).getTags().size(), 2);
+ Assert.assertTrue(accountDao.getAccount(ACCOUNT_KEY).getTags().indexOf(TAG_ONE.getName()) != -1);
+ Assert.assertTrue(accountDao.getAccount(ACCOUNT_KEY).getTags().indexOf(TAG_TWO.getName()) != -1);
// Test the shutdown sequence
try {
diff --git a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
index 267c2bb..368b8c1 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
@@ -16,21 +16,9 @@
package com.ning.billing.analytics.dao;
-import com.ning.billing.analytics.BusinessAccount;
-import com.ning.billing.analytics.BusinessSubscription;
-import com.ning.billing.analytics.BusinessSubscriptionEvent;
-import com.ning.billing.analytics.BusinessSubscriptionTransition;
-import com.ning.billing.analytics.MockDuration;
-import com.ning.billing.analytics.MockPhase;
-import com.ning.billing.analytics.MockPlan;
-import com.ning.billing.analytics.MockProduct;
+import com.ning.billing.analytics.*;
import com.ning.billing.analytics.utils.Rounder;
-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.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.api.user.Subscription;
import org.apache.commons.io.IOUtils;
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 f22f7b9..faf4dc8 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
@@ -16,12 +16,20 @@
package com.ning.billing.analytics;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.catalog.api.Currency;
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
+import java.math.BigDecimal;
+import java.util.List;
import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDescription;
-public class MockAccount implements IAccount
+public class MockAccount implements Account
{
private final UUID id;
private final String accountKey;
@@ -35,33 +43,37 @@ public class MockAccount implements IAccount
}
@Override
- public String getName()
- {
- throw new UnsupportedOperationException();
+ public int getFirstNameLength() {
+ return 0;
}
@Override
public String getEmail()
{
- throw new UnsupportedOperationException();
+ return "test@test.com";
}
@Override
public String getPhone()
{
- throw new UnsupportedOperationException();
+ return "408-555-6665";
}
@Override
- public String getKey()
+ public String getExternalKey()
{
return accountKey;
}
@Override
+ public String getName() {
+ return "firstName lastName";
+ }
+
+ @Override
public int getBillCycleDay()
{
- throw new UnsupportedOperationException();
+ return 12;
}
@Override
@@ -71,32 +83,83 @@ public class MockAccount implements IAccount
}
@Override
+ public String getPaymentProviderName() {
+ return "PayPal";
+ }
+
+ @Override
public UUID getId()
{
return id;
}
@Override
- public void load()
- {
- throw new UnsupportedOperationException();
+ public String getFieldValue(String fieldName) {
+ throw new NotImplementedException();
}
@Override
- public void save()
- {
- throw new UnsupportedOperationException();
+ public void setFieldValue(String fieldName, String fieldValue) {
+ throw new NotImplementedException();
}
@Override
- public String getFieldValue(final String fieldName)
- {
- throw new UnsupportedOperationException();
+ public List<CustomField> getFieldList() {
+ throw new NotImplementedException();
}
@Override
- public void setFieldValue(final String fieldName, final String fieldValue)
- {
- throw new UnsupportedOperationException();
+ public void clearFields() {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public String getObjectName() {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public List<Tag> getTagList() {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public boolean hasTag(String tagName) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void addTag(TagDescription description, String addedBy, DateTime dateAdded) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void addTags(List<Tag> tags) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void clearTags() {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void removeTag(TagDescription description) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public boolean generateInvoice() {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public boolean processPayment() {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public BigDecimal getBalance() {
+ return BigDecimal.ZERO;
}
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
index ccd67af..4c39456 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
@@ -16,44 +16,58 @@
package com.ning.billing.analytics;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountData;
-import com.ning.billing.account.api.IAccountUserApi;
-import com.ning.billing.catalog.api.Currency;
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.util.List;
import java.util.UUID;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.catalog.api.Currency;
-public class MockIAccountUserApi implements IAccountUserApi
+public class MockIAccountUserApi implements AccountUserApi
{
- private final MockAccount account;
+ private final AccountData account;
+ private final UUID id;
public MockIAccountUserApi(final String accountKey, final Currency currency)
{
- account = new MockAccount(UUID.randomUUID(), accountKey, currency);
+ this.id = UUID.randomUUID();
+ account = new MockAccount(id, accountKey, currency);
}
@Override
- public IAccount createAccount(final IAccountData data)
+ public Account createAccount(final AccountData data)
{
throw new UnsupportedOperationException();
}
@Override
- public IAccount getAccountByKey(final String key)
+ public void saveAccount(Account account) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public Account getAccountByKey(final String key)
{
throw new UnsupportedOperationException();
}
@Override
- public IAccount getAccountFromId(final UUID uid)
+ public Account getAccountById(final UUID uid)
{
- return account;
+ return new DefaultAccount(account);
}
@Override
- public List<IAccount> getAccounts()
+ public List<Account> getAccounts()
{
throw new UnsupportedOperationException();
}
+
+ @Override
+ public UUID getIdFromKey(String externalKey) {
+ return id;
+ }
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
index 1fd1022..12b6f77 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
@@ -16,19 +16,20 @@
package com.ning.billing.analytics;
-import com.ning.billing.account.api.IAccount;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.account.api.AccountData;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+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 org.joda.time.DateTime;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
public class MockIEntitlementUserApi implements EntitlementUserApi
{
@@ -94,7 +95,7 @@ public class MockIEntitlementUserApi implements EntitlementUserApi
}
@Override
- public SubscriptionBundle createBundleForAccount(final IAccount account, final String bundleKey) throws EntitlementUserApiException
+ public SubscriptionBundle createBundleForAccount(final UUID accountId, final String bundleKey) throws EntitlementUserApiException
{
throw new UnsupportedOperationException();
}
@@ -105,9 +106,13 @@ public class MockIEntitlementUserApi implements EntitlementUserApi
}
@Override
- public Subscription createSubscription(UUID bundleId, String productName,
- BillingPeriod term, String priceList, PhaseType initialPhase,
+ public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec,
DateTime requestedDate) throws EntitlementUserApiException {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException();
}
+
+ @Override
+ public SubscriptionBundle getBundleForKey(String bundleKey) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
index af8e993..7eb9b44 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
@@ -16,14 +16,7 @@
package com.ning.billing.analytics;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.InternationalPrice;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Price;
-import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.*;
import java.math.BigDecimal;
import java.util.Date;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
index 73b47ee..0e0809c 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
@@ -16,12 +16,10 @@
package com.ning.billing.analytics;
-import com.ning.billing.catalog.api.BillingAlignment;
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.Product;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
import java.util.Iterator;
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 c8485f9..6420325 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -22,7 +22,6 @@ import com.ning.billing.catalog.api.PlanPhase;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionTransition;
-
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
@@ -130,7 +129,12 @@ public class MockSubscription implements Subscription
}
@Override
+
public List<SubscriptionTransition> getAllTransitions() {
throw new UnsupportedOperationException();
+ }
+
+ public SubscriptionTransition getPendingTransition() {
+ 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 819f46b..7bad790 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -16,12 +16,7 @@
package com.ning.billing.analytics;
-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.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
import com.ning.billing.entitlement.events.EntitlementEvent;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
index 73e7811..6c38854 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
@@ -16,12 +16,7 @@
package com.ning.billing.analytics;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.api.user.Subscription;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java
index 72574dd..5ea1950 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java
@@ -16,11 +16,7 @@
package com.ning.billing.analytics;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.api.user.Subscription;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
index 5b7e3fe..592d20d 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
@@ -16,11 +16,7 @@
package com.ning.billing.analytics;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.api.user.Subscription;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index 7f7f108..a998c67 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/account/api/ChangedField.java b/api/src/main/java/com/ning/billing/account/api/ChangedField.java
new file mode 100644
index 0000000..8bf2ef1
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/ChangedField.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.account.api;
+
+import org.joda.time.DateTime;
+
+public interface ChangedField {
+ public DateTime getChangeDate();
+ public String getFieldName();
+ public String getOldValue();
+ public String getNewValue();
+}
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 f360eec..0fe2e25 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
@@ -47,7 +47,7 @@ public interface Catalog {
public abstract void configureEffectiveDate(Date date);
- public abstract String getCalalogName();
+ public abstract String getCatalogName();
public abstract PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier) throws CatalogApiException;
diff --git a/api/src/main/java/com/ning/billing/catalog/api/Currency.java b/api/src/main/java/com/ning/billing/catalog/api/Currency.java
index 029616a..0e7cd7d 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/Currency.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/Currency.java
@@ -26,10 +26,12 @@ public enum Currency {
BRL,
EUR,
AUD,
- USD
-
+ USD;
// Unsupported
// CAD,
// JPY
+ public Currency getDefaultCurrency() {
+ return Currency.USD;
+ }
}
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 b7da39b..4d603e1 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
@@ -71,7 +71,7 @@ public interface BillingEvent extends Comparable<BillingEvent> {
*
* @return the billing mode for the current event
*/
- public BillingMode getBillingMode();
+ public BillingModeType getBillingMode();
/**
*
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
index fbc130a..9311235 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
@@ -36,7 +36,7 @@ public class DefaultBillingEvent implements BillingEvent {
final private InternationalPrice fixedPrice;
final private InternationalPrice recurringPrice;
final private String description;
- final private BillingMode billingMode;
+ final private BillingModeType billingModeType;
final private BillingPeriod billingPeriod;
public DefaultBillingEvent(SubscriptionTransition transition, int billCycleDay) {
@@ -48,14 +48,14 @@ public class DefaultBillingEvent implements BillingEvent {
fixedPrice = transition.getNextPhase().getFixedPrice();
recurringPrice = transition.getNextPhase().getRecurringPrice();
description = transition.getTransitionType().toString();
- billingMode=BillingMode.IN_ADVANCE;
+ billingModeType=BillingModeType.IN_ADVANCE;
billingPeriod = transition.getNextPhase().getBillingPeriod();
}
// Intended for test only
public DefaultBillingEvent(UUID subscriptionId, DateTime effectiveDate, String planName, String planPhaseName, InternationalPrice fixedPrice,
- InternationalPrice recurringPrice, BillingPeriod billingPeriod, int billCycleDay, BillingMode billingMode, String description) {
+ InternationalPrice recurringPrice, BillingPeriod billingPeriod, int billCycleDay, BillingModeType billingModeType, String description) {
this.subscriptionId = subscriptionId;
this.effectiveDate = effectiveDate;
this.planName = planName;
@@ -64,7 +64,7 @@ public class DefaultBillingEvent implements BillingEvent {
this.recurringPrice = recurringPrice;
this.billingPeriod = billingPeriod;
this.billCycleDay = billCycleDay;
- this.billingMode = billingMode;
+ this.billingModeType = billingModeType;
this.description = description;
}
@@ -124,8 +124,8 @@ public class DefaultBillingEvent implements BillingEvent {
}
@Override
- public BillingMode getBillingMode() {
- return billingMode;
+ public BillingModeType getBillingMode() {
+ return billingModeType;
}
@Override
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
index 4fed5ff..f9b2234 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
@@ -16,17 +16,28 @@
package com.ning.billing.entitlement.api.billing;
+import java.util.List;
import java.util.SortedSet;
import java.util.UUID;
import org.joda.time.DateTime;
+import com.ning.billing.account.api.Account;
+
public interface EntitlementBillingApi {
/**
*
* @param accountId
* @return an ordered list of billing events for the given account
+ * @return the list of accounts which have active subscriptions
+ */
+ public List<Account> getActiveAccounts();
+
+ /**
+ *
+ * @param subscriptionId the subscriptionId of interest for a gievn account
+ * @return an ordered list of billing event
*
*/
public SortedSet<BillingEvent> getBillingEventsForSubscription(UUID accountId);
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 b325d6b..53854d1 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
@@ -17,13 +17,13 @@
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.test.EntitlementTestApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.lifecycle.KillbillService;
public interface EntitlementService extends KillbillService {
-
@Override
public String getName();
@@ -33,5 +33,5 @@ public interface EntitlementService extends KillbillService {
public EntitlementTestApi getTestApi();
-
+ public EntitlementMigrationApi getMigrationApi();
}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.java b/api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.java
new file mode 100644
index 0000000..9498c6f
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/entitlement/api/migration/EntitlementMigrationApi.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.entitlement.api.migration;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public interface EntitlementMigrationApi {
+
+
+ public interface EntitlementAccountMigration {
+ public UUID getAccountKey();
+ public EntitlementBundleMigration [] getBundles();
+ }
+
+ public interface EntitlementBundleMigration {
+ public String getBundleKey();
+ public EntitlementSubscriptionMigration [] getSubscriptions();
+ }
+
+ public interface EntitlementSubscriptionMigration {
+ public ProductCategory getCategory();
+ public EntitlementSubscriptionMigrationCase [] getSubscriptionCases();
+ }
+
+ /**
+ *
+ * Each case is either a PHASE or a different PlanSpecifer
+ */
+ public interface EntitlementSubscriptionMigrationCase {
+ public PlanPhaseSpecifier getPlanPhaseSpecifer();
+ public DateTime getEffectiveDate();
+ public DateTime getCancelledDate();
+ }
+
+
+ /**
+ * Migrate all the existing entitlements associated with that account.
+ * The semantics is 'all or nothing' (atomic operation)
+ *
+ * @param toBeMigrated all the bundles and associated subscription that should be migrated for the account
+ *
+ */
+ public void migrate(EntitlementAccountMigration toBeMigrated)
+ throws EntitlementMigrationApiException;
+
+ /**
+ * Remove all the data pertaining to that acount
+ *
+ * @param accountKey
+ */
+ public void undoMigration(UUID accountKey)
+ throws EntitlementMigrationApiException;
+
+}
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 fc4425a..22b9830 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
@@ -18,12 +18,8 @@ package com.ning.billing.entitlement.api.user;
import java.util.List;
import java.util.UUID;
-
import org.joda.time.DateTime;
-
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
public interface EntitlementUserApi {
@@ -32,16 +28,18 @@ public interface EntitlementUserApi {
public Subscription getSubscriptionFromId(UUID id);
+ public SubscriptionBundle getBundleForKey(String bundleKey);
+
public List<SubscriptionBundle> getBundlesForAccount(UUID accountId);
public List<Subscription> getSubscriptionsForBundle(UUID bundleId);
public List<Subscription> getSubscriptionsForKey(String bundleKey);
- public SubscriptionBundle createBundleForAccount(IAccount account, String bundleKey)
+ public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleKey)
throws EntitlementUserApiException;
-
- public Subscription createSubscription(UUID bundleId, String productName, BillingPeriod term, String priceList, PhaseType initialPhase, DateTime requestedDate)
+ public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec, DateTime requestedDate)
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 6db08fb..d19de5f 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,14 +16,13 @@
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 org.joda.time.DateTime;
+
+import java.util.List;
+import java.util.UUID;
public interface Subscription {
@@ -70,4 +69,6 @@ public interface Subscription {
public List<SubscriptionTransition> getAllTransitions();
+ public SubscriptionTransition getPendingTransition();
+
}
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 a6ecd91..f7c2e84 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,9 @@
package com.ning.billing.entitlement.api.user;
-import java.util.UUID;
-
import org.joda.time.DateTime;
-import com.ning.billing.catalog.api.BillingPeriod;
+import java.util.UUID;
public interface SubscriptionBundle {
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
index 00e478f..26ce81f 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.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.user.Subscription.SubscriptionState;
import com.ning.billing.util.eventbus.EventBusNotification;
+import org.joda.time.DateTime;
+
+import java.util.UUID;
public interface SubscriptionTransition extends EventBusNotification {
public enum SubscriptionTransitionType {
+ MIGRATE_ENTITLEMENT,
CREATE,
CHANGE,
PAUSE,
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 8fc3df4..8336ddb 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -33,7 +33,7 @@ public enum ErrorCode {
/* Creation */
ENT_CREATE_BAD_PHASE(1011, "Can't create plan initial phase %s"),
- ENT_CREATE_NO_BUNDLE(1012, "Bundle %s does not exists"),
+ ENT_CREATE_NO_BUNDLE(1012, "Bundle %s does not exist"),
ENT_CREATE_NO_BP(1013, "Missing Base Subscription for bundle %s"),
ENT_CREATE_BP_EXISTS(1015, "Subscription bundle %s already has a base subscription"),
/* Change plan */
diff --git a/api/src/main/java/com/ning/billing/invoice/api/Invoice.java b/api/src/main/java/com/ning/billing/invoice/api/Invoice.java
new file mode 100644
index 0000000..f69b934
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/Invoice.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.ning.billing.util.entity.Entity;
+import com.ning.billing.catalog.api.Currency;
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+public interface Invoice extends Entity {
+ boolean add(InvoiceItem item);
+
+ boolean add(List<InvoiceItem> items);
+
+ List<InvoiceItem> getItems();
+
+ int getNumberOfItems();
+
+ UUID getAccountId();
+
+ DateTime getInvoiceDate();
+
+ DateTime getTargetDate();
+
+ Currency getCurrency();
+
+ DateTime getLastPaymentAttempt();
+
+ BigDecimal getAmountPaid();
+
+ BigDecimal getTotalAmount();
+
+ BigDecimal getAmountOutstanding();
+
+ boolean isDueForPayment(DateTime targetDate, int numberOfDays);
+}
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceCreationNotification.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceCreationNotification.java
new file mode 100644
index 0000000..89c0d87
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceCreationNotification.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.invoice.api;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.eventbus.EventBusNotification;
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+public interface InvoiceCreationNotification extends EventBusNotification {
+ public UUID getInvoiceId();
+ public UUID getAccountId();
+ public BigDecimal getAmountOwed();
+ public Currency getCurrency();
+ public DateTime getInvoiceCreationDate();
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..44c46a7
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.entity.Entity;
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+public interface InvoiceItem extends Entity, Comparable<InvoiceItem> {
+ UUID getInvoiceId();
+
+ UUID getSubscriptionId();
+
+ DateTime getStartDate();
+
+ DateTime getEndDate();
+
+ String getDescription();
+
+ BigDecimal getAmount();
+
+ BigDecimal getRate();
+
+ Currency getCurrency();
+
+ InvoiceItem asCredit(UUID invoiceId);
+
+ int compareTo(InvoiceItem invoiceItem);
+
+ void subtract(InvoiceItem that);
+
+ boolean duplicates(InvoiceItem that);
+
+ boolean cancels(InvoiceItem that);
+}
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java b/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java
new file mode 100644
index 0000000..bde12a9
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.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.invoice.api;
+
+import com.ning.billing.catalog.api.Currency;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+import org.joda.time.DateTime;
+
+public interface InvoicePaymentApi {
+ public void paymentSuccessful(UUID invoiceId, BigDecimal amount, Currency currency, UUID paymentId, DateTime paymentAttemptDate);
+
+ public void paymentFailed(UUID invoiceId, UUID paymentId, DateTime paymentAttemptDate);
+
+ public List<Invoice> getInvoicesByAccount(UUID accountId);
+
+ public Invoice getInvoice(UUID invoiceId);
+}
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
new file mode 100644
index 0000000..7109223
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceService.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+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/invoice/api/InvoiceUserApi.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
new file mode 100644
index 0000000..2c8d02e
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.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.invoice.api;
+
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+import com.ning.billing.catalog.api.Currency;
+
+public interface InvoiceUserApi {
+ public List<UUID> getInvoicesForPayment(DateTime targetDate, int numberOfDays);
+
+ public List<Invoice> getInvoicesByAccount(UUID accountId);
+
+ public Invoice getInvoice(UUID invoiceId);
+
+ public void paymentAttemptFailed(UUID invoiceId, UUID paymentId, DateTime paymentAttemptDate);
+
+ public void paymentAttemptSuccessful(UUID invoiceId, BigDecimal amount, Currency currency,
+ UUID paymentId, DateTime paymentDate);
+}
diff --git a/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java b/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java
index 105842b..759cc13 100644
--- a/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java
+++ b/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java
@@ -16,14 +16,14 @@
package com.ning.billing.lifecycle;
+import com.google.common.collect.Lists;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
-import com.google.common.collect.Lists;
-
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LifecycleHandlerType {
diff --git a/api/src/main/java/com/ning/billing/util/customfield/CustomizableEntity.java b/api/src/main/java/com/ning/billing/util/customfield/CustomizableEntity.java
new file mode 100644
index 0000000..7b8f37a
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/customfield/CustomizableEntity.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.util.customfield;
+
+import java.util.List;
+import com.ning.billing.util.entity.Entity;
+
+public interface CustomizableEntity extends Entity {
+ public String getFieldValue(String fieldName);
+
+ public void setFieldValue(String fieldName, String fieldValue);
+
+ public List<CustomField> getFieldList();
+
+ public void clearFields();
+
+ public String getObjectName();
+}
diff --git a/api/src/main/java/com/ning/billing/util/customfield/FieldStore.java b/api/src/main/java/com/ning/billing/util/customfield/FieldStore.java
new file mode 100644
index 0000000..c2dd73f
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/customfield/FieldStore.java
@@ -0,0 +1,25 @@
+/*
+ * 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.customfield;
+
+import com.ning.billing.util.entity.EntityCollection;
+
+public interface FieldStore extends EntityCollection<CustomField> {
+ public void setValue(String fieldName, String fieldValue);
+
+ public String getValue(String fieldName);
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/util/entity/EntityCollection.java b/api/src/main/java/com/ning/billing/util/entity/EntityCollection.java
new file mode 100644
index 0000000..c9df896
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/entity/EntityCollection.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.util.entity;
+
+import java.util.List;
+
+public interface EntityCollection<T extends Entity> {
+ public String getEntityKey(T entity);
+
+ public void clear();
+
+ public void add(T entity);
+
+ public void add(List<T> entities);
+
+ public void remove(T entity);
+
+ public List<T> getEntityList();
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java b/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java
index 1985465..0bddb7e 100644
--- a/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java
+++ b/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java
@@ -16,8 +16,8 @@
package com.ning.billing.util.eventbus;
-import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import com.google.common.eventbus.Subscribe;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
/**
diff --git a/api/src/main/java/com/ning/billing/util/tag/Tag.java b/api/src/main/java/com/ning/billing/util/tag/Tag.java
new file mode 100644
index 0000000..9fb15ed
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/tag/Tag.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.util.tag;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.util.entity.Entity;
+
+public interface Tag extends Entity {
+ UUID getTagDescriptionId();
+
+ String getName();
+
+ boolean getProcessPayment();
+
+ boolean getGenerateInvoice();
+
+ String getAddedBy();
+
+ DateTime getDateAdded();
+}
diff --git a/api/src/main/java/com/ning/billing/util/tag/TagDescription.java b/api/src/main/java/com/ning/billing/util/tag/TagDescription.java
new file mode 100644
index 0000000..1edb1a3
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/tag/TagDescription.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.util.tag;
+
+import org.joda.time.DateTime;
+import com.ning.billing.util.entity.Entity;
+
+public interface TagDescription extends Entity {
+ String getName();
+
+ String getCreatedBy();
+
+ DateTime getCreationDate();
+
+ String getDescription();
+
+ boolean getGenerateInvoice();
+
+ boolean getProcessPayment();
+}
diff --git a/api/src/main/java/com/ning/billing/util/tag/Taggable.java b/api/src/main/java/com/ning/billing/util/tag/Taggable.java
new file mode 100644
index 0000000..f274294
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/tag/Taggable.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.util.tag;
+
+import java.util.List;
+import org.joda.time.DateTime;
+
+public interface Taggable {
+ public List<Tag> getTagList();
+ public boolean hasTag(String tagName);
+ public void addTag(TagDescription description, String addedBy, DateTime dateAdded);
+ public void addTags(List<Tag> tags);
+ public void clearTags();
+ public void removeTag(TagDescription description);
+ public boolean generateInvoice();
+ public boolean processPayment();
+}
diff --git a/api/src/main/java/com/ning/billing/util/tag/TagStore.java b/api/src/main/java/com/ning/billing/util/tag/TagStore.java
new file mode 100644
index 0000000..705e203
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/tag/TagStore.java
@@ -0,0 +1,29 @@
+/*
+ * 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.tag;
+
+import com.ning.billing.util.entity.EntityCollection;
+
+public interface TagStore extends EntityCollection<Tag> {
+ public boolean processPayment();
+
+ public boolean generateInvoice();
+
+ public void remove(String tagName);
+
+ public boolean containsTag(String tagName);
+}
beatrix/pom.xml 2(+1 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index b211a46..ec79685 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-beatrix</artifactId>
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
index 253e693..c0edf2c 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
@@ -16,18 +16,6 @@
package com.ning.billing.beatrix.lifecycle;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
@@ -39,6 +27,13 @@ import com.ning.billing.lifecycle.KillbillService;
import com.ning.billing.lifecycle.LifecycleHandlerType;
import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel.Sequence;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
public class Lifecycle {
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
index b5fca46..a4a4ce2 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
@@ -17,28 +17,17 @@
package com.ning.billing.beatrix.lifecycle;
+import com.ning.billing.lifecycle.KillbillService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.File;
import java.io.IOException;
-import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
import java.util.jar.JarFile;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.ning.billing.lifecycle.KillbillService;
-
public class ServiceFinder {
private static final Logger log = LoggerFactory.getLogger(ServiceFinder.class);
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java b/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
index a01220e..69e6a0d 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
@@ -16,21 +16,16 @@
package com.ning.billing.beatrix.lifecycle;
+import com.google.inject.*;
+import com.ning.billing.lifecycle.KillbillService;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Stage;
-import com.ning.billing.lifecycle.KillbillService;
-import com.ning.billing.lifecycle.LifecycleHandlerType;
-import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-
public class TestLifecycle {
catalog/pom.xml 2(+1 -1)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index bf50441..8d5c9c1 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
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 37d66f3..813ed2b 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
@@ -25,7 +25,6 @@ import com.ning.billing.config.CatalogConfig;
import com.ning.billing.lifecycle.KillbillService;
import com.ning.billing.lifecycle.LifecycleHandlerType;
import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-import com.ning.billing.util.config.XMLLoader;
public class DefaultCatalogService implements KillbillService, Provider<Catalog>, CatalogService {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
index 16897bc..be3ea55 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
@@ -16,15 +16,15 @@
package com.ning.billing.catalog;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
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;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> implements Duration {
@XmlElement(required=true)
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
index deca8b6..b53dcd3 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
@@ -16,24 +16,19 @@
package com.ning.billing.catalog;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Date;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.CurrencyValueNull;
-import com.ning.billing.catalog.api.InternationalPrice;
-import com.ning.billing.catalog.api.Price;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Date;
+
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalog> implements InternationalPrice {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
index 11154df..3620162 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
@@ -16,18 +16,6 @@
package com.ning.billing.catalog;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlID;
-import javax.xml.bind.annotation.XmlIDREF;
-
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
@@ -35,6 +23,11 @@ import com.ning.billing.catalog.api.Product;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.*;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements Plan {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
index e12b90f..e086bfe 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
@@ -16,22 +16,16 @@
package com.ning.billing.catalog;
-import java.net.URI;
+import com.ning.billing.catalog.api.*;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
+import com.ning.billing.util.config.ValidationErrors;
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 com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.InternationalPrice;
-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.util.config.ValidatingConfig;
-import com.ning.billing.util.config.ValidationError;
-import com.ning.billing.util.config.ValidationErrors;
+import java.net.URI;
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implements PlanPhase {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java
index 2021913..d9d26a6 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java
@@ -16,18 +16,17 @@
package com.ning.billing.catalog;
-import java.math.BigDecimal;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.CurrencyValueNull;
import com.ning.billing.catalog.api.Price;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import java.math.BigDecimal;
+
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements Price {
@XmlElement(required=true)
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 785d173..04916ba 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
@@ -16,14 +16,6 @@
package com.ning.billing.catalog;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlID;
-import javax.xml.bind.annotation.XmlIDREF;
-
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
@@ -31,6 +23,8 @@ import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.*;
+
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implements PriceList {
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 fc86268..b876fa9 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
@@ -16,10 +16,6 @@
package com.ning.billing.catalog;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.Product;
@@ -27,6 +23,10 @@ import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> {
@XmlElement(required=true, name="defaultPriceList")
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 500a4b0..79520ce 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
@@ -16,21 +16,14 @@
package com.ning.billing.catalog;
-import java.net.URI;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlID;
-import javax.xml.bind.annotation.XmlIDREF;
-
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.*;
+import java.net.URI;
+
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implements Product {
private static final DefaultProduct[] EMPTY_PRODUCT_LIST = new DefaultProduct[0];
@@ -107,7 +100,7 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
@Override
public void initialize(StandaloneCatalog catalog, URI sourceURI) {
- catalogName = catalog.getCalalogName();
+ catalogName = catalog.getCatalogName();
}
@Override
diff --git a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
index 4b182ef..8702b6f 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
@@ -16,14 +16,13 @@
package com.ning.billing.catalog.glue;
-import org.skife.config.ConfigurationObjectFactory;
-
import com.google.inject.AbstractModule;
import com.ning.billing.catalog.DefaultCatalogService;
import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.io.ICatalogLoader;
import com.ning.billing.catalog.io.VersionedCatalogLoader;
import com.ning.billing.config.CatalogConfig;
+import org.skife.config.ConfigurationObjectFactory;
public class CatalogModule extends AbstractModule {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
index b383647..4ad78df 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
@@ -16,13 +16,6 @@
package com.ning.billing.catalog.io;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
import com.google.inject.Inject;
import com.ning.billing.catalog.StandaloneCatalog;
import com.ning.billing.catalog.VersionedCatalog;
@@ -31,6 +24,13 @@ import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.config.UriAccessor;
import com.ning.billing.util.config.XMLLoader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
public class VersionedCatalogLoader implements ICatalogLoader {
private static final Object PROTOCOL_FOR_FILE = "file";
private final String XML_EXTENSION = ".xml";
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
index 72b6567..f667e17 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
@@ -16,13 +16,13 @@
package com.ning.billing.catalog;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-
import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
@XmlAccessorType(XmlAccessType.NONE)
public class PriceListDefault extends DefaultPriceList {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java b/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
index 8ef2cb2..00bc275 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
@@ -16,9 +16,10 @@
package com.ning.billing.catalog.rules;
-import com.ning.billing.catalog.StandaloneCatalog;
+
import com.ning.billing.catalog.DefaultPriceList;
import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.StandaloneCatalog;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.catalog.api.PlanSpecifier;
@@ -28,12 +29,15 @@ import com.ning.billing.util.config.ValidationErrors;
public abstract class Case<T> extends ValidatingConfig<StandaloneCatalog> {
- protected DefaultProduct product;
- protected ProductCategory productCategory;
- protected BillingPeriod billingPeriod;
- protected DefaultPriceList priceList;
-
protected abstract T getResult();
+
+ public abstract DefaultProduct getProduct();
+
+ public abstract ProductCategory getProductCategory();
+
+ public abstract BillingPeriod getBillingPeriod();
+
+ public abstract DefaultPriceList getPriceList();
public T getResult(PlanSpecifier planPhase, StandaloneCatalog c) throws CatalogApiException {
if (satisfiesCase(planPhase, c) ) {
@@ -43,10 +47,10 @@ public abstract class Case<T> extends ValidatingConfig<StandaloneCatalog> {
}
protected boolean satisfiesCase(PlanSpecifier planPhase, StandaloneCatalog c) throws CatalogApiException {
- return (product == null || product.equals(c.findProduct(planPhase.getProductName()))) &&
- (productCategory == null || productCategory.equals(planPhase.getProductCategory())) &&
- (billingPeriod == null || billingPeriod.equals(planPhase.getBillingPeriod())) &&
- (priceList == null || priceList.equals(c.getPriceListFromName(planPhase.getPriceListName())));
+ return (getProduct() == null || getProduct().equals(c.findProduct(planPhase.getProductName()))) &&
+ (getProductCategory() == null || getProductCategory().equals(planPhase.getProductCategory())) &&
+ (getBillingPeriod() == null || getBillingPeriod().equals(planPhase.getBillingPeriod())) &&
+ (getPriceList() == null || getPriceList().equals(c.getPriceListFromName(planPhase.getPriceListName())));
}
public static <K> K getResult(Case<K>[] cases, PlanSpecifier planSpec, StandaloneCatalog catalog) throws CatalogApiException {
@@ -67,26 +71,11 @@ public abstract class Case<T> extends ValidatingConfig<StandaloneCatalog> {
return errors;
}
- protected Case<T> setProduct(DefaultProduct product) {
- this.product = product;
- return this;
- }
+ protected abstract Case<T> setProduct(DefaultProduct product);
- protected Case<T> setProductCategory(ProductCategory productCategory) {
- this.productCategory = productCategory;
- return this;
- }
+ protected abstract Case<T> setProductCategory(ProductCategory productCategory);
- protected Case<T> setBillingPeriod(BillingPeriod billingPeriod) {
- this.billingPeriod = billingPeriod;
- return this;
- }
+ protected abstract Case<T> setBillingPeriod(BillingPeriod billingPeriod);
- protected Case<T> setPriceList(DefaultPriceList priceList) {
- this.priceList = priceList;
- return this;
- }
-
-
-
+ protected abstract Case<T> setPriceList(DefaultPriceList priceList);
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
index 0c22d00..a340fdc 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
@@ -16,23 +16,18 @@
package com.ning.billing.catalog.rules;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlIDREF;
-
-import com.ning.billing.catalog.StandaloneCatalog;
import com.ning.billing.catalog.DefaultPriceList;
import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
@XmlAccessorType(XmlAccessType.NONE)
public abstract class CaseChange<T> extends ValidatingConfig<StandaloneCatalog> {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
index fe46942..b38c1f8 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
@@ -16,27 +16,23 @@
package com.ning.billing.catalog.rules;
-import javax.xml.bind.annotation.XmlElement;
-
import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.XmlElement;
+
public abstract class CasePhase<T> extends CaseStandardNaming<T> {
@XmlElement(required=false)
private PhaseType phaseType;
public T getResult(PlanPhaseSpecifier specifier, StandaloneCatalog c) throws CatalogApiException {
- if (
- (phaseType == null || specifier.getPhaseType() == null || specifier.getPhaseType() == phaseType) &&
+ if ((phaseType == null ||
+ specifier.getPhaseType() == null || specifier.getPhaseType() == phaseType) &&
satisfiesCase(new PlanSpecifier(specifier), c)
) {
return getResult();
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
index 5508c96..5063131 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
@@ -16,46 +16,75 @@
package com.ning.billing.catalog.rules;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlIDREF;
-
import com.ning.billing.catalog.DefaultPriceList;
import com.ning.billing.catalog.DefaultProduct;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.ProductCategory;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
public class CasePriceList extends Case<DefaultPriceList> {
+ @XmlElement(required=false, name="fromProduct")
+ @XmlIDREF
+ private DefaultProduct fromProduct;
+
+ @XmlElement(required=false, name="fromProductCategory")
+ private ProductCategory fromProductCategory;
+
+ @XmlElement(required=false, name="fromBillingPeriod")
+ private BillingPeriod fromBillingPeriod;
+
+ @XmlElement(required=false, name="fromPriceList")
+ @XmlIDREF
+ private DefaultPriceList fromPriceList;
- private DefaultPriceList toPriceList;
+ @XmlElement(required=true, name="toPriceList")
+ @XmlIDREF
+ private DefaultPriceList toPriceList;
- @XmlElement(required=false, name="fromProduct")
- @XmlIDREF
- public DefaultProduct getProduct(){
- return product;
- }
+ public DefaultProduct getProduct(){
+ return fromProduct;
+ }
- @XmlElement(required=false, name="fromProductCategory")
- public ProductCategory getProductCategory() {
- return productCategory;
- }
+ public ProductCategory getProductCategory() {
+ return fromProductCategory;
+ }
- @XmlElement(required=false, name="fromBillingPeriod")
- public BillingPeriod getBillingPeriod() {
- return billingPeriod;
- }
-
- @XmlElement(required=false, name="fromPriceList")
- @XmlIDREF
- public DefaultPriceList getPriceList() {
- return priceList;
- }
+ public BillingPeriod getBillingPeriod() {
+ return fromBillingPeriod;
+ }
+
+ public DefaultPriceList getPriceList() {
+ return fromPriceList;
+ }
+
+ protected DefaultPriceList getResult() {
+ return toPriceList;
+ }
+
+ protected CasePriceList setProduct(DefaultProduct product) {
+ this.fromProduct = product;
+ return this;
+ }
+
+ protected CasePriceList setProductCategory(ProductCategory productCategory) {
+ this.fromProductCategory = productCategory;
+ return this;
+ }
+
+ protected CasePriceList setBillingPeriod(BillingPeriod billingPeriod) {
+ this.fromBillingPeriod = billingPeriod;
+ return this;
+ }
+
+ protected CasePriceList setPriceList(DefaultPriceList priceList) {
+ this.fromPriceList = priceList;
+ return this;
+ }
+
+
- @Override
- @XmlElement(required=true, name="toPriceList")
- @XmlIDREF
- protected DefaultPriceList getResult() {
- return toPriceList;
- }
protected CasePriceList setToPriceList(DefaultPriceList toPriceList) {
this.toPriceList = toPriceList;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
index a0235de..8e161ce 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
@@ -16,36 +16,62 @@
package com.ning.billing.catalog.rules;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlIDREF;
-
import com.ning.billing.catalog.DefaultPriceList;
import com.ning.billing.catalog.DefaultProduct;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.ProductCategory;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
public abstract class CaseStandardNaming<T> extends Case<T> {
+ @XmlElement(required=false, name="product")
+ @XmlIDREF
+ private DefaultProduct product;
+ @XmlElement(required=false, name="productCategory")
+ private ProductCategory productCategory;
+
+ @XmlElement(required=false, name="billingPeriod")
+ private BillingPeriod billingPeriod;
+
+ @XmlElement(required=false, name="priceList")
+ @XmlIDREF
+ private DefaultPriceList priceList;
- @XmlElement(required=false, name="product")
- @XmlIDREF
public DefaultProduct getProduct(){
return product;
}
- @XmlElement(required=false, name="productCategory")
public ProductCategory getProductCategory() {
return productCategory;
}
- @XmlElement(required=false, name="billingPeriod")
public BillingPeriod getBillingPeriod() {
return billingPeriod;
}
- @XmlElement(required=false, name="priceList")
- @XmlIDREF
public DefaultPriceList getPriceList() {
return priceList;
}
+ protected CaseStandardNaming<T> setProduct(DefaultProduct product) {
+ this.product = product;
+ return this;
+ }
+
+ protected CaseStandardNaming<T> setProductCategory(ProductCategory productCategory) {
+ this.productCategory = productCategory;
+ return this;
+ }
+
+ protected CaseStandardNaming<T> setBillingPeriod(BillingPeriod billingPeriod) {
+ this.billingPeriod = billingPeriod;
+ return this;
+ }
+
+ protected CaseStandardNaming<T> setPriceList(DefaultPriceList priceList) {
+ this.priceList = priceList;
+ return this;
+ }
+
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
index 40edb6b..54aa5c7 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
@@ -16,25 +16,17 @@
package com.ning.billing.catalog.rules;
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
+
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 com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingAlignment;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.IllegalPlanChange;
-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.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.util.config.ValidatingConfig;
-import com.ning.billing.util.config.ValidationErrors;
-
@XmlAccessorType(XmlAccessType.NONE)
public class PlanRules extends ValidatingConfig<StandaloneCatalog> {
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 4ba7bc1..06b24bb 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
@@ -16,35 +16,18 @@
package com.ning.billing.catalog;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Date;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
-
import com.ning.billing.ErrorCode;
-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.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.IllegalPlanChange;
-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.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.catalog.rules.PlanRules;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
+import javax.xml.bind.annotation.*;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Date;
+
@XmlRootElement(name="catalog")
@XmlAccessorType(XmlAccessType.NONE)
public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> implements Catalog {
@@ -84,7 +67,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
* @see com.ning.billing.catalog.ICatalog#getCalalogName()
*/
@Override
- public String getCalalogName() {
+ public String getCatalogName() {
return catalogName;
}
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 6b43a4b..bb48b9b 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -32,20 +32,21 @@ import com.google.inject.Inject;
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.Catalog;
import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
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.Product;
import com.ning.billing.util.config.ValidatingConfig;
import com.ning.billing.util.config.ValidationErrors;
+
@XmlRootElement(name="catalog")
@XmlAccessorType(XmlAccessType.NONE)
public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implements Catalog {
@@ -178,8 +179,8 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
}
@Override
- public String getCalalogName() {
- return currentCatalog.getCalalogName();
+ public String getCatalogName() {
+ return currentCatalog.getCatalogName();
}
@Override
diff --git a/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java b/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java
index 9094733..4367c9a 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java
@@ -16,13 +16,12 @@
package com.ning.billing.catalog;
+import com.ning.billing.util.config.XMLSchemaGenerator;
+
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.util.config.XMLSchemaGenerator;
-
public class CreateCatalogSchema {
/**
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
index 3860561..9708b99 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
@@ -15,8 +15,18 @@
*/
package com.ning.billing.catalog.io;
-import static org.testng.AssertJUnit.assertEquals;
+import com.google.common.io.Resources;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.VersionedCatalog;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
@@ -25,19 +35,7 @@ import java.net.URL;
import java.util.Iterator;
import java.util.List;
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
-
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
-
-import com.google.common.io.Resources;
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.VersionedCatalog;
-import com.ning.billing.catalog.api.InvalidConfigException;
-import com.ning.billing.lifecycle.KillbillService.ServiceException;
-import com.ning.billing.util.clock.DefaultClock;
+import static org.testng.AssertJUnit.assertEquals;
public class TestVersionedCatalogLoader {
private final VersionedCatalogLoader loader = new VersionedCatalogLoader(new DefaultClock());
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
index 3ec03d5..77f7248 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
@@ -16,11 +16,10 @@
package com.ning.billing.catalog.io;
-import org.testng.annotations.Test;
-
import com.google.common.io.Resources;
import com.ning.billing.catalog.StandaloneCatalog;
import com.ning.billing.util.config.XMLLoader;
+import org.testng.annotations.Test;
public class TestXMLReader {
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 5c4975e..089c1e4 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
@@ -16,16 +16,12 @@
package com.ning.billing.catalog;
-import java.util.Date;
-
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.ProductCategory;
-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;
+import com.ning.billing.catalog.rules.*;
+
+import java.util.Date;
public class MockCatalog extends StandaloneCatalog {
private static final String[] PRODUCT_NAMES = new String[]{ "TestProduct1", "TestProduct2", "TestProduct3"};
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
index 1a4d8d9..5d1af74 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
@@ -16,11 +16,11 @@
package com.ning.billing.catalog;
+import com.ning.billing.catalog.api.Currency;
+
import java.math.BigDecimal;
import java.util.Date;
-import com.ning.billing.catalog.api.Currency;
-
public class MockInternationalPrice extends DefaultInternationalPrice {
MockInternationalPrice() {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
index a9c3ffc..0c2f3b0 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
@@ -16,215 +16,259 @@
package com.ning.billing.catalog.rules;
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
+import org.testng.annotations.Test;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNull;
-import javax.xml.bind.annotation.XmlElement;
+public class TestCase {
-import org.testng.annotations.Test;
+ protected class CaseResult extends Case<Result> {
+
+ @XmlElement(required=true)
+ private Result policy;
+
+ public CaseResult(DefaultProduct product, ProductCategory productCategory, BillingPeriod billingPeriod, DefaultPriceList priceList,
+ Result policy) {
+ setProduct(product);
+ setProductCategory(productCategory);
+ setBillingPeriod(billingPeriod);
+ setPriceList(priceList);
+ this.policy = policy;
+ }
+
+ @Override
+ protected Result getResult() {
+ return policy;
+ }
+
+ @XmlElement(required=false, name="product")
+ @XmlIDREF
+ protected DefaultProduct product;
+ @XmlElement(required=false, name="productCategory")
+ protected ProductCategory productCategory;
+
+ @XmlElement(required=false, name="billingPeriod")
+ protected BillingPeriod billingPeriod;
+
+ @XmlElement(required=false, name="priceList")
+ @XmlIDREF
+ protected DefaultPriceList priceList;
+
+ public DefaultProduct getProduct(){
+ return product;
+ }
+
+ public ProductCategory getProductCategory() {
+ return productCategory;
+ }
+
+ public BillingPeriod getBillingPeriod() {
+ return billingPeriod;
+ }
+
+ public DefaultPriceList getPriceList() {
+ return priceList;
+ }
+
+ protected CaseResult setProduct(DefaultProduct product) {
+ this.product = product;
+ return this;
+ }
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.catalog.rules.Case;
+ protected CaseResult setProductCategory(ProductCategory productCategory) {
+ this.productCategory = productCategory;
+ return this;
+ }
+
+ protected CaseResult setBillingPeriod(BillingPeriod billingPeriod) {
+ this.billingPeriod = billingPeriod;
+ return this;
+ }
+
+ protected CaseResult setPriceList(DefaultPriceList priceList) {
+ this.priceList = priceList;
+ return this;
+ }
+ }
-public class TestCase {
+ @Test(enabled=true)
+ public void testBasic() throws CatalogApiException{
+ MockCatalog cat = new MockCatalog();
+
+ DefaultProduct product = cat.getProducts()[0];
+ DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardProduct() throws CatalogApiException{
+ MockCatalog cat = new MockCatalog();
+
+ DefaultProduct product = cat.getProducts()[0];
+ DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+
+ CaseResult cr = new CaseResult(
+ null,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertion(Result.FOO, cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardProductCategory() throws CatalogApiException{
+ MockCatalog cat = new MockCatalog();
+
+ DefaultProduct product = cat.getProducts()[0];
+ DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ null,
+ BillingPeriod.MONTHLY,
+ priceList,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardBillingPeriod() throws CatalogApiException{
+ MockCatalog cat = new MockCatalog();
+
+ DefaultProduct product = cat.getProducts()[0];
+ DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ null,
+ priceList,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardPriceList() throws CatalogApiException{
+ MockCatalog cat = new MockCatalog();
+
+ DefaultProduct product = cat.getProducts()[0];
+ DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ null,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test
+ public void testCaseOrder() throws CatalogApiException {
+ MockCatalog cat = new MockCatalog();
+
+ DefaultProduct product = cat.getProducts()[0];
+ DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+
+ CaseResult cr0 = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+ Result.FOO);
+
+ CaseResult cr1 = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+ Result.BAR);
+
+ CaseResult cr2 = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.ANNUAL,
+ priceList,
+ Result.DIPSY);
+
+ CaseResult cr3 = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.ANNUAL,
+ priceList,
+ Result.LALA);
+
+ Result r1 = Case.getResult(new CaseResult[]{cr0, cr1, cr2,cr3},
+ new PlanSpecifier(product.getName(), product.getCategory(), BillingPeriod.MONTHLY, priceList.getName()), cat);
+ assertEquals(Result.FOO, r1);
+
+ Result r2 = Case.getResult(new CaseResult[]{cr0, cr1, cr2},
+ new PlanSpecifier(product.getName(), product.getCategory(), BillingPeriod.ANNUAL, priceList.getName()), cat);
+ assertEquals(Result.DIPSY, r2);
+ }
+
+
+
+
+ protected void assertionNull(CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, StandaloneCatalog cat) throws CatalogApiException{
+ assertNull(cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
+ }
- protected class CaseResult extends Case<Result> {
-
- @XmlElement(required=true)
- private Result policy;
-
- public CaseResult(DefaultProduct product, ProductCategory productCategory, BillingPeriod billingPeriod, DefaultPriceList priceList,
- Result policy) {
- setProduct(product);
- setProductCategory(productCategory);
- setBillingPeriod(billingPeriod);
- setPriceList(priceList);
- this.policy = policy;
- }
-
- @Override
- protected Result getResult() {
- return policy;
- }
- }
-
- @Test(enabled=true)
- public void testBasic() throws CatalogApiException{
- MockCatalog cat = new MockCatalog();
-
- DefaultProduct product = cat.getProducts()[0];
- DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
-
-
- CaseResult cr = new CaseResult(
- product,
- ProductCategory.BASE,
- BillingPeriod.MONTHLY,
- priceList,
- Result.FOO);
-
- assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
- }
-
- @Test(enabled=true)
- public void testWildCardProduct() throws CatalogApiException{
- MockCatalog cat = new MockCatalog();
-
- DefaultProduct product = cat.getProducts()[0];
- DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
-
-
- CaseResult cr = new CaseResult(
- null,
- ProductCategory.BASE,
- BillingPeriod.MONTHLY,
- priceList,
-
- Result.FOO);
-
- assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertion(Result.FOO, cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
- }
-
- @Test(enabled=true)
- public void testWildCardProductCategory() throws CatalogApiException{
- MockCatalog cat = new MockCatalog();
-
- DefaultProduct product = cat.getProducts()[0];
- DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
-
-
- CaseResult cr = new CaseResult(
- product,
- null,
- BillingPeriod.MONTHLY,
- priceList,
-
- Result.FOO);
-
- assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertion(Result.FOO, cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
- }
-
- @Test(enabled=true)
- public void testWildCardBillingPeriod() throws CatalogApiException{
- MockCatalog cat = new MockCatalog();
-
- DefaultProduct product = cat.getProducts()[0];
- DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
-
-
- CaseResult cr = new CaseResult(
- product,
- ProductCategory.BASE,
- null,
- priceList,
-
- Result.FOO);
-
- assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
- }
-
- @Test(enabled=true)
- public void testWildCardPriceList() throws CatalogApiException{
- MockCatalog cat = new MockCatalog();
-
- DefaultProduct product = cat.getProducts()[0];
- DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
-
-
- CaseResult cr = new CaseResult(
- product,
- ProductCategory.BASE,
- BillingPeriod.MONTHLY,
- null,
-
- Result.FOO);
-
- assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
- assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
- assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
- }
-
- @Test
- public void testCaseOrder() throws CatalogApiException {
- MockCatalog cat = new MockCatalog();
-
- DefaultProduct product = cat.getProducts()[0];
- DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
-
-
- CaseResult cr0 = new CaseResult(
- product,
- ProductCategory.BASE,
- BillingPeriod.MONTHLY,
- priceList,
- Result.FOO);
-
- CaseResult cr1 = new CaseResult(
- product,
- ProductCategory.BASE,
- BillingPeriod.MONTHLY,
- priceList,
- Result.BAR);
-
- CaseResult cr2 = new CaseResult(
- product,
- ProductCategory.BASE,
- BillingPeriod.ANNUAL,
- priceList,
- Result.DIPSY);
-
- CaseResult cr3 = new CaseResult(
- product,
- ProductCategory.BASE,
- BillingPeriod.ANNUAL,
- priceList,
- Result.LALA);
-
- Result r1 = Case.getResult(new CaseResult[]{cr0, cr1, cr2,cr3},
- new PlanSpecifier(product.getName(), product.getCategory(), BillingPeriod.MONTHLY, priceList.getName()), cat);
- assertEquals(Result.FOO, r1);
-
- Result r2 = Case.getResult(new CaseResult[]{cr0, cr1, cr2},
- new PlanSpecifier(product.getName(), product.getCategory(), BillingPeriod.ANNUAL, priceList.getName()), cat);
- assertEquals(Result.DIPSY, r2);
- }
-
-
-
-
- protected void assertionNull(CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, StandaloneCatalog cat) throws CatalogApiException{
- assertNull(cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
- }
-
- protected void assertion(Result result, CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName,StandaloneCatalog cat) throws CatalogApiException{
- assertEquals(result, cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
- }
+ protected void assertion(Result result, CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName,StandaloneCatalog cat) throws CatalogApiException{
+ assertEquals(result, cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
+ }
}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
index bfc3f6d..af13162 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
@@ -16,25 +16,18 @@
package com.ning.billing.catalog.rules;
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
-
-import javax.xml.bind.annotation.XmlElement;
-
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
import org.testng.Assert;
import org.testng.annotations.Test;
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
+import javax.xml.bind.annotation.XmlElement;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
public class TestCaseChange {
protected static class CaseChangeResult extends CaseChange<Result> {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
index c9d2f22..fe505f4 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
@@ -16,21 +16,15 @@
package com.ning.billing.catalog.rules;
-import javax.xml.bind.annotation.XmlElement;
-
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
import org.testng.Assert;
import org.testng.annotations.Test;
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.catalog.rules.CasePhase;
+import javax.xml.bind.annotation.XmlElement;
public class TestCasePhase {
protected class CaseResult extends CasePhase<Result> {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestLoadRules.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestLoadRules.java
new file mode 100644
index 0000000..6f1d9e2
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestLoadRules.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog.rules;
+
+import java.io.File;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.util.config.XMLLoader;
+
+public class TestLoadRules {
+
+ @Test
+ public void test() throws Exception {
+ StandaloneCatalog catalog = XMLLoader.getObjectFromUri(new File("src/test/resources/WeaponsHireSmall.xml").toURI(), StandaloneCatalog.class);
+ Assert.assertNotNull(catalog);
+ PlanRules rules = catalog.getPlanRules();
+
+ PlanSpecifier specifier = new PlanSpecifier("Laser-Scope", ProductCategory.ADD_ON , BillingPeriod.MONTHLY,
+ "DEFAULT");
+
+ PlanAlignmentCreate alignment= rules.getPlanCreateAlignment(specifier, catalog);
+ Assert.assertEquals(alignment, PlanAlignmentCreate.START_OF_SUBSCRIPTION);
+
+ PlanSpecifier specifier2 = new PlanSpecifier("Extra-Ammo", ProductCategory.ADD_ON , BillingPeriod.MONTHLY,
+ "DEFAULT");
+
+ PlanAlignmentCreate alignment2 = rules.getPlanCreateAlignment(specifier2, catalog);
+ Assert.assertEquals(alignment2, PlanAlignmentCreate.START_OF_BUNDLE);
+ }
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
index 1d744e0..e41d506 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
@@ -16,26 +16,16 @@
package com.ning.billing.catalog.rules;
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-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.PriceListSet;
-import com.ning.billing.catalog.api.IllegalPlanChange;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
-import com.ning.billing.catalog.api.PlanChangeResult;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-
public class TestPlanRules {
Logger log = LoggerFactory.getLogger(TestPlanRules.class);
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
index 93991e1..0f75459 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
@@ -15,19 +15,18 @@
*/
package com.ning.billing.catalog;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Date;
-
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.config.ValidationErrors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.util.config.ValidationErrors;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
public class TestInternationalPrice {
private static final Logger log = LoggerFactory.getLogger(TestInternationalPrice.class);
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
index 4f14b48..4bfcf30 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
@@ -16,14 +16,13 @@
package com.ning.billing.catalog;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.util.config.ValidationErrors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.util.config.ValidationErrors;
-
public class TestPlanPhase {
Logger log = LoggerFactory.getLogger(TestPlanPhase.class);
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 d1f231e..09024ce 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
@@ -16,16 +16,17 @@
package com.ning.billing.catalog;
-import static com.ning.billing.catalog.api.BillingPeriod.*;
-import static com.ning.billing.catalog.api.PhaseType.*;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static com.ning.billing.catalog.api.BillingPeriod.ANNUAL;
+import static com.ning.billing.catalog.api.BillingPeriod.MONTHLY;
+import static com.ning.billing.catalog.api.PhaseType.DISCOUNT;
+import static com.ning.billing.catalog.api.PhaseType.EVERGREEN;
public class TestPriceListSet {
@Test(enabled=true)
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
index 08f6ebf..bc07e3e 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
@@ -15,25 +15,23 @@
*/
package com.ning.billing.catalog;
-import static org.testng.AssertJUnit.assertEquals;
+import com.google.common.io.Resources;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.catalog.io.VersionedCatalogLoader;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.Date;
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
-
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
-
-import com.google.common.io.Resources;
-import com.ning.billing.catalog.api.InvalidConfigException;
-import com.ning.billing.catalog.io.VersionedCatalogLoader;
-import com.ning.billing.lifecycle.KillbillService.ServiceException;
-import com.ning.billing.util.clock.DefaultClock;
+import static org.testng.AssertJUnit.assertEquals;
public class TestVersionedCatalog {
private final VersionedCatalogLoader loader = new VersionedCatalogLoader(new DefaultClock());
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
index a29e929..fe66528 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
@@ -57,6 +57,15 @@
<alignment>START_OF_SUBSCRIPTION</alignment>
</changeAlignmentCase>
</changeAlignment>
+ <createAlignment>
+ <createAlignmentCase>
+ <product>Laser-Scope</product>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </createAlignmentCase>
+ <createAlignmentCase>
+ <alignment>START_OF_BUNDLE</alignment>
+ </createAlignmentCase>
+ </createAlignment>
</rules>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
index 135a89e..66f2cca 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
@@ -57,6 +57,15 @@
<alignment>START_OF_SUBSCRIPTION</alignment>
</changeAlignmentCase>
</changeAlignment>
+ <createAlignment>
+ <createAlignmentCase>
+ <product>Laser-Scope</product>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </createAlignmentCase>
+ <createAlignmentCase>
+ <alignment>START_OF_BUNDLE</alignment>
+ </createAlignmentCase>
+ </createAlignment>
</rules>
<plans>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
index 747f54b..88caefd 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
@@ -57,6 +57,15 @@
<alignment>START_OF_SUBSCRIPTION</alignment>
</changeAlignmentCase>
</changeAlignment>
+ <createAlignment>
+ <createAlignmentCase>
+ <product>Laser-Scope</product>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </createAlignmentCase>
+ <createAlignmentCase>
+ <alignment>START_OF_BUNDLE</alignment>
+ </createAlignmentCase>
+ </createAlignment>
</rules>
diff --git a/catalog/src/test/resources/WeaponsHire.xml b/catalog/src/test/resources/WeaponsHire.xml
index 740a903..01d7cb4 100644
--- a/catalog/src/test/resources/WeaponsHire.xml
+++ b/catalog/src/test/resources/WeaponsHire.xml
@@ -18,7 +18,7 @@
<!--
Use cases covered so far:
Tiered Product (Pistol/Shotgun/Assault-Rifle)
- Multiple change plan policies
+ Multiple changeEvent plan policies
Multiple PlanAlignment (see below, trial add-on alignments and rescue discount package)
Product transition rules
Add on (Scopes, Hoster)
diff --git a/catalog/src/test/resources/WeaponsHireSmall.xml b/catalog/src/test/resources/WeaponsHireSmall.xml
index 0a3ed52..21a9f08 100644
--- a/catalog/src/test/resources/WeaponsHireSmall.xml
+++ b/catalog/src/test/resources/WeaponsHireSmall.xml
@@ -37,6 +37,9 @@
<product name="Laser-Scope">
<category>ADD_ON</category>
</product>
+ <product name="Extra-Ammo">
+ <category>ADD_ON</category>
+ </product>
</products>
<rules>
@@ -52,11 +55,20 @@
<policy>IMMEDIATE</policy>
</changePolicyCase>
</changePolicy>
- <changeAlignment>
- <changeAlignmentCase>
- <alignment>START_OF_SUBSCRIPTION</alignment>
- </changeAlignmentCase>
- </changeAlignment>
+ <changeAlignment>
+ <changeAlignmentCase>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </changeAlignmentCase>
+ </changeAlignment>
+ <createAlignment>
+ <createAlignmentCase>
+ <product>Laser-Scope</product>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </createAlignmentCase>
+ <createAlignmentCase>
+ <alignment>START_OF_BUNDLE</alignment>
+ </createAlignmentCase>
+ </createAlignment>
</rules>
<plans>
@@ -136,6 +148,34 @@
</recurringPrice>
</finalPhase>
</plan>
+ <plan name="laser-scope-monthly">
+ <product>Laser-Scope</product>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>1999.95</value></price>
+ <price><currency>EUR</currency><value>1499.95</value></price>
+ <price><currency>GBP</currency><value>1999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="extra-ammo-monthly">
+ <product>Extra-Ammo</product>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>1999.95</value></price>
+ <price><currency>EUR</currency><value>1499.95</value></price>
+ <price><currency>GBP</currency><value>1999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
</plans>
<priceLists>
<defaultPriceList name="DEFAULT">
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 89039ff..7e97852 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
new file mode 100644
index 0000000..4290f73
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
@@ -0,0 +1,209 @@
+/*
+ * 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.alignment;
+
+
+import org.joda.time.DateTime;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+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.PlanPhaseSpecifier;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApiException;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementSubscriptionMigrationCase;
+import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
+import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.ning.billing.util.clock.DefaultClock;
+
+public class MigrationPlanAligner {
+
+ private final CatalogService catalogService;
+
+ @Inject
+ public MigrationPlanAligner(CatalogService catalogService) {
+ this.catalogService = catalogService;
+ }
+
+
+ public TimedMigration [] getEventsMigration(EntitlementSubscriptionMigrationCase [] input, DateTime now)
+ throws EntitlementMigrationApiException {
+
+ try {
+ TimedMigration [] events = null;
+ Plan plan0 = catalogService.getCatalog().findPlan(input[0].getPlanPhaseSpecifer().getProductName(),
+ input[0].getPlanPhaseSpecifer().getBillingPeriod(), input[0].getPlanPhaseSpecifer().getPriceListName());
+
+ Plan plan1 = (input.length > 1) ? catalogService.getCatalog().findPlan(input[1].getPlanPhaseSpecifer().getProductName(),
+ input[1].getPlanPhaseSpecifer().getBillingPeriod(), input[1].getPlanPhaseSpecifer().getPriceListName()) :
+ null;
+
+ DateTime migrationStartDate = now;
+
+ if (isRegularMigratedSubscription(input)) {
+
+ events = getEventsOnRegularMigration(plan0,
+ getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
+ input[0].getPlanPhaseSpecifer().getPriceListName(),
+ now);
+
+ } else if (isRegularFutureCancelledMigratedSubscription(input)) {
+
+ events = getEventsOnFuturePlanCancelMigration(plan0,
+ getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
+ input[0].getPlanPhaseSpecifer().getPriceListName(),
+ now,
+ input[0].getCancelledDate());
+
+ } else if (isPhaseChangeMigratedSubscription(input)) {
+
+ PhaseType curPhaseType = input[0].getPlanPhaseSpecifer().getPhaseType();
+ Duration curPhaseDuration = null;
+ for (PlanPhase cur : plan0.getAllPhases()) {
+ if (cur.getPhaseType() == curPhaseType) {
+ curPhaseDuration = cur.getDuration();
+ break;
+ }
+ }
+ if (curPhaseDuration == null) {
+ throw new EntitlementMigrationApiException(String.format("Failed to compute current phase duration for plan %s and phase %s",
+ plan0.getName(), curPhaseType));
+ }
+
+ migrationStartDate = DefaultClock.removeDuration(input[1].getEffectiveDate(), curPhaseDuration);
+ events = getEventsOnFuturePhaseChangeMigration(plan0,
+ getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
+ input[0].getPlanPhaseSpecifer().getPriceListName(),
+ migrationStartDate,
+ input[1].getEffectiveDate());
+
+ } else if (isPlanChangeMigratedSubscription(input)) {
+
+ events = getEventsOnFuturePlanChangeMigration(plan0,
+ getPlanPhase(plan0, input[0].getPlanPhaseSpecifer().getPhaseType()),
+ plan1,
+ getPlanPhase(plan1, input[1].getPlanPhaseSpecifer().getPhaseType()),
+ input[0].getPlanPhaseSpecifer().getPriceListName(),
+ now,
+ input[1].getEffectiveDate());
+
+ } else {
+ throw new EntitlementMigrationApiException("Unknown migration type");
+ }
+
+ return events;
+ } catch (CatalogApiException e) {
+ throw new EntitlementMigrationApiException(e);
+ }
+ }
+
+ private TimedMigration [] getEventsOnRegularMigration(Plan plan, PlanPhase initialPhase, String priceList, DateTime effectiveDate) {
+ TimedMigration [] result = new TimedMigration[1];
+ result[0] = new TimedMigration(effectiveDate, EventType.API_USER, ApiEventType.MIGRATE_ENTITLEMENT, plan, initialPhase, priceList);
+ return result;
+ }
+
+ private TimedMigration [] getEventsOnFuturePhaseChangeMigration(Plan plan, PlanPhase initialPhase, String priceList, DateTime effectiveDate, DateTime effectiveDateForNextPhase)
+ throws EntitlementMigrationApiException {
+
+ TimedMigration [] result = new TimedMigration[2];
+ result[0] = new TimedMigration(effectiveDate, EventType.API_USER, ApiEventType.MIGRATE_ENTITLEMENT, plan, initialPhase, priceList);
+ boolean foundCurrent = false;
+ PlanPhase nextPhase = null;
+ for (PlanPhase cur : plan.getAllPhases()) {
+ if (cur == initialPhase) {
+ foundCurrent = true;
+ continue;
+ }
+ if (foundCurrent) {
+ nextPhase = cur;
+ }
+ }
+ if (nextPhase == null) {
+ throw new EntitlementMigrationApiException(String.format("Cannot find next phase for Plan %s and current Phase %s",
+ plan.getName(), initialPhase.getName()));
+ }
+ result[1] = new TimedMigration(effectiveDateForNextPhase, EventType.PHASE, null, plan, nextPhase, priceList);
+ return result;
+ }
+
+ private TimedMigration [] getEventsOnFuturePlanChangeMigration(Plan currentPlan, PlanPhase currentPhase, Plan newPlan, PlanPhase newPhase, String priceList, DateTime effectiveDate, DateTime effectiveDateForChangePlan) {
+ TimedMigration [] result = new TimedMigration[2];
+ result[0] = new TimedMigration(effectiveDate, EventType.API_USER, ApiEventType.MIGRATE_ENTITLEMENT, currentPlan, currentPhase, priceList);
+ result[1] = new TimedMigration(effectiveDateForChangePlan, EventType.API_USER, ApiEventType.CHANGE, newPlan, newPhase, priceList);
+ return result;
+ }
+
+ private TimedMigration [] getEventsOnFuturePlanCancelMigration(Plan plan, PlanPhase initialPhase, String priceList, DateTime effectiveDate, DateTime effectiveDateForCancellation) {
+ TimedMigration [] result = new TimedMigration[2];
+ result[0] = new TimedMigration(effectiveDate, EventType.API_USER, ApiEventType.MIGRATE_ENTITLEMENT, plan, initialPhase, priceList);
+ result[1] = new TimedMigration(effectiveDateForCancellation, EventType.API_USER, ApiEventType.CANCEL, null, null, null);
+ return result;
+ }
+
+
+ // STEPH should be in catalog
+ private PlanPhase getPlanPhase(Plan plan, PhaseType phaseType) throws EntitlementMigrationApiException {
+ for (PlanPhase cur: plan.getAllPhases()) {
+ if (cur.getPhaseType() == phaseType) {
+ return cur;
+ }
+ }
+ throw new EntitlementMigrationApiException(String.format("Cannot find PlanPhase from Plan %s and type %s", plan.getName(), phaseType));
+ }
+
+ private boolean isRegularMigratedSubscription(EntitlementSubscriptionMigrationCase [] input) {
+ return (input.length == 1 && input[0].getCancelledDate() == null);
+ }
+
+ private boolean isRegularFutureCancelledMigratedSubscription(EntitlementSubscriptionMigrationCase [] input) {
+ return (input.length == 1 && input[0].getCancelledDate() != null);
+ }
+
+ private boolean isPhaseChangeMigratedSubscription(EntitlementSubscriptionMigrationCase [] input) {
+ if (input.length != 2) {
+ return false;
+ }
+ return (isSamePlan(input[0].getPlanPhaseSpecifer(), input[1].getPlanPhaseSpecifer()) &&
+ !isSamePhase(input[0].getPlanPhaseSpecifer(), input[1].getPlanPhaseSpecifer()));
+ }
+
+ private boolean isPlanChangeMigratedSubscription(EntitlementSubscriptionMigrationCase [] input) {
+ if (input.length != 2) {
+ return false;
+ }
+ return ! isSamePlan(input[0].getPlanPhaseSpecifer(), input[1].getPlanPhaseSpecifer());
+ }
+
+ private boolean isSamePlan(PlanPhaseSpecifier plan0, PlanPhaseSpecifier plan1) {
+ if (plan0.getPriceListName().equals(plan1.getPriceListName()) &&
+ plan0.getProductName().equals(plan1.getProductName())) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isSamePhase(PlanPhaseSpecifier plan0, PlanPhaseSpecifier plan1) {
+ if (plan0.getPhaseType() == plan1.getPhaseType()) {
+ return true;
+ }
+ return false;
+ }
+}
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 d9ab5b3..083aef5 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
@@ -16,29 +16,18 @@
package com.ning.billing.entitlement.alignment;
-import java.util.Collections;
-import java.util.LinkedList;
-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.CatalogApiException;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.CatalogService;
-import com.ning.billing.catalog.api.Duration;
-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.PlanAlignmentChange;
-import com.ning.billing.catalog.api.PlanAlignmentCreate;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
/**
*
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedMigration.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedMigration.java
new file mode 100644
index 0000000..e1ad564
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedMigration.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.entitlement.alignment;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
+import com.ning.billing.entitlement.events.user.ApiEventType;
+
+public class TimedMigration {
+
+ private final DateTime eventTime;
+ private final EventType eventType;
+ private final ApiEventType apiEventType;
+
+ private final Plan plan;
+ private final PlanPhase phase;
+ private final String priceList;
+
+
+ public TimedMigration(DateTime eventTime, EventType eventType,
+ ApiEventType apiEventType, Plan plan, PlanPhase phase, String priceList) {
+ super();
+ this.eventTime = eventTime;
+ this.eventType = eventType;
+ this.apiEventType = apiEventType;
+ this.plan = plan;
+ this.phase = phase;
+ this.priceList = priceList;
+ }
+
+ public DateTime getEventTime() {
+ return eventTime;
+ }
+
+ public EventType getEventType() {
+ return eventType;
+ }
+
+
+ public ApiEventType getApiEventType() {
+ return apiEventType;
+ }
+
+ public Plan getPlan() {
+ return plan;
+ }
+
+ public PlanPhase getPhase() {
+ return phase;
+ }
+
+ public String getPriceList() {
+ return priceList;
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java
index 08f1427..889d0ac 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java
@@ -16,9 +16,8 @@
package com.ning.billing.entitlement.alignment;
-import org.joda.time.DateTime;
-
import com.ning.billing.catalog.api.PlanPhase;
+import org.joda.time.DateTime;
public final class TimedPhase {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
index e16f2b5..a607c7c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
@@ -25,13 +25,13 @@ 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.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.api.user.SubscriptionTransition;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
-import com.ning.billing.entitlement.events.EntitlementEvent;
public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
@@ -64,6 +64,10 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
}
return result;
}
+
+ public List<Account> getActiveAccounts() {
+ return null;
+ }
private BillingEvent createBillingEvent(SubscriptionTransition transition) {
@@ -74,7 +78,7 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
public void setChargedThroughDate(UUID subscriptionId, DateTime ctd) {
SubscriptionData subscription = (SubscriptionData) dao.getSubscriptionFromId(subscriptionId);
if (subscription == null) {
- new EntitlementBillingApiException(String.format("Unknwon subscription %s", subscriptionId));
+ new EntitlementBillingApiException(String.format("Unknown subscription %s", subscriptionId));
}
SubscriptionBuilder builder = new SubscriptionBuilder(subscription)
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/AccountMigrationData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/AccountMigrationData.java
new file mode 100644
index 0000000..7396136
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/AccountMigrationData.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.entitlement.api.migration;
+
+import java.util.List;
+
+import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.events.EntitlementEvent;
+
+public class AccountMigrationData {
+
+ private final List<BundleMigrationData> data;
+
+ public AccountMigrationData(List<BundleMigrationData> data) {
+ super();
+ this.data = data;
+ }
+
+ public List<BundleMigrationData> getData() {
+ return data;
+ }
+
+ public static class BundleMigrationData {
+
+ private final SubscriptionBundleData data;
+ private final List<SubscriptionMigrationData> subscriptions;
+
+ public BundleMigrationData(SubscriptionBundleData data,
+ List<SubscriptionMigrationData> subscriptions) {
+ super();
+ this.data = data;
+ this.subscriptions = subscriptions;
+ }
+
+ public SubscriptionBundleData getData() {
+ return data;
+ }
+
+ public List<SubscriptionMigrationData> getSubscriptions() {
+ return subscriptions;
+ }
+ }
+
+ public static class SubscriptionMigrationData {
+
+ private final SubscriptionData data;
+ private final List<EntitlementEvent> initialEvents;
+
+ public SubscriptionMigrationData(SubscriptionData data,
+
+ List<EntitlementEvent> initialEvents) {
+ super();
+ this.data = data;
+ this.initialEvents = initialEvents;
+ }
+
+ public SubscriptionData getData() {
+ return data;
+ }
+
+ public List<EntitlementEvent> getInitialEvents() {
+ return initialEvents;
+ }
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
new file mode 100644
index 0000000..d8a0100
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/migration/DefaultEntitlementMigrationApi.java
@@ -0,0 +1,188 @@
+/*
+ * 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.migration;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+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.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.alignment.MigrationPlanAligner;
+import com.ning.billing.entitlement.alignment.TimedMigration;
+import com.ning.billing.entitlement.api.migration.AccountMigrationData.BundleMigrationData;
+import com.ning.billing.entitlement.api.migration.AccountMigrationData.SubscriptionMigrationData;
+import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
+import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.events.EntitlementEvent;
+import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
+import com.ning.billing.entitlement.events.phase.PhaseEvent;
+import com.ning.billing.entitlement.events.phase.PhaseEventData;
+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.ApiEventMigrate;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.DefaultClock;
+
+public class DefaultEntitlementMigrationApi implements EntitlementMigrationApi {
+
+
+ private final EntitlementDao dao;
+ private final MigrationPlanAligner migrationAligner;
+ private final SubscriptionFactory factory;
+ private final CatalogService catalogService;
+ private final Clock clock;
+
+ @Inject
+ public DefaultEntitlementMigrationApi(MigrationPlanAligner migrationAligner,
+ SubscriptionFactory factory,
+ CatalogService catalogService,
+ EntitlementDao dao,
+ Clock clock) {
+ this.dao = dao;
+ this.migrationAligner = migrationAligner;
+ this.factory = factory;
+ this.catalogService = catalogService;
+ this.clock = clock;
+ }
+
+ @Override
+ public void migrate(EntitlementAccountMigration toBeMigrated)
+ throws EntitlementMigrationApiException {
+ AccountMigrationData accountMigrationData = createAccountMigrationData(toBeMigrated);
+ dao.migrate(toBeMigrated.getAccountKey(), accountMigrationData);
+ }
+
+ @Override
+ public void undoMigration(UUID accountId) {
+ dao.undoMigration(accountId);
+ }
+
+ private AccountMigrationData createAccountMigrationData(EntitlementAccountMigration toBeMigrated)
+ throws EntitlementMigrationApiException {
+
+ final UUID accountId = toBeMigrated.getAccountKey();
+ final DateTime now = clock.getUTCNow();
+
+ List<BundleMigrationData> accountBundleData = new LinkedList<BundleMigrationData>();
+
+ for (final EntitlementBundleMigration curBundle : toBeMigrated.getBundles()) {
+
+ SubscriptionBundleData bundleData = new SubscriptionBundleData(curBundle.getBundleKey(), accountId);
+ List<SubscriptionMigrationData> bundleSubscriptionData = new LinkedList<AccountMigrationData.SubscriptionMigrationData>();
+
+ for (EntitlementSubscriptionMigration curSub : curBundle.getSubscriptions()) {
+ SubscriptionMigrationData data = null;
+ switch (curSub.getCategory()) {
+ case BASE:
+ data = createBaseSubscriptionMigrationData(bundleData.getId(), curSub.getCategory(), curSub.getSubscriptionCases(), now);
+ break;
+ case ADD_ON:
+ // Not implemented yet
+ break;
+ case STANDALONE:
+ // Not implemented yet
+ break;
+ default:
+ throw new EntitlementMigrationApiException(String.format("Unkown product type ", curSub.getCategory()));
+ }
+ if (data != null) {
+ bundleSubscriptionData.add(data);
+ }
+ }
+ BundleMigrationData bundleMigrationData = new BundleMigrationData(bundleData, bundleSubscriptionData);
+ accountBundleData.add(bundleMigrationData);
+ }
+ AccountMigrationData accountMigrationData = new AccountMigrationData(accountBundleData);
+ return accountMigrationData;
+ }
+
+ private SubscriptionMigrationData createBaseSubscriptionMigrationData(UUID bundleId, ProductCategory productCategory,
+ EntitlementSubscriptionMigrationCase [] input, DateTime now)
+ throws EntitlementMigrationApiException {
+
+ TimedMigration [] events = migrationAligner.getEventsMigration(input, now);
+ DateTime migrationStartDate= events[0].getEventTime();
+ List<EntitlementEvent> emptyEvents = Collections.emptyList();
+ SubscriptionData subscriptionData = factory.createSubscription(new SubscriptionBuilder()
+ .setId(UUID.randomUUID())
+ .setBundleId(bundleId)
+ .setCategory(productCategory)
+ .setBundleStartDate(migrationStartDate)
+ .setStartDate(migrationStartDate),
+ emptyEvents);
+ return new SubscriptionMigrationData(subscriptionData, toEvents(subscriptionData, now, events));
+ }
+
+ private List<EntitlementEvent> toEvents(SubscriptionData subscriptionData, DateTime now, TimedMigration [] migrationEvents) {
+
+ List<EntitlementEvent> events = new ArrayList<EntitlementEvent>(migrationEvents.length);
+ for (TimedMigration cur : migrationEvents) {
+
+ if (cur.getEventType() == EventType.PHASE) {
+ PhaseEvent nextPhaseEvent = PhaseEventData.getNextPhaseEvent(cur.getPhase().getName(), subscriptionData, now, cur.getEventTime());
+ events.add(nextPhaseEvent);
+
+ } else if (cur.getEventType() == EventType.API_USER) {
+
+ ApiEventBuilder builder = new ApiEventBuilder()
+ .setSubscriptionId(subscriptionData.getId())
+ .setEventPlan((cur.getPlan() != null) ? cur.getPlan().getName() : null)
+ .setEventPlanPhase((cur.getPhase() != null) ? cur.getPhase().getName() : null)
+ .setEventPriceList(cur.getPriceList())
+ .setActiveVersion(subscriptionData.getActiveVersion())
+ .setEffectiveDate(cur.getEventTime())
+ .setProcessedDate(now)
+ .setRequestedDate(now);
+
+ switch(cur.getApiEventType()) {
+ case MIGRATE_ENTITLEMENT:
+ events.add(new ApiEventMigrate(builder));
+ break;
+
+ case CHANGE:
+ events.add(new ApiEventChange(builder));
+ break;
+ case CANCEL:
+ events.add(new ApiEventCancel(builder));
+ break;
+ default:
+ throw new EntitlementError(String.format("Unexpected type of api migration event %s", cur.getApiEventType()));
+ }
+ } else {
+ throw new EntitlementError(String.format("Unexpected type of migration event %s", cur.getEventType()));
+ }
+ }
+ return events;
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java
index d0897ed..c2f5878 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java
@@ -16,14 +16,13 @@
package com.ning.billing.entitlement.api.test;
-import java.util.UUID;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.google.inject.Inject;
import com.ning.billing.config.EntitlementConfig;
import com.ning.billing.entitlement.engine.core.EventNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.UUID;
public class DefaultEntitlementTestApi implements EntitlementTestApi {
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 d79d514..8b6d59a 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
@@ -18,28 +18,20 @@ package com.ning.billing.entitlement.api.user;
import java.util.List;
import java.util.UUID;
-
import org.joda.time.DateTime;
-
import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
-import com.ning.billing.account.api.IAccount;
-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.Plan;
import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.entitlement.alignment.PlanAligner;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.exceptions.EntitlementError;
-import com.ning.billing.util.clock.DefaultClock;
import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.DefaultClock;
public class DefaultEntitlementUserApi implements EntitlementUserApi {
@@ -68,6 +60,11 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
}
@Override
+ public SubscriptionBundle getBundleForKey(String bundleKey) {
+ return dao.getSubscriptionBundleFromKey(bundleKey);
+ }
+
+ @Override
public List<SubscriptionBundle> getBundlesForAccount(UUID accountId) {
return dao.getSubscriptionBundleForAccount(accountId);
}
@@ -84,18 +81,17 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
}
@Override
- public SubscriptionBundle createBundleForAccount(IAccount account, String bundleName)
+ public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleName)
throws EntitlementUserApiException {
- SubscriptionBundleData bundle = new SubscriptionBundleData(bundleName, account.getId());
+ SubscriptionBundleData bundle = new SubscriptionBundleData(bundleName, accountId);
return dao.createSubscriptionBundle(bundle);
}
@Override
- public Subscription createSubscription(UUID bundleId, String productName,
- BillingPeriod term, String priceList, PhaseType initialPhase, DateTime requestedDate) throws EntitlementUserApiException {
+ public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec, DateTime requestedDate) throws EntitlementUserApiException {
try {
- String realPriceList = (priceList == null) ? PriceListSet.DEFAULT_PRICELIST_NAME : priceList;
+ String realPriceList = (spec.getPriceListName() == null) ? PriceListSet.DEFAULT_PRICELIST_NAME : spec.getPriceListName();
DateTime now = clock.getUTCNow();
requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
if (requestedDate != null && requestedDate.isAfter(now)) {
@@ -104,13 +100,13 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
requestedDate = (requestedDate == null) ? now : requestedDate;
DateTime effectiveDate = requestedDate;
- Plan plan = catalogService.getCatalog().findPlan(productName, term, realPriceList);
+ Plan plan = catalogService.getCatalog().findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList);
PlanPhase phase = (plan.getInitialPhases() != null) ? plan.getInitialPhases()[0] : plan.getFinalPhase();
if (phase == null) {
throw new EntitlementError(String.format("No initial PlanPhase for Product %s, term %s and set %s does not exist in the catalog",
- productName, term.toString(), realPriceList));
+ spec.getProductName(), spec.getBillingPeriod().toString(), realPriceList));
}
SubscriptionBundle bundle = dao.getSubscriptionBundleFromId(bundleId);
@@ -145,7 +141,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
.setCategory(plan.getProduct().getCategory())
.setBundleStartDate(bundleStartDate)
.setStartDate(effectiveDate),
- plan, initialPhase, realPriceList, requestedDate, effectiveDate, now);
+ plan, spec.getPhaseType(), realPriceList, requestedDate, effectiveDate, now);
return subscription;
} catch (CatalogApiException e) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
index 1561aec..3aebac0 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
@@ -16,26 +16,9 @@
package com.ning.billing.entitlement.api.user;
-import java.util.ArrayList;
-import java.util.LinkedList;
-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.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.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.PhaseType;
-import com.ning.billing.catalog.api.PlanChangeResult;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.alignment.TimedPhase;
import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
@@ -44,13 +27,13 @@ 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.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.ApiEventUncancel;
+import com.ning.billing.entitlement.events.user.*;
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 SubscriptionApiService {
@@ -88,7 +71,10 @@ public class SubscriptionApiService {
.setEffectiveDate(effectiveDate)
.setRequestedDate(requestedDate));
- PhaseEvent nextPhaseEvent = PhaseEventData.getNextPhaseEvent(curAndNextPhases[1], subscription, processedDate);
+ TimedPhase nextTimedPhase = curAndNextPhases[1];
+ PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
+ PhaseEventData.getNextPhaseEvent(nextTimedPhase.getPhase().getName(), subscription, processedDate, nextTimedPhase.getStartPhase()) :
+ null;
List<EntitlementEvent> events = new ArrayList<EntitlementEvent>();
events.add(creationEvent);
if (nextPhaseEvent != null) {
@@ -112,7 +98,8 @@ public class SubscriptionApiService {
}
DateTime now = clock.getUTCNow();
- requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : null;
+ requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
+ // STEPH needs to check if requestedDate is before last 'erasable event'?
if (requestedDate != null && requestedDate.isAfter(now)) {
throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
}
@@ -126,7 +113,7 @@ public class SubscriptionApiService {
ActionPolicy policy = null;
policy = catalogService.getCatalog().planCancelPolicy(planPhase);
- DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, now);
+ DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, requestedDate);
EntitlementEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
.setSubscriptionId(subscription.getId())
@@ -163,7 +150,9 @@ public class SubscriptionApiService {
DateTime planStartDate = subscription.getCurrentPlanStart();
TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription.getCurrentPlan(), subscription.getInitialPhaseOnCurrentPlan().getPhaseType(), now, planStartDate);
- PhaseEvent nextPhaseEvent = PhaseEventData.getNextPhaseEvent(nextTimedPhase, subscription, now);
+ PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
+ PhaseEventData.getNextPhaseEvent(nextTimedPhase.getPhase().getName(), subscription, now, nextTimedPhase.getStartPhase()) :
+ null;
if (nextPhaseEvent != null) {
uncancelEvents.add(nextPhaseEvent);
}
@@ -176,66 +165,74 @@ public class SubscriptionApiService {
throws EntitlementUserApiException {
try {
- requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : null;
- String currentPriceList = subscription.getCurrentPriceList();
- SubscriptionState currentState = subscription.getState();
- if (currentState != SubscriptionState.ACTIVE) {
- throw new EntitlementUserApiException(ErrorCode.ENT_CHANGE_NON_ACTIVE, subscription.getId(), currentState);
- }
- if (subscription.isSubscriptionFutureCancelled()) {
- throw new EntitlementUserApiException(ErrorCode.ENT_CHANGE_FUTURE_CANCELLED, subscription.getId());
- }
+ DateTime now = clock.getUTCNow();
+ requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
+ // STEPH needs to check if requestedDate is before last 'erasable event'?
+ if (requestedDate != null && requestedDate.isAfter(now)) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
+ }
- DateTime now = clock.getUTCNow();
- PlanChangeResult planChangeResult = null;
- try {
+ String currentPriceList = subscription.getCurrentPriceList();
- Product destProduct = catalogService.getCatalog().findProduct(productName);
- Plan currentPlan = subscription.getCurrentPlan();
- PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
- currentPlan.getProduct().getCategory(),
- currentPlan.getBillingPeriod(),
- currentPriceList, subscription.getCurrentPhase().getPhaseType());
- PlanSpecifier toPlanPhase = new PlanSpecifier(productName,
- destProduct.getCategory(),
- term,
- priceList);
-
- planChangeResult = catalogService.getCatalog().planChange(fromPlanPhase, toPlanPhase);
- } catch (CatalogApiException e) {
- throw new EntitlementUserApiException(e);
- }
+ SubscriptionState currentState = subscription.getState();
+ if (currentState != SubscriptionState.ACTIVE) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_CHANGE_NON_ACTIVE, subscription.getId(), currentState);
+ }
- ActionPolicy policy = planChangeResult.getPolicy();
- PriceList newPriceList = planChangeResult.getNewPriceList();
+ if (subscription.isSubscriptionFutureCancelled()) {
+ throw new EntitlementUserApiException(ErrorCode.ENT_CHANGE_FUTURE_CANCELLED, subscription.getId());
+ }
+ PlanChangeResult planChangeResult = null;
+ try {
+
+ Product destProduct = catalogService.getCatalog().findProduct(productName);
+ Plan currentPlan = subscription.getCurrentPlan();
+ PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
+ currentPlan.getProduct().getCategory(),
+ currentPlan.getBillingPeriod(),
+ currentPriceList, subscription.getCurrentPhase().getPhaseType());
+ PlanSpecifier toPlanPhase = new PlanSpecifier(productName,
+ destProduct.getCategory(),
+ term,
+ priceList);
+
+ planChangeResult = catalogService.getCatalog().planChange(fromPlanPhase, toPlanPhase);
+ } catch (CatalogApiException e) {
+ throw new EntitlementUserApiException(e);
+ }
- Plan newPlan = catalogService.getCatalog().findPlan(productName, term, newPriceList.getName());
- DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, now);
+ ActionPolicy policy = planChangeResult.getPolicy();
+ PriceList newPriceList = planChangeResult.getNewPriceList();
- TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), effectiveDate);
+ Plan newPlan = catalogService.getCatalog().findPlan(productName, term, newPriceList.getName());
+ DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, now);
- EntitlementEvent changeEvent = new ApiEventChange(new ApiEventBuilder()
- .setSubscriptionId(subscription.getId())
- .setEventPlan(newPlan.getName())
- .setEventPlanPhase(currentTimedPhase.getPhase().getName())
- .setEventPriceList(newPriceList.getName())
- .setActiveVersion(subscription.getActiveVersion())
- .setProcessedDate(now)
- .setEffectiveDate(effectiveDate)
- .setRequestedDate(now));
-
- TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), effectiveDate);
- PhaseEvent nextPhaseEvent = PhaseEventData.getNextPhaseEvent(nextTimedPhase, subscription, now);
- List<EntitlementEvent> changeEvents = new ArrayList<EntitlementEvent>();
- // Only add the PHASE if it does not coincide with the CHANGE, if not this is 'just' a CHANGE.
- if (nextPhaseEvent != null && ! nextPhaseEvent.getEffectiveDate().equals(changeEvent.getEffectiveDate())) {
- changeEvents.add(nextPhaseEvent);
- }
- changeEvents.add(changeEvent);
- dao.changePlan(subscription.getId(), changeEvents);
- subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getCatalog());
+ TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), effectiveDate);
+
+ EntitlementEvent changeEvent = new ApiEventChange(new ApiEventBuilder()
+ .setSubscriptionId(subscription.getId())
+ .setEventPlan(newPlan.getName())
+ .setEventPlanPhase(currentTimedPhase.getPhase().getName())
+ .setEventPriceList(newPriceList.getName())
+ .setActiveVersion(subscription.getActiveVersion())
+ .setProcessedDate(now)
+ .setEffectiveDate(effectiveDate)
+ .setRequestedDate(now));
+
+ TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), effectiveDate);
+ PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
+ PhaseEventData.getNextPhaseEvent(nextTimedPhase.getPhase().getName(), subscription, now, nextTimedPhase.getStartPhase()) :
+ null;
+ List<EntitlementEvent> changeEvents = new ArrayList<EntitlementEvent>();
+ // Only add the PHASE if it does not coincide with the CHANGE, if not this is 'just' a CHANGE.
+ if (nextPhaseEvent != null && ! nextPhaseEvent.getEffectiveDate().equals(changeEvent.getEffectiveDate())) {
+ changeEvents.add(nextPhaseEvent);
+ }
+ changeEvents.add(changeEvent);
+ dao.changePlan(subscription.getId(), changeEvents);
+ subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getCatalog());
} catch (CatalogApiException e) {
throw new EntitlementUserApiException(e);
}
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 ad56168..8bdd584 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,13 +16,9 @@
package com.ning.billing.entitlement.api.user;
-import java.util.UUID;
-
import org.joda.time.DateTime;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.entitlement.events.EntitlementEvent;
-import com.ning.billing.entitlement.events.user.ApiEventCreate;
+import java.util.UUID;
public class SubscriptionBundleData implements SubscriptionBundle {
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 7561305..11f6d71 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,34 +16,21 @@
package com.ning.billing.entitlement.api.user;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.ning.billing.ErrorCode;
-
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
-import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.clock.Clock;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
public class SubscriptionData implements Subscription {
@@ -196,6 +183,17 @@ public class SubscriptionData implements Subscription {
return result;
}
+ public SubscriptionTransition getPendingTransition() {
+ if (transitions == null) {
+ return null;
+ }
+ for (SubscriptionTransition cur : transitions) {
+ if (cur.getEffectiveTransitionTime().isAfter(clock.getUTCNow())) {
+ return cur;
+ }
+ }
+ return null;
+ }
public SubscriptionTransition getLatestTranstion() {
@@ -291,10 +289,10 @@ public class SubscriptionData implements Subscription {
}
- public DateTime getPlanChangeEffectiveDate(ActionPolicy policy, DateTime now) {
+ public DateTime getPlanChangeEffectiveDate(ActionPolicy policy, DateTime requestedDate) {
if (policy == ActionPolicy.IMMEDIATE) {
- return now;
+ return requestedDate;
}
if (policy != ActionPolicy.END_OF_TERM) {
throw new EntitlementError(String.format("Unexpected policy type %s", policy.toString()));
@@ -368,6 +366,7 @@ public class SubscriptionData implements Subscription {
ApiEvent userEV = (ApiEvent) cur;
apiEventType = userEV.getEventType();
switch(apiEventType) {
+ case MIGRATE_ENTITLEMENT:
case CREATE:
nextState = SubscriptionState.ACTIVE;
nextPlanName = userEV.getEventPlan();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java
index d69d4e2..66dfb88 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java
@@ -16,11 +16,11 @@
package com.ning.billing.entitlement.api.user;
+import com.ning.billing.entitlement.events.EntitlementEvent;
+
import java.util.LinkedList;
import java.util.UUID;
-import com.ning.billing.entitlement.events.EntitlementEvent;
-
public class SubscriptionEvents {
public static final long INITIAL_VERSION = 1;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
index 48008bf..207b4b2 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
@@ -16,18 +16,17 @@
package com.ning.billing.entitlement.api.user;
-import java.lang.reflect.Field;
-import java.util.List;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
import com.google.inject.Inject;
import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.clock.Clock;
+import org.joda.time.DateTime;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.UUID;
public class SubscriptionFactory {
@@ -44,12 +43,13 @@ public class SubscriptionFactory {
public SubscriptionData createSubscription(SubscriptionBuilder builder, List<EntitlementEvent> events) {
SubscriptionData subscription = new SubscriptionData(builder, apiService, clock);
- subscription.rebuildTransitions(events, catalogService.getCatalog());
+ if (events.size() > 0) {
+ subscription.rebuildTransitions(events, catalogService.getCatalog());
+ }
return subscription;
}
-
public static class SubscriptionBuilder {
private UUID 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 08cedf7..5a0eba0 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,16 +16,15 @@
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.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 org.joda.time.DateTime;
+
+import java.util.UUID;
public class SubscriptionTransitionData implements SubscriptionTransition {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
index 52fa9a4..cfeaca7 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
@@ -16,20 +16,6 @@
package com.ning.billing.entitlement.engine.core;
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.inject.Inject;
@@ -37,6 +23,15 @@ import com.ning.billing.config.EntitlementConfig;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.util.clock.Clock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.*;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
public abstract class ApiEventProcessorBase implements EventNotifier {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java
index c3c2f20..eba828e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java
@@ -16,15 +16,15 @@
package com.ning.billing.entitlement.engine.core;
-import java.util.Collection;
-import java.util.List;
-
import com.google.inject.Inject;
import com.ning.billing.config.EntitlementConfig;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.util.clock.Clock;
+import java.util.Collection;
+import java.util.List;
+
public class DefaultApiEventProcessor extends ApiEventProcessorBase {
@Inject
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 89b4f2b..3eb5dd3 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
@@ -21,14 +21,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
-import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.config.EntitlementConfig;
-
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.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.test.DefaultEntitlementTestApi;
import com.ning.billing.entitlement.api.test.EntitlementTestApi;
import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
@@ -45,7 +45,6 @@ import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.eventbus.EventBus;
import com.ning.billing.util.eventbus.EventBus.EventBusException;
-import com.sun.org.apache.xml.internal.resolver.CatalogException;
public class Engine implements EventListener, EntitlementService {
@@ -64,6 +63,7 @@ public class Engine implements EventListener, EntitlementService {
private final EntitlementUserApi userApi;
private final EntitlementBillingApi billingApi;
private final EntitlementTestApi testApi;
+ private final EntitlementMigrationApi migrationApi;
private final EventBus eventBus;
private boolean startedNotificationThread;
@@ -71,7 +71,8 @@ public class Engine implements EventListener, EntitlementService {
@Inject
public Engine(Clock clock, EntitlementDao dao, EventNotifier apiEventProcessor,
PlanAligner planAligner, EntitlementConfig config, DefaultEntitlementUserApi userApi,
- DefaultEntitlementBillingApi billingApi, DefaultEntitlementTestApi testApi, EventBus eventBus) {
+ DefaultEntitlementBillingApi billingApi, DefaultEntitlementTestApi testApi,
+ DefaultEntitlementMigrationApi migrationApi, EventBus eventBus) {
super();
this.clock = clock;
this.dao = dao;
@@ -80,6 +81,7 @@ public class Engine implements EventListener, EntitlementService {
this.userApi = userApi;
this.testApi = testApi;
this.billingApi = billingApi;
+ this.migrationApi = migrationApi;
this.eventBus = eventBus;
this.startedNotificationThread = false;
@@ -124,6 +126,12 @@ public class Engine implements EventListener, EntitlementService {
}
@Override
+ public EntitlementMigrationApi getMigrationApi() {
+ return migrationApi;
+ }
+
+
+ @Override
public void processEventReady(EntitlementEvent event) {
SubscriptionData subscription = (SubscriptionData) dao.getSubscriptionFromId(event.getSubscriptionId());
if (subscription == null) {
@@ -180,7 +188,9 @@ public class Engine implements EventListener, EntitlementService {
try {
DateTime now = clock.getUTCNow();
TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription.getCurrentPlan(), subscription.getInitialPhaseOnCurrentPlan().getPhaseType(), now, subscription.getCurrentPlanStart());
- PhaseEvent nextPhaseEvent = PhaseEventData.getNextPhaseEvent(nextTimedPhase, subscription, now);
+ PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
+ PhaseEventData.getNextPhaseEvent(nextTimedPhase.getPhase().getName(), subscription, now, nextTimedPhase.getStartPhase()) :
+ null;
if (nextPhaseEvent != null) {
dao.createNextPhaseEvent(subscription.getId(), nextPhaseEvent);
}
@@ -188,4 +198,5 @@ public class Engine implements EventListener, EntitlementService {
log.error(String.format("Failed to insert next phase for subscription %s", subscription.getId()), e);
}
}
+
}
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 10e0348..d2b9f11 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,13 +16,8 @@
package com.ning.billing.entitlement.engine.dao;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-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 org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.skife.jdbi.v2.SQLStatement;
@@ -38,15 +33,22 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
@ExternalizedSqlViaStringTemplate3()
-public interface BundleSqlDao extends Transactional<EventSqlDao>, CloseMe, Transmogrifier {
+public interface BundleSqlDao extends Transactional<BundleSqlDao>, CloseMe, Transmogrifier {
@SqlUpdate
public void insertBundle(@Bind(binder = SubscriptionBundleBinder.class) SubscriptionBundleData bundle);
+ @SqlUpdate
+ public void removeBundle(@Bind("id") String id);
+
@SqlQuery
@Mapper(ISubscriptionBundleSqlMapper.class)
public SubscriptionBundle getBundleFromId(@Bind("id") String id);
@@ -59,7 +61,6 @@ public interface BundleSqlDao extends Transactional<EventSqlDao>, CloseMe, Trans
@Mapper(ISubscriptionBundleSqlMapper.class)
public List<SubscriptionBundle> getBundleFromAccount(@Bind("account_id") String accountId);
-
public static class SubscriptionBundleBinder implements Binder<Bind, SubscriptionBundleData> {
private Date getDate(DateTime dateTime) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
index 835da51..b118110 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
@@ -16,15 +16,15 @@
package com.ning.billing.entitlement.engine.dao;
-import java.util.Collection;
-import java.util.List;
-import java.util.UUID;
-
+import com.ning.billing.entitlement.api.migration.AccountMigrationData;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.events.EntitlementEvent;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
public interface EntitlementDao {
@@ -32,6 +32,8 @@ public interface EntitlementDao {
// Bundle apis
public List<SubscriptionBundle> getSubscriptionBundleForAccount(UUID accountId);
+ public SubscriptionBundle getSubscriptionBundleFromKey(String bundleKey);
+
public SubscriptionBundle getSubscriptionBundleFromId(UUID bundleId);
public SubscriptionBundle createSubscriptionBundle(SubscriptionBundleData bundle);
@@ -68,4 +70,8 @@ public interface EntitlementDao {
public void uncancelSubscription(UUID subscriptionId, List<EntitlementEvent> uncancelEvents);
public void changePlan(UUID subscriptionId, List<EntitlementEvent> changeEvents);
+
+ public void migrate(UUID acountId, AccountMigrationData data);
+
+ public void undoMigration(UUID accountId);
}
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 15f1e8c..016f005 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
@@ -16,22 +16,12 @@
package com.ning.billing.entitlement.engine.dao;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
-import org.skife.jdbi.v2.DBI;
-import org.skife.jdbi.v2.Transaction;
-import org.skife.jdbi.v2.TransactionStatus;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.google.inject.Inject;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.config.EntitlementConfig;
+import com.ning.billing.entitlement.api.migration.AccountMigrationData;
+import com.ning.billing.entitlement.api.migration.AccountMigrationData.BundleMigrationData;
+import com.ning.billing.entitlement.api.migration.AccountMigrationData.SubscriptionMigrationData;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
@@ -40,11 +30,18 @@ import com.ning.billing.entitlement.api.user.SubscriptionFactory;
import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
-import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.Hostname;
import com.ning.billing.util.clock.Clock;
+import org.skife.jdbi.v2.DBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
public class EntitlementSqlDao implements EntitlementDao {
@@ -70,6 +67,11 @@ public class EntitlementSqlDao implements EntitlementDao {
}
@Override
+ public SubscriptionBundle getSubscriptionBundleFromKey(String bundleKey) {
+ return bundlesDao.getBundleFromKey(bundleKey);
+ }
+
+ @Override
public List<SubscriptionBundle> getSubscriptionBundleForAccount(
UUID accountId) {
return bundlesDao.getBundleFromAccount(accountId.toString());
@@ -81,9 +83,14 @@ public class EntitlementSqlDao implements EntitlementDao {
}
@Override
- public SubscriptionBundle createSubscriptionBundle(SubscriptionBundleData bundle) {
- bundlesDao.insertBundle(bundle);
- return bundle;
+ public SubscriptionBundle createSubscriptionBundle(final SubscriptionBundleData bundle) {
+ return bundlesDao.inTransaction(new Transaction<SubscriptionBundle, BundleSqlDao>() {
+ @Override
+ public SubscriptionBundle inTransaction(BundleSqlDao bundlesDao, TransactionStatus status) {
+ bundlesDao.insertBundle(bundle);
+ return bundle;
+ }
+ });
}
@Override
@@ -339,4 +346,64 @@ public class EntitlementSqlDao implements EntitlementDao {
}
return result;
}
+
+ @Override
+ public void migrate(final UUID accountId, final AccountMigrationData accountData) {
+
+ eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
+
+ @Override
+ public Void inTransaction(EventSqlDao transEventDao,
+ TransactionStatus status) throws Exception {
+
+ SubscriptionSqlDao transSubDao = transEventDao.become(SubscriptionSqlDao.class);
+ BundleSqlDao transBundleDao = transEventDao.become(BundleSqlDao.class);
+
+ // First get rid of any data from account
+ undoMigrationFromTransaction(accountId, transEventDao, transBundleDao, transSubDao);
+
+ for (BundleMigrationData curBundle : accountData.getData()) {
+ SubscriptionBundleData bundleData = curBundle.getData();
+ for (SubscriptionMigrationData curSubscription : curBundle.getSubscriptions()) {
+ SubscriptionData subData = curSubscription.getData();
+ for (EntitlementEvent curEvent : curSubscription.getInitialEvents()) {
+ transEventDao.insertEvent(curEvent);
+ }
+ transSubDao.insertSubscription(subData);
+ }
+ transBundleDao.insertBundle(bundleData);
+ }
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public void undoMigration(final UUID accountId) {
+
+ eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
+
+ @Override
+ public Void inTransaction(EventSqlDao transEventDao,
+ TransactionStatus status) throws Exception {
+
+ SubscriptionSqlDao transSubDao = transEventDao.become(SubscriptionSqlDao.class);
+ BundleSqlDao transBundleDao = transEventDao.become(BundleSqlDao.class);
+ undoMigrationFromTransaction(accountId, transEventDao, transBundleDao, transSubDao);
+ return null;
+ }
+ });
+ }
+
+ private void undoMigrationFromTransaction(final UUID accountId, EventSqlDao transEventDao, BundleSqlDao transBundleDao, SubscriptionSqlDao transSubDao) {
+ final List<SubscriptionBundle> bundles = transBundleDao.getBundleFromAccount(accountId.toString());
+ for (SubscriptionBundle curBundle : bundles) {
+ List<Subscription> subscriptions = transSubDao.getSubscriptionsFromBundleId(curBundle.getId().toString());
+ for (Subscription cur : subscriptions) {
+ eventsDao.removeEvents(cur.getId().toString());
+ transSubDao.removeSubscription(cur.getId().toString());
+ }
+ transBundleDao.removeBundle(curBundle.getId().toString());
+ }
+ }
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
index a1e2670..de61217 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
@@ -16,13 +16,15 @@
package com.ning.billing.entitlement.engine.dao;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
+import com.ning.billing.entitlement.events.EntitlementEvent;
+import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
+import com.ning.billing.entitlement.events.EventBaseBuilder;
+import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
+import com.ning.billing.entitlement.events.phase.PhaseEvent;
+import com.ning.billing.entitlement.events.phase.PhaseEventBuilder;
+import com.ning.billing.entitlement.events.phase.PhaseEventData;
+import com.ning.billing.entitlement.events.user.*;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.skife.jdbi.v2.SQLStatement;
@@ -37,24 +39,12 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
-
-import com.ning.billing.entitlement.events.EventBaseBuilder;
-import com.ning.billing.entitlement.events.EntitlementEvent;
-import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
-import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
-import com.ning.billing.entitlement.events.phase.PhaseEvent;
-import com.ning.billing.entitlement.events.phase.PhaseEventData;
-import com.ning.billing.entitlement.events.phase.PhaseEventBuilder;
-import com.ning.billing.entitlement.events.user.ApiEventBuilder;
-import com.ning.billing.entitlement.events.user.ApiEventCancel;
-import com.ning.billing.entitlement.events.user.ApiEventChange;
-import com.ning.billing.entitlement.events.user.ApiEventCreate;
-import com.ning.billing.entitlement.events.user.ApiEventPause;
-import com.ning.billing.entitlement.events.user.ApiEventResume;
-import com.ning.billing.entitlement.events.user.ApiEventType;
-import com.ning.billing.entitlement.events.user.ApiEventUncancel;
-import com.ning.billing.entitlement.events.user.ApiEvent;
-import com.ning.billing.entitlement.exceptions.EntitlementError;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
@ExternalizedSqlViaStringTemplate3()
public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transmogrifier {
@@ -70,6 +60,9 @@ public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transm
public int claimEvent(@Bind("owner") String owner, @Bind("next_available") Date nextAvailable, @Bind("event_id") String eventId, @Bind("now") Date now);
@SqlUpdate
+ public void removeEvents(@Bind("subscription_id") String subscriptionId);
+
+ @SqlUpdate
public void clearEvent(@Bind("event_id") String eventId, @Bind("owner") String owner);
@SqlUpdate
@@ -163,12 +156,9 @@ public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transm
EntitlementEvent result = null;
if (eventType == EventType.PHASE) {
- EventBaseBuilder<PhaseEventBuilder> realBase = (EventBaseBuilder<PhaseEventBuilder>) base;
- result = new PhaseEventData(new PhaseEventBuilder(realBase).setPhaseName(phaseName));
+ result = new PhaseEventData(new PhaseEventBuilder(base).setPhaseName(phaseName));
} else if (eventType == EventType.API_USER) {
-
- EventBaseBuilder<ApiEventBuilder> realBase = (EventBaseBuilder<ApiEventBuilder>) base;
- ApiEventBuilder builder = new ApiEventBuilder(realBase)
+ ApiEventBuilder builder = new ApiEventBuilder(base)
.setEventPlan(planName)
.setEventPlanPhase(phaseName)
.setEventPriceList(priceListName)
@@ -176,6 +166,8 @@ public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transm
if (userType == ApiEventType.CREATE) {
result = new ApiEventCreate(builder);
+ } else if (userType == ApiEventType.MIGRATE_ENTITLEMENT) {
+ result = new ApiEventMigrate(builder);
} else if (userType == ApiEventType.CHANGE) {
result = new ApiEventChange(builder);
} else if (userType == ApiEventType.CANCEL) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
index 4a5312c..d896ebe 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
@@ -16,13 +16,10 @@
package com.ning.billing.entitlement.engine.dao;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.skife.jdbi.v2.SQLStatement;
@@ -38,10 +35,12 @@ 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.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionData;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
@ExternalizedSqlViaStringTemplate3()
@@ -50,6 +49,9 @@ public interface SubscriptionSqlDao extends Transactional<SubscriptionSqlDao>, C
@SqlUpdate
public void insertSubscription(@Bind(binder = ISubscriptionDaoBinder.class) SubscriptionData sub);
+ @SqlUpdate
+ public void removeSubscription(@Bind("id") String id);
+
@SqlQuery
@Mapper(ISubscriptionDaoSqlMapper.class)
public Subscription getSubscriptionFromId(@Bind("id") String id);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java
index cfbfd63..af74752 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java
@@ -16,10 +16,10 @@
package com.ning.billing.entitlement.events;
-import java.util.UUID;
-
import org.joda.time.DateTime;
+import java.util.UUID;
+
public interface EntitlementEvent extends EventLifecycle, Comparable<EntitlementEvent> {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
index d7a578c..93dc9e1 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
@@ -16,14 +16,11 @@
package com.ning.billing.entitlement.events;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
import com.ning.billing.entitlement.events.user.ApiEvent;
import com.ning.billing.entitlement.exceptions.EntitlementError;
+import org.joda.time.DateTime;
+
+import java.util.UUID;
public abstract class EventBase implements EntitlementEvent {
@@ -40,7 +37,7 @@ public abstract class EventBase implements EntitlementEvent {
private DateTime nextAvailableProcessingTime;
private EventLifecycleState processingState;
- public EventBase(EventBaseBuilder builder) {
+ public EventBase(EventBaseBuilder<?> builder) {
this.uuid = builder.getUuid();
this.subscriptionId = builder.getSubscriptionId();
this.requestedDate = builder.getRequestedDate();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
index e003e35..104fbef 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
@@ -16,11 +16,10 @@
package com.ning.billing.entitlement.events;
-import java.util.UUID;
-
+import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
import org.joda.time.DateTime;
-import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
+import java.util.UUID;
@SuppressWarnings("unchecked")
public class EventBaseBuilder<T extends EventBaseBuilder<T>> {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java
index 0e9b226..ed2b042 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java
@@ -16,10 +16,10 @@
package com.ning.billing.entitlement.events;
-import java.util.UUID;
-
import org.joda.time.DateTime;
+import java.util.UUID;
+
public interface EventLifecycle {
public enum EventLifecycleState {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.java
index 00ac8e2..5847970 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventBuilder.java
@@ -26,7 +26,7 @@ public class PhaseEventBuilder extends EventBaseBuilder<PhaseEventBuilder> {
super();
}
- public PhaseEventBuilder(EventBaseBuilder<PhaseEventBuilder> base) {
+ public PhaseEventBuilder(EventBaseBuilder<?> base) {
super(base);
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java
index 873fb6d..9744363 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java
@@ -17,11 +17,10 @@
package com.ning.billing.entitlement.events.phase;
-import org.joda.time.DateTime;
-
import com.ning.billing.entitlement.alignment.TimedPhase;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.events.EventBase;
+import org.joda.time.DateTime;
public class PhaseEventData extends EventBase implements PhaseEvent {
@@ -57,15 +56,15 @@ public class PhaseEventData extends EventBase implements PhaseEvent {
+ ", isActive()=" + isActive() + "]\n";
}
- public static final PhaseEvent getNextPhaseEvent(TimedPhase nextTimedPhase, SubscriptionData subscription, DateTime now) {
- return (nextTimedPhase == null) ?
+ public static final PhaseEvent getNextPhaseEvent(String phaseName, SubscriptionData subscription, DateTime now, DateTime effectiveDate) {
+ return (phaseName == null) ?
null :
new PhaseEventData(new PhaseEventBuilder()
.setSubscriptionId(subscription.getId())
.setRequestedDate(now)
- .setEffectiveDate(nextTimedPhase.getStartPhase())
+ .setEffectiveDate(effectiveDate)
.setProcessedDate(now)
.setActiveVersion(subscription.getActiveVersion())
- .setPhaseName(nextTimedPhase.getPhase().getName()));
+ .setPhaseName(phaseName));
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
index d6f390e..3f033a4 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
@@ -16,10 +16,10 @@
package com.ning.billing.entitlement.events.user;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
import com.ning.billing.entitlement.events.EventBase;
+import org.joda.time.DateTime;
+
+import java.util.UUID;
public class ApiEventBase extends EventBase implements ApiEvent {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBuilder.java
index cd3857e..2ff026b 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBuilder.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBuilder.java
@@ -29,7 +29,7 @@ public class ApiEventBuilder extends EventBaseBuilder<ApiEventBuilder> {
super();
}
- public ApiEventBuilder(EventBaseBuilder<ApiEventBuilder> base) {
+ public ApiEventBuilder(EventBaseBuilder<?> base) {
super(base);
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java
index c28941e..b994899 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java
@@ -20,6 +20,10 @@ import com.ning.billing.entitlement.api.user.SubscriptionTransition.Subscription
public enum ApiEventType {
+ MIGRATE_ENTITLEMENT {
+ @Override
+ public SubscriptionTransitionType getSubscriptionTransitionType() { return SubscriptionTransitionType.MIGRATE_ENTITLEMENT; }
+ },
CREATE {
@Override
public SubscriptionTransitionType getSubscriptionTransitionType() { return SubscriptionTransitionType.CREATE; }
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 4284181..ab04700 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
@@ -16,14 +16,15 @@
package com.ning.billing.entitlement.glue;
-import org.skife.config.ConfigurationObjectFactory;
-
import com.google.inject.AbstractModule;
import com.ning.billing.config.EntitlementConfig;
+import com.ning.billing.entitlement.alignment.MigrationPlanAligner;
import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.api.EntitlementService;
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.test.DefaultEntitlementTestApi;
import com.ning.billing.entitlement.api.test.EntitlementTestApi;
import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
@@ -32,10 +33,11 @@ import com.ning.billing.entitlement.api.user.SubscriptionApiService;
import com.ning.billing.entitlement.engine.core.DefaultApiEventProcessor;
import com.ning.billing.entitlement.engine.core.Engine;
import com.ning.billing.entitlement.engine.core.EventNotifier;
-import com.ning.billing.entitlement.engine.dao.EntitlementSqlDao;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
-import com.ning.billing.util.clock.DefaultClock;
+import com.ning.billing.entitlement.engine.dao.EntitlementSqlDao;
import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.DefaultClock;
+import org.skife.config.ConfigurationObjectFactory;
@@ -64,9 +66,11 @@ public class EntitlementModule extends AbstractModule {
bind(EntitlementService.class).to(Engine.class).asEagerSingleton();
bind(Engine.class).asEagerSingleton();
bind(PlanAligner.class).asEagerSingleton();
+ bind(MigrationPlanAligner.class).asEagerSingleton();
bind(EntitlementTestApi.class).to(DefaultEntitlementTestApi.class).asEagerSingleton();
bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
bind(EntitlementBillingApi.class).to(DefaultEntitlementBillingApi.class).asEagerSingleton();
+ bind(EntitlementMigrationApi.class).to(DefaultEntitlementMigrationApi.class).asEagerSingleton();
}
@Override
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
index f79666e..4540ad8 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
@@ -3,7 +3,7 @@ CREATE TABLE events (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
event_id char(36) NOT NULL,
event_type varchar(9) NOT NULL,
- user_type varchar(10) DEFAULT NULL,
+ user_type varchar(25) DEFAULT NULL,
created_dt datetime NOT NULL,
updated_dt datetime NOT NULL,
requested_dt datetime NOT NULL,
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg
index cb15e9b..d9f26c2 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/BundleSqlDao.sql.stg
@@ -14,6 +14,12 @@ insertBundle() ::= <<
);
>>
+removeBundle(id) ::= <<
+ delete from bundles
+ where
+ id = :id
+ ;
+>>
getBundleFromId(id) ::= <<
select
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg
index a3b677a..31e9eaf 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EventSqlDao.sql.stg
@@ -96,6 +96,13 @@ insertEvent() ::= <<
);
>>
+removeEvents(subscription_id) ::= <<
+ delete from events
+ where
+ subscription_id = :subscription_id
+ ;
+>>
+
insertClaimedHistory(sequence_id, owner_id, hostname, claimed_dt, event_id) ::= <<
insert into claimed_events (
sequence_id
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg
index 094bdf1..bb7400b 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.sql.stg
@@ -22,6 +22,12 @@ insertSubscription() ::= <<
);
>>
+removeSubscription(id) ::= <<
+ delete from subscriptions
+ where id = :id
+ ;
+>>
+
getSubscriptionFromId(id) ::= <<
select
id
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
index b14bf38..6bee471 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
@@ -16,20 +16,16 @@
package com.ning.billing.entitlement.api;
-import java.util.EmptyStackException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Stack;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
import com.google.common.eventbus.Subscribe;
import com.ning.billing.entitlement.api.user.SubscriptionTransition;
import com.ning.billing.util.eventbus.EventBus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
public class ApiTestListener {
@@ -40,6 +36,7 @@ public class ApiTestListener {
private volatile boolean completed;
public enum NextEvent {
+ MIGRATE_ENTITLEMENT,
CREATE,
CHANGE,
CANCEL,
@@ -56,6 +53,9 @@ public class ApiTestListener {
@Subscribe
public void handleEntitlementEvent(SubscriptionTransition event) {
switch (event.getTransitionType()) {
+ case MIGRATE_ENTITLEMENT:
+ subscriptionMigrated(event);
+ break;
case CREATE:
subscriptionCreated(event);
break;
@@ -139,6 +139,12 @@ public class ApiTestListener {
}
+ public void subscriptionMigrated(SubscriptionTransition migrated) {
+ log.debug("-> Got event MIGRATED");
+ assertEqualsNicely(NextEvent.MIGRATE_ENTITLEMENT);
+ notifyIfStackEmpty();
+ }
+
public void subscriptionCreated(SubscriptionTransition created) {
log.debug("-> Got event CREATED");
assertEqualsNicely(NextEvent.CREATE);
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
new file mode 100644
index 0000000..271de3c
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
@@ -0,0 +1,371 @@
+/*
+ * 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.migration;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+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.PlanPhaseSpecifier;
+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.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApiException;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementAccountMigration;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementBundleMigration;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementSubscriptionMigration;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi.EntitlementSubscriptionMigrationCase;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.entitlement.glue.MockEngineModuleSql;
+
+public abstract class TestMigration extends TestApiBase {
+
+
+ public void testSingleBasePlan() {
+
+ try {
+ DateTime beforeMigration = clock.getUTCNow();
+ EntitlementAccountMigration toBeMigrated = createAccountWithRegularBasePlan();
+ DateTime afterMigration = clock.getUTCNow();
+
+ testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
+ migrationApi.migrate(toBeMigrated);
+ assertTrue(testListener.isCompleted(5000));
+
+ List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
+ assertEquals(bundles.size(), 1);
+ SubscriptionBundle bundle = bundles.get(0);
+
+ List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(bundle.getId());
+ assertEquals(subscriptions.size(), 1);
+ Subscription subscription = subscriptions.get(0);
+ assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
+ assertEquals(subscription.getEndDate(), null);
+ assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
+ assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-annual");
+ } catch (EntitlementMigrationApiException e) {
+ Assert.fail("", e);
+ }
+ }
+
+
+ public void testSingleBasePlanFutureCancelled() {
+
+ try {
+
+ DateTime beforeMigration = clock.getUTCNow();
+ EntitlementAccountMigration toBeMigrated = createAccountWithRegularBasePlanFutreCancelled();
+ DateTime afterMigration = clock.getUTCNow();
+
+ testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
+ migrationApi.migrate(toBeMigrated);
+ assertTrue(testListener.isCompleted(5000));
+
+ List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
+ assertEquals(bundles.size(), 1);
+ SubscriptionBundle bundle = bundles.get(0);
+ //assertEquals(bundle.getStartDate(), effectiveDate);
+
+ List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(bundle.getId());
+ assertEquals(subscriptions.size(), 1);
+ Subscription subscription = subscriptions.get(0);
+ assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
+ assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
+ assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-annual");
+
+ testListener.pushExpectedEvent(NextEvent.CANCEL);
+ Duration oneYear = getDurationYear(1);
+ clock.setDeltaFromReality(oneYear, 0);
+ assertTrue(testListener.isCompleted(5000));
+
+ assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
+ assertNotNull(subscription.getEndDate());
+ assertTrue(subscription.getEndDate().isAfterNow());
+ assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPhase(), null);
+ assertEquals(subscription.getState(), SubscriptionState.CANCELLED);
+ assertNull(subscription.getCurrentPlan());
+
+ } catch (EntitlementMigrationApiException e) {
+ Assert.fail("", e);
+ }
+ }
+
+ public void testSingleBasePlanWithPendingPhase() {
+
+ try {
+ DateTime beforeMigration = clock.getUTCNow();
+ final DateTime trialDate = clock.getUTCNow().minusDays(10);
+ EntitlementAccountMigration toBeMigrated = createAccountFuturePendingPhase(trialDate);
+ DateTime afterMigration = clock.getUTCNow();
+
+ testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
+ migrationApi.migrate(toBeMigrated);
+ assertTrue(testListener.isCompleted(5000));
+
+ List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
+ assertEquals(bundles.size(), 1);
+ SubscriptionBundle bundle = bundles.get(0);
+
+ List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(bundle.getId());
+ assertEquals(subscriptions.size(), 1);
+ Subscription subscription = subscriptions.get(0);
+
+ assertEquals(subscription.getStartDate(), trialDate);
+ assertEquals(subscription.getEndDate(), null);
+ assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.TRIAL);
+ assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-monthly");
+
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ Duration thirtyDays = getDurationDay(30);
+ clock.setDeltaFromReality(thirtyDays, 0);
+ assertTrue(testListener.isCompleted(5000));
+
+ assertEquals(subscription.getStartDate(), trialDate);
+ assertEquals(subscription.getEndDate(), null);
+ assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
+ assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-monthly");
+ assertEquals(subscription.getCurrentPhase().getName(), "assault-rifle-monthly-evergreen");
+
+ } catch (EntitlementMigrationApiException e) {
+ Assert.fail("", e);
+ }
+ }
+
+
+ public void testSingleBasePlanWithPendingChange() {
+
+ try {
+ DateTime beforeMigration = clock.getUTCNow();
+ EntitlementAccountMigration toBeMigrated = createAccountFuturePendingChange();
+ DateTime afterMigration = clock.getUTCNow();
+
+ testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT);
+ migrationApi.migrate(toBeMigrated);
+ assertTrue(testListener.isCompleted(5000));
+
+ List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(toBeMigrated.getAccountKey());
+ assertEquals(bundles.size(), 1);
+ SubscriptionBundle bundle = bundles.get(0);
+
+ List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(bundle.getId());
+ assertEquals(subscriptions.size(), 1);
+ Subscription subscription = subscriptions.get(0);
+ assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
+ assertEquals(subscription.getEndDate(), null);
+ assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+ assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
+ assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-monthly");
+
+ testListener.pushExpectedEvent(NextEvent.CHANGE);
+ Duration oneMonth = getDurationMonth(1);
+ clock.setDeltaFromReality(oneMonth, 0);
+ assertTrue(testListener.isCompleted(5000));
+
+ assertDateWithin(subscription.getStartDate(), beforeMigration, afterMigration);
+ assertEquals(subscription.getEndDate(), null);
+ assertEquals(subscription.getCurrentPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME);
+
+ assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN);
+ assertEquals(subscription.getState(), SubscriptionState.ACTIVE);
+ assertEquals(subscription.getCurrentPlan().getName(), "shotgun-annual");
+
+ } catch (EntitlementMigrationApiException e) {
+ Assert.fail("", e);
+ }
+ }
+
+
+ private EntitlementAccountMigration createAccountWithSingleBasePlan(final List<EntitlementSubscriptionMigrationCase> cases) {
+
+ return new EntitlementAccountMigration() {
+
+ private final UUID accountId = UUID.randomUUID();
+
+ @Override
+ public EntitlementBundleMigration[] getBundles() {
+ List<EntitlementBundleMigration> bundles = new ArrayList<EntitlementBundleMigration>();
+ EntitlementBundleMigration bundle0 = new EntitlementBundleMigration() {
+
+ @Override
+ public EntitlementSubscriptionMigration[] getSubscriptions() {
+ EntitlementSubscriptionMigration subscription = new EntitlementSubscriptionMigration() {
+ @Override
+ public EntitlementSubscriptionMigrationCase[] getSubscriptionCases() {
+ return cases.toArray(new EntitlementSubscriptionMigrationCase[cases.size()]);
+ }
+ @Override
+ public ProductCategory getCategory() {
+ return ProductCategory.BASE;
+ }
+ };
+ EntitlementSubscriptionMigration[] result = new EntitlementSubscriptionMigration[1];
+ result[0] = subscription;
+ return result;
+ }
+ @Override
+ public String getBundleKey() {
+ return "12345";
+ }
+ };
+ bundles.add(bundle0);
+ return bundles.toArray(new EntitlementBundleMigration[bundles.size()]);
+ }
+
+ @Override
+ public UUID getAccountKey() {
+ return accountId;
+ }
+ };
+ }
+
+ private EntitlementAccountMigration createAccountWithRegularBasePlan() {
+ List<EntitlementSubscriptionMigrationCase> cases = new LinkedList<EntitlementSubscriptionMigrationCase>();
+ cases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return clock.getUTCNow().minusMonths(3);
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return null;
+ }
+ });
+ return createAccountWithSingleBasePlan(cases);
+ }
+
+ private EntitlementAccountMigration createAccountWithRegularBasePlanFutreCancelled() {
+ List<EntitlementSubscriptionMigrationCase> cases = new LinkedList<EntitlementSubscriptionMigrationCase>();
+ final DateTime effectiveDate = clock.getUTCNow().minusMonths(3);
+ cases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return effectiveDate.plusYears(1);
+ }
+ });
+ return createAccountWithSingleBasePlan(cases);
+ }
+
+
+ private EntitlementAccountMigration createAccountFuturePendingPhase(final DateTime trialDate) {
+ List<EntitlementSubscriptionMigrationCase> cases = new LinkedList<EntitlementSubscriptionMigrationCase>();
+ cases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.TRIAL);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return trialDate;
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return trialDate.plusDays(30);
+ }
+ });
+ cases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return trialDate.plusDays(30);
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return null;
+ }
+ });
+ return createAccountWithSingleBasePlan(cases);
+ }
+
+ private EntitlementAccountMigration createAccountFuturePendingChange() {
+ List<EntitlementSubscriptionMigrationCase> cases = new LinkedList<EntitlementSubscriptionMigrationCase>();
+ final DateTime effectiveDate = clock.getUTCNow().minusDays(10);
+ cases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return effectiveDate.plusMonths(1);
+ }
+ });
+ cases.add(new EntitlementSubscriptionMigrationCase() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifer() {
+ return new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN);
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return effectiveDate.plusMonths(1).plusDays(1);
+ }
+ @Override
+ public DateTime getCancelledDate() {
+ return null;
+ }
+ });
+ return createAccountWithSingleBasePlan(cases);
+ }
+
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationMemory.java
new file mode 100644
index 0000000..05d6fb5
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationMemory.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.entitlement.api.migration;
+
+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;
+
+public class TestMigrationMemory extends TestMigration {
+ @Override
+ protected Injector getInjector() {
+ return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleMemory());
+ }
+
+ @Override
+ @Test(enabled=true, groups="fast")
+ public void testSingleBasePlan() {
+ super.testSingleBasePlan();
+ }
+
+ @Override
+ @Test(enabled=true, groups="fast")
+ public void testSingleBasePlanFutureCancelled() {
+ super.testSingleBasePlanFutureCancelled();
+ }
+
+ @Override
+ @Test(enabled=true, groups="fast")
+ public void testSingleBasePlanWithPendingPhase() {
+ super.testSingleBasePlanWithPendingPhase();
+ }
+
+ @Override
+ @Test(enabled=true, groups="fast")
+ public void testSingleBasePlanWithPendingChange() {
+ super.testSingleBasePlanWithPendingChange();
+ }
+}
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
new file mode 100644
index 0000000..b3eb168
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigrationSql.java
@@ -0,0 +1,56 @@
+/*
+ * 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.migration;
+
+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;
+
+public class TestMigrationSql extends TestMigration {
+
+ @Override
+ protected Injector getInjector() {
+ return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
+ }
+
+ @Override
+ @Test(enabled=true, groups="sql")
+ public void testSingleBasePlan() {
+ super.testSingleBasePlan();
+ }
+
+ @Override
+ @Test(enabled=true, groups="sql")
+ public void testSingleBasePlanFutureCancelled() {
+ super.testSingleBasePlanFutureCancelled();
+ }
+
+ @Override
+ @Test(enabled=true, groups="sql")
+ public void testSingleBasePlanWithPendingPhase() {
+ super.testSingleBasePlanWithPendingPhase();
+ }
+
+ @Override
+ @Test(enabled=true, groups="sql")
+ public void testSingleBasePlanWithPendingChange() {
+ super.testSingleBasePlanWithPendingChange();
+ }
+}
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 09a70f2..3326bc8 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,27 +17,28 @@
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 java.util.List;
-
+import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+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.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.util.clock.DefaultClock;
+import com.ning.billing.entitlement.api.TestApiBase;
+import java.util.List;
-public abstract class TestUserApiCancel extends TestUserApiBase {
+public abstract class TestUserApiCancel extends TestApiBase {
- protected void testCancelSubscriptionIMMReal() {
+ protected void testCancelSubscriptionIMM() {
log.info("Starting testCancelSubscriptionIMM");
@@ -79,7 +80,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
}
- protected void testCancelSubscriptionEOTWithChargeThroughDateReal() {
+ protected void testCancelSubscriptionEOTWithChargeThroughDate() {
log.info("Starting testCancelSubscriptionEOTWithChargeThroughDate");
try {
@@ -131,7 +132,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
}
- protected void testCancelSubscriptionEOTWithNoChargeThroughDateReal() {
+ protected void testCancelSubscriptionEOTWithNoChargeThroughDate() {
log.info("Starting testCancelSubscriptionEOTWithNoChargeThroughDate");
@@ -175,7 +176,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
// Similar test to testCancelSubscriptionEOTWithChargeThroughDate except we uncancel and check things
// are as they used to be and we can move forward without hitting cancellation
//
- protected void testUncancelReal() {
+ protected void testUncancel() {
log.info("Starting testUncancel");
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 66cd35a..630d925 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,11 @@
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 TestUserApiCancelMemory extends TestUserApiCancel {
@@ -31,23 +30,27 @@ public class TestUserApiCancelMemory extends TestUserApiCancel {
return Guice.createInjector(Stage.PRODUCTION, new MockEngineModuleMemory());
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testCancelSubscriptionIMM() {
- invokeRealMethod(this);
+ super.testCancelSubscriptionIMM();
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testCancelSubscriptionEOTWithChargeThroughDate() {
- invokeRealMethod(this);
+ super.testCancelSubscriptionEOTWithChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testCancelSubscriptionEOTWithNoChargeThroughDate() {
- invokeRealMethod(this);
+ super.testCancelSubscriptionEOTWithNoChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testUncancel() {
- invokeRealMethod(this);
+ super.testUncancel();
}
}
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 83d4d8e..187c080 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,11 @@
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 TestUserApiCancelSql extends TestUserApiCancel {
@@ -48,24 +47,28 @@ public class TestUserApiCancelSql extends TestUserApiCancel {
}
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testCancelSubscriptionIMM() {
- invokeRealMethod(this);
+ super.testCancelSubscriptionIMM();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testCancelSubscriptionEOTWithChargeThroughDate() {
- invokeRealMethod(this);
+ super.testCancelSubscriptionEOTWithChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testCancelSubscriptionEOTWithNoChargeThroughDate() {
- invokeRealMethod(this);
+ super.testCancelSubscriptionEOTWithNoChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testUncancel() {
- invokeRealMethod(this);
+ super.testUncancel();
}
}
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 14a46aa..dc6567f 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
@@ -34,12 +34,14 @@ 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.events.EntitlementEvent;
import com.ning.billing.entitlement.events.user.ApiEvent;
import com.ning.billing.util.clock.DefaultClock;
-public abstract class TestUserApiChangePlan extends TestUserApiBase {
+public abstract class TestUserApiChangePlan extends TestApiBase {
@@ -59,7 +61,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
- protected void testChangePlanBundleAlignEOTWithNoChargeThroughDateReal() {
+ protected void testChangePlanBundleAlignEOTWithNoChargeThroughDate() {
tChangePlanBundleAlignEOTWithNoChargeThroughDate("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, "Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
}
@@ -98,7 +100,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
}
- protected void testChangePlanBundleAlignEOTWithChargeThroughDateReal() {
+ protected void testChangePlanBundleAlignEOTWithChargeThroughDate() {
testChangePlanBundleAlignEOTWithChargeThroughDate("Shotgun", BillingPeriod.ANNUAL, "gunclubDiscount", "Pistol", BillingPeriod.ANNUAL, "gunclubDiscount");
}
@@ -163,7 +165,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
}
- protected void testChangePlanBundleAlignIMMReal() {
+ protected void testChangePlanBundleAlignIMM() {
tChangePlanBundleAlignIMM("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, "Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
}
@@ -205,7 +207,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
}
- protected void testChangePlanChangePlanAlignEOTWithChargeThroughDateReal() {
+ protected void testChangePlanChangePlanAlignEOTWithChargeThroughDate() {
tChangePlanChangePlanAlignEOTWithChargeThroughDate("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, "Assault-Rifle", BillingPeriod.ANNUAL, "rescue");
}
@@ -286,7 +288,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
}
}
- protected void testMultipleChangeLastIMMReal() {
+ protected void testMultipleChangeLastIMM() {
try {
SubscriptionData subscription = createSubscription("Assault-Rifle", BillingPeriod.MONTHLY, "gunclubDiscount");
@@ -333,7 +335,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
}
}
- protected void testMultipleChangeLastEOTReal() {
+ protected void testMultipleChangeLastEOT() {
try {
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 341b9b6..aecaaac 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,11 @@
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 TestUserApiChangePlanMemory extends TestUserApiChangePlan {
@@ -31,35 +30,40 @@ public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testChangePlanBundleAlignEOTWithNoChargeThroughDate() {
- invokeRealMethod(this);
+ super.testChangePlanBundleAlignEOTWithNoChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testChangePlanBundleAlignEOTWithChargeThroughDate() {
- invokeRealMethod(this);
+ super.testChangePlanBundleAlignEOTWithChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testChangePlanBundleAlignIMM() {
- invokeRealMethod(this);
+ super.testChangePlanBundleAlignIMM();
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testMultipleChangeLastIMM() {
- invokeRealMethod(this);
+ super.testMultipleChangeLastIMM();
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testMultipleChangeLastEOT() {
- invokeRealMethod(this);
+ super.testMultipleChangeLastEOT();
}
// Set to false until we implement rescue example.
+ @Override
@Test(enabled=false, groups={"fast"})
public void testChangePlanChangePlanAlignEOTWithChargeThroughDate() {
- invokeRealMethod(this);
+ super.testChangePlanChangePlanAlignEOTWithChargeThroughDate();
}
-
}
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 2ccf83f..f5ad803 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,11 @@
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 TestUserApiChangePlanSql extends TestUserApiChangePlan {
@@ -53,35 +52,41 @@ public class TestUserApiChangePlanSql extends TestUserApiChangePlan {
}
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testChangePlanBundleAlignEOTWithNoChargeThroughDate() {
- invokeRealMethod(this);
+ super.testChangePlanBundleAlignEOTWithNoChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testChangePlanBundleAlignEOTWithChargeThroughDate() {
- invokeRealMethod(this);
+ super.testChangePlanBundleAlignEOTWithChargeThroughDate();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testChangePlanBundleAlignIMM() {
- invokeRealMethod(this);
+ super.testChangePlanBundleAlignIMM();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testMultipleChangeLastIMM() {
- invokeRealMethod(this);
+ super.testMultipleChangeLastIMM();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testMultipleChangeLastEOT() {
- invokeRealMethod(this);
+ super.testMultipleChangeLastEOT();
}
// rescue not implemented yet
+ @Override
@Test(enabled=false, groups={"sql"})
public void testChangePlanChangePlanAlignEOTWithChargeThroughDate() {
- invokeRealMethod(this);
+ super.testChangePlanChangePlanAlignEOTWithChargeThroughDate();
}
}
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 7c14390..ff55ca0 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
@@ -16,12 +16,12 @@
package com.ning.billing.entitlement.api.user;
+
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
-
import org.joda.time.DateTime;
import org.testng.Assert;
@@ -31,16 +31,16 @@ 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.events.EntitlementEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.util.clock.DefaultClock;
-public abstract class TestUserApiCreate extends TestUserApiBase {
+public abstract class TestUserApiCreate extends TestApiBase {
-
- protected void testCreateWithRequestedDateReal() {
+ public void testCreateWithRequestedDate() {
log.info("Starting testCreateWithRequestedDate");
try {
@@ -56,7 +56,8 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CREATE);
- SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, null, requestedDate);
+ SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+ getProductSpecifier(productName, planSetName, term, null), requestedDate);
assertNotNull(subscription);
assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
@@ -71,7 +72,7 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
}
}
- protected void testCreateWithInitialPhaseReal() {
+ protected void testCreateWithInitialPhase() {
log.info("Starting testCreateWithInitialPhase");
try {
@@ -84,7 +85,8 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CREATE);
- SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, PhaseType.EVERGREEN, clock.getUTCNow());
+ SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+ getProductSpecifier(productName, planSetName, term, PhaseType.EVERGREEN), clock.getUTCNow());
assertNotNull(subscription);
assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
@@ -110,7 +112,7 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
}
}
- protected void testSimpleCreateSubscriptionReal() {
+ protected void testSimpleCreateSubscription() {
log.info("Starting testSimpleCreateSubscription");
try {
@@ -123,7 +125,9 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CREATE);
- SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, null, clock.getUTCNow());
+ SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+ getProductSpecifier(productName, planSetName, term, null),
+ clock.getUTCNow());
assertNotNull(subscription);
assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
@@ -174,7 +178,7 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
}
- protected void testSimpleSubscriptionThroughPhasesReal() {
+ protected void testSimpleSubscriptionThroughPhases() {
log.info("Starting testSimpleSubscriptionThroughPhases");
try {
@@ -188,7 +192,8 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CREATE);
// CREATE SUBSCRIPTION
- SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, null, clock.getUTCNow());
+ SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+ getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow());
assertNotNull(subscription);
PlanPhase currentPhase = subscription.getCurrentPhase();
@@ -224,7 +229,7 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
}
}
- protected void testSubscriptionWithAddOnReal() {
+ protected void testSubscriptionWithAddOn() {
log.info("Starting testSubscriptionWithAddOn");
try {
@@ -235,7 +240,8 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
testListener.pushExpectedEvent(NextEvent.CREATE);
- SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(), productName, term, planSetName, null, clock.getUTCNow());
+ SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+ getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow());
assertNotNull(subscription);
} catch (EntitlementUserApiException e) {
@@ -244,4 +250,5 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
}
+
}
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 d8a86c3..f4474f9 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,12 +16,11 @@
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 {
@@ -31,29 +30,30 @@ public class TestUserApiCreateMemory extends TestUserApiCreate {
return Guice.createInjector(Stage.PRODUCTION, new MockEngineModuleMemory());
}
+ @Override
@Test(enabled=true, groups={"fast"})
public void testCreateWithRequestedDate() {
- invokeRealMethod(this);
+ super.testCreateWithRequestedDate();
}
@Test(enabled=true, groups={"fast"})
public void testCreateWithInitialPhase() {
- invokeRealMethod(this);
+ super.testSimpleSubscriptionThroughPhases();
}
@Test(enabled=true, groups={"fast"})
public void testSimpleCreateSubscription() {
- invokeRealMethod(this);
+ super.testSimpleCreateSubscription();
}
@Test(enabled=true, groups={"fast"})
protected void testSimpleSubscriptionThroughPhases() {
- invokeRealMethod(this);
+ super.testSimpleSubscriptionThroughPhases();
}
@Test(enabled=false, groups={"fast"})
protected void testSubscriptionWithAddOn() {
- invokeRealMethod(this);
+ super.testSubscriptionWithAddOn();
}
}
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 3ff899b..8170b6d 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,12 +16,11 @@
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 {
@@ -30,29 +29,34 @@ public class TestUserApiCreateSql extends TestUserApiCreate {
return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testCreateWithRequestedDate() {
- invokeRealMethod(this);
+ super.testCreateWithRequestedDate();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testCreateWithInitialPhase() {
- invokeRealMethod(this);
+ super.testCreateWithInitialPhase();
}
+ @Override
@Test(enabled=true, groups={"sql"})
public void testSimpleCreateSubscription() {
- invokeRealMethod(this);
+ super.testSimpleCreateSubscription();
}
+ @Override
@Test(enabled=true, groups={"sql"})
protected void testSimpleSubscriptionThroughPhases() {
- invokeRealMethod(this);
+ super.testSimpleSubscriptionThroughPhases();
}
+ @Override
@Test(enabled=false, groups={"sql"})
protected void testSubscriptionWithAddOn() {
- invokeRealMethod(this);
+ super.testSubscriptionWithAddOn();
}
}
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 2476629..4a8b4b1 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,34 +16,32 @@
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.slf4j.Logger;
-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.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.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 TestUserApiBase {
+public class TestUserApiDemos extends TestApiBase {
@Override
protected Injector getInjector() {
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 bf7b717..c32b654 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,29 +16,28 @@
package com.ning.billing.entitlement.api.user;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-
-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.ErrorCode;
-import com.ning.billing.catalog.DefaultPriceListSet;
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.glue.MockEngineModuleMemory;
import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.UUID;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
-public class TestUserApiError extends TestUserApiBase {
+public class TestUserApiError extends TestApiBase {
@Override
@@ -88,7 +87,9 @@ public class TestUserApiError extends TestUserApiBase {
private void tCreateSubscriptionInternal(UUID bundleId, String productName,
BillingPeriod term, String planSet, ErrorCode expected) {
try {
- entitlementApi.createSubscription(bundleId, productName, term, planSet, null, clock.getUTCNow());
+ entitlementApi.createSubscription(bundleId,
+ getProductSpecifier(productName, planSet, term, null),
+ clock.getUTCNow());
assertFalse(true);
} catch (EntitlementUserApiException e) {
assertEquals(e.getCode(), expected.getCode());
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiPriceList.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiPriceList.java
index d6a2b12..a1a0dc7 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiPriceList.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiPriceList.java
@@ -17,8 +17,9 @@
package com.ning.billing.entitlement.api.user;
import com.google.inject.Injector;
+import com.ning.billing.entitlement.api.TestApiBase;
-public class TestUserApiPriceList extends TestUserApiBase {
+public class TestUserApiPriceList extends TestApiBase {
@Override
protected Injector getInjector() {
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 69fcd08..84d1031 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,26 +16,25 @@
package com.ning.billing.entitlement.api.user;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
-
-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.PlanPhase;
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.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 TestUserApiBase {
+public class TestUserApiScenarios extends TestApiBase {
@Override
protected Injector getInjector() {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java
index 434827a..83b981f 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java
@@ -16,9 +16,6 @@
package com.ning.billing.entitlement.engine.core;
-import java.util.Collection;
-import java.util.List;
-
import com.google.inject.Inject;
import com.ning.billing.config.EntitlementConfig;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
@@ -26,6 +23,9 @@ import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import com.ning.billing.util.clock.Clock;
+import java.util.Collection;
+import java.util.List;
+
public class MockApiEventProcessorMemory extends ApiEventProcessorBase {
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 f3f42f6..7fc8342 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
@@ -16,38 +16,31 @@
package com.ning.billing.entitlement.engine.dao;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.TreeSet;
-import java.util.UUID;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.google.inject.Inject;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.config.EntitlementConfig;
+
+import com.ning.billing.entitlement.api.migration.AccountMigrationData;
+import com.ning.billing.entitlement.api.migration.AccountMigrationData.BundleMigrationData;
+import com.ning.billing.entitlement.api.migration.AccountMigrationData.SubscriptionMigrationData;
import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionApiService;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
import com.ning.billing.entitlement.api.user.SubscriptionFactory;
+
import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
-import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.util.clock.Clock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlementDao {
@@ -102,6 +95,17 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
}
@Override
+ public SubscriptionBundle getSubscriptionBundleFromKey(String bundleKey) {
+ for (SubscriptionBundle cur : bundles) {
+ if (cur.getKey().equals(bundleKey)) {
+ return cur;
+ }
+ }
+ return null;
+ }
+
+
+ @Override
public SubscriptionBundle createSubscriptionBundle(SubscriptionBundleData bundle) {
bundles.add(bundle);
return getSubscriptionBundleFromId(bundle.getId());
@@ -349,4 +353,44 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
}
}
+
+ @Override
+ public void migrate(final UUID accountId, final AccountMigrationData accountData) {
+ synchronized(events) {
+
+ undoMigration(accountId);
+
+ for (BundleMigrationData curBundle : accountData.getData()) {
+ SubscriptionBundleData bundleData = curBundle.getData();
+ for (SubscriptionMigrationData curSubscription : curBundle.getSubscriptions()) {
+ SubscriptionData subData = curSubscription.getData();
+ for (EntitlementEvent curEvent : curSubscription.getInitialEvents()) {
+ events.add(curEvent);
+ }
+ subscriptions.add(subData);
+ }
+ bundles.add(bundleData);
+ }
+ }
+ }
+
+ @Override
+ public void undoMigration(UUID accountId) {
+ synchronized(events) {
+
+ List<SubscriptionBundle> allBundles = getSubscriptionBundleForAccount(accountId);
+ for (SubscriptionBundle bundle : allBundles) {
+ List<Subscription> allSubscriptions = getSubscriptions(bundle.getId());
+ for (Subscription subscription : allSubscriptions) {
+ List<EntitlementEvent> allEvents = getEventsForSubscription(subscription.getId());
+ for (EntitlementEvent event : allEvents) {
+ events.remove(event);
+ }
+ subscriptions.remove(subscription);
+ }
+ bundles.remove(bundle);
+ }
+ }
+
+ }
}
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 6f6d50d..2ebdea9 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,6 +16,10 @@
package com.ning.billing.entitlement.engine.dao;
+import com.google.inject.Inject;
+import com.ning.billing.config.EntitlementConfig;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
+import com.ning.billing.util.clock.Clock;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Transaction;
import org.skife.jdbi.v2.TransactionStatus;
@@ -23,14 +27,6 @@ import org.skife.jdbi.v2.sqlobject.SqlUpdate;
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.catalog.api.Catalog;
-import com.ning.billing.catalog.api.CatalogService;
-import com.ning.billing.config.EntitlementConfig;
-import com.ning.billing.entitlement.api.user.SubscriptionApiService;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory;
-import com.ning.billing.util.clock.Clock;
-
public class MockEntitlementDaoSql extends EntitlementSqlDao implements MockEntitlementDao {
private final ResetSqlDao resetDao;
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 75074ee..dc422a6 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
@@ -17,8 +17,8 @@
package com.ning.billing.entitlement.glue;
import com.ning.billing.catalog.glue.CatalogModule;
-import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.glue.EventBusModule;
public class MockEngineModule extends EntitlementModule {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
index b8ef041..c6ce269 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
@@ -17,10 +17,10 @@
package com.ning.billing.entitlement.glue;
-import com.ning.billing.entitlement.engine.core.MockApiEventProcessorMemory;
import com.ning.billing.entitlement.engine.core.EventNotifier;
-import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoMemory;
+import com.ning.billing.entitlement.engine.core.MockApiEventProcessorMemory;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoMemory;
public class MockEngineModuleMemory extends MockEngineModule {
@Override
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 afc8c06..f1cd237 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,15 +16,14 @@
package com.ning.billing.entitlement.glue;
-import org.skife.config.ConfigurationObjectFactory;
-import org.skife.jdbi.v2.DBI;
-
import com.ning.billing.dbi.DBIProvider;
import com.ning.billing.dbi.DbiConfig;
-import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoSql;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
-import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoSql;
import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.DBI;
public class MockEngineModuleSql extends MockEngineModule {
diff --git a/entitlement/src/test/resources/testInput.xml b/entitlement/src/test/resources/testInput.xml
index 740a903..01d7cb4 100644
--- a/entitlement/src/test/resources/testInput.xml
+++ b/entitlement/src/test/resources/testInput.xml
@@ -18,7 +18,7 @@
<!--
Use cases covered so far:
Tiered Product (Pistol/Shotgun/Assault-Rifle)
- Multiple change plan policies
+ Multiple changeEvent plan policies
Multiple PlanAlignment (see below, trial add-on alignments and rescue discount package)
Product transition rules
Add on (Scopes, Hoster)
invoice/pom.xml 38(+37 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 5bd70f4..3d7dc27 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-invoice</artifactId>
@@ -29,20 +29,56 @@
<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>
</dependency>
<dependency>
+ <groupId>com.mysql</groupId>
+ <artifactId>management</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.mysql</groupId>
+ <artifactId>management-dbfiles</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.0</version>
</dependency>
<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi</artifactId>
<version>2.27</version>
</dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>stringtemplate</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<build>
</build>
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
new file mode 100644
index 0000000..b7bc657
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.google.inject.Inject;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+
+public class DefaultInvoiceService implements InvoiceService {
+ private static final String INVOICE_SERVICE_NAME = "invoice-service";
+ private final InvoiceUserApi userApi;
+ private final InvoicePaymentApi paymentApi;
+
+ @Inject
+ public DefaultInvoiceService(InvoiceUserApi userApi, InvoicePaymentApi paymentApi) {
+ this.userApi = userApi;
+ this.paymentApi = paymentApi;
+ }
+
+ @Override
+ public String getName() {
+ return INVOICE_SERVICE_NAME;
+ }
+
+ @Override
+ public InvoiceUserApi getUserApi() {
+ return userApi;
+ }
+
+ @Override
+ public InvoicePaymentApi getPaymentApi() {
+ return paymentApi;
+ }
+
+ @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.INIT_SERVICE)
+ public void initialize() {
+ }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java
new file mode 100644
index 0000000..094e6f1
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api.user;
+
+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.InvoiceCreationNotification;
+
+public class DefaultInvoiceCreationNotification implements InvoiceCreationNotification {
+ private final UUID invoiceId;
+ private final UUID accountId;
+ private final BigDecimal amountOwed;
+ private final Currency currency;
+ private final DateTime invoiceCreationDate;
+
+ public DefaultInvoiceCreationNotification(UUID invoiceId, UUID accountId, BigDecimal amountOwed, Currency currency, DateTime invoiceCreationDate) {
+ this.invoiceId = invoiceId;
+ this.accountId = accountId;
+ this.amountOwed = amountOwed;
+ this.currency = currency;
+ this.invoiceCreationDate = invoiceCreationDate;
+ }
+
+ @Override
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ @Override
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ @Override
+ public BigDecimal getAmountOwed() {
+ return amountOwed;
+ }
+
+ @Override
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ @Override
+ public DateTime getInvoiceCreationDate() {
+ return invoiceCreationDate;
+ }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
new file mode 100644
index 0000000..22f4990
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api.user;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.invoice.dao.DefaultInvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.util.eventbus.EventBus;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.IDBI;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+public class DefaultInvoiceUserApi implements InvoiceUserApi {
+ private final InvoiceDao dao;
+
+ @Inject
+ public DefaultInvoiceUserApi(InvoiceDao dao) {
+ this.dao = dao;
+ }
+
+ @Override
+ public List<UUID> getInvoicesForPayment(DateTime targetDate, int numberOfDays) {
+ return dao.getInvoicesForPayment(targetDate.toDate(), numberOfDays);
+ }
+
+ @Override
+ public List<Invoice> getInvoicesByAccount(UUID accountId) {
+ return dao.getInvoicesByAccount(accountId.toString());
+ }
+
+ @Override
+ public Invoice getInvoice(UUID invoiceId) {
+ return dao.getById(invoiceId.toString());
+ }
+
+ @Override
+ public void paymentAttemptFailed(UUID invoiceId, UUID paymentId, DateTime paymentAttemptDate) {
+ dao.notifyFailedPayment(invoiceId.toString(), paymentId.toString(), paymentAttemptDate.toDate());
+ }
+
+ @Override
+ public void paymentAttemptSuccessful(UUID invoiceId, BigDecimal amount, Currency currency, UUID paymentId, DateTime paymentDate) {
+ dao.notifySuccessfulPayment(invoiceId.toString(), amount, currency.toString(), paymentId.toString(), paymentDate.toDate());
+ }
+}
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
new file mode 100644
index 0000000..1186456
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.dao;
+
+import com.google.inject.Inject;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceCreationNotification;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.user.DefaultInvoiceCreationNotification;
+import com.ning.billing.util.eventbus.EventBus;
+import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+public class DefaultInvoiceDao implements InvoiceDao {
+ private final InvoiceSqlDao invoiceDao;
+
+ private final EventBus eventBus;
+ private final static Logger log = LoggerFactory.getLogger(DefaultInvoiceDao.class);
+
+ @Inject
+ public DefaultInvoiceDao(IDBI dbi, EventBus eventBus) {
+ this.invoiceDao = dbi.onDemand(InvoiceSqlDao.class);
+ this.eventBus = eventBus;
+ }
+
+ @Override
+ public List<Invoice> getInvoicesByAccount(final String accountId) {
+ return invoiceDao.getInvoicesByAccount(accountId);
+ }
+
+ @Override
+ public List<Invoice> get() {
+ return invoiceDao.inTransaction(new Transaction<List<Invoice>, InvoiceSqlDao>() {
+ @Override
+ public List<Invoice> inTransaction(InvoiceSqlDao invoiceDao, TransactionStatus status) throws Exception {
+ List<Invoice> invoices = invoiceDao.get();
+
+ InvoiceItemSqlDao invoiceItemDao = invoiceDao.become(InvoiceItemSqlDao.class);
+ for (Invoice invoice : invoices) {
+ List<InvoiceItem> invoiceItems = invoiceItemDao.getInvoiceItemsByInvoice(invoice.getId().toString());
+ invoice.add(invoiceItems);
+ }
+
+ return invoices;
+ }
+ });
+ }
+
+ @Override
+ public Invoice getById(final String invoiceId) {
+ return invoiceDao.inTransaction(new Transaction<Invoice, InvoiceSqlDao>() {
+ @Override
+ public Invoice inTransaction(InvoiceSqlDao invoiceDao, TransactionStatus status) throws Exception {
+ Invoice invoice = invoiceDao.getById(invoiceId);
+
+ if (invoice != null) {
+ InvoiceItemSqlDao invoiceItemDao = invoiceDao.become(InvoiceItemSqlDao.class);
+ List<InvoiceItem> invoiceItems = invoiceItemDao.getInvoiceItemsByInvoice(invoiceId);
+ invoice.add(invoiceItems);
+ }
+
+ return invoice;
+ }
+ });
+ }
+
+ @Override
+ public void save(final Invoice invoice) {
+ invoiceDao.inTransaction(new Transaction<Void, InvoiceSqlDao>() {
+ @Override
+ public Void inTransaction(InvoiceSqlDao invoiceDao, TransactionStatus status) throws Exception {
+ Invoice currentInvoice = invoiceDao.getById(invoice.getId().toString());
+ invoiceDao.save(invoice);
+
+ List<InvoiceItem> invoiceItems = invoice.getItems();
+ InvoiceItemSqlDao invoiceItemDao = invoiceDao.become(InvoiceItemSqlDao.class);
+ invoiceItemDao.save(invoiceItems);
+
+ if (currentInvoice == null) {
+ InvoiceCreationNotification event;
+ event = new DefaultInvoiceCreationNotification(invoice.getId(), invoice.getAccountId(),
+ invoice.getAmountOutstanding(), invoice.getCurrency(),
+ invoice.getInvoiceDate());
+ eventBus.post(event);
+ } else {
+
+ }
+
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public List<Invoice> getInvoicesBySubscription(final String subscriptionId) {
+ return invoiceDao.inTransaction(new Transaction<List<Invoice>, InvoiceSqlDao>() {
+ @Override
+ public List<Invoice> inTransaction(InvoiceSqlDao invoiceDao, TransactionStatus status) throws Exception {
+ List<Invoice> invoices = invoiceDao.getInvoicesBySubscription(subscriptionId);
+
+ InvoiceItemSqlDao invoiceItemDao = invoiceDao.become(InvoiceItemSqlDao.class);
+ for (Invoice invoice : invoices) {
+ List<InvoiceItem> invoiceItems = invoiceItemDao.getInvoiceItemsByInvoice(invoice.getId().toString());
+ invoice.add(invoiceItems);
+ }
+
+ return invoices;
+ }
+ });
+ }
+
+ @Override
+ public List<UUID> getInvoicesForPayment(Date targetDate, int numberOfDays) {
+ return invoiceDao.getInvoicesForPayment(targetDate, numberOfDays);
+ }
+
+ @Override
+ public void notifySuccessfulPayment(String invoiceId, BigDecimal paymentAmount, String currency, String paymentId, Date paymentDate) {
+ invoiceDao.notifySuccessfulPayment(invoiceId, paymentAmount, currency, paymentId, paymentDate);
+ }
+
+ @Override
+ public void notifyFailedPayment(String invoiceId, String paymentId, Date paymentAttemptDate) {
+ invoiceDao.notifyFailedPayment(invoiceId, paymentId, paymentAttemptDate);
+ }
+
+ @Override
+ public void test() {
+ invoiceDao.test();
+ }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index 9abc12a..b59e4ed 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -16,32 +16,35 @@
package com.ning.billing.invoice.dao;
-import com.ning.billing.invoice.model.Invoice;
-import org.skife.jdbi.v2.sqlobject.Bind;
-import org.skife.jdbi.v2.sqlobject.BindBean;
-import org.skife.jdbi.v2.sqlobject.SqlQuery;
-import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
-import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
-
import java.math.BigDecimal;
+import java.util.Date;
import java.util.List;
+import java.util.UUID;
+import com.ning.billing.invoice.api.Invoice;
-@ExternalizedSqlViaStringTemplate3()
-@RegisterMapper(InvoiceMapper.class)
public interface InvoiceDao {
- @SqlQuery
- List<Invoice> getInvoicesByAccount(@Bind final String accountId);
+ void save(Invoice invoice);
+
+ Invoice getById(final String id);
+
+ List<Invoice> get();
+
+ List<Invoice> getInvoicesByAccount(final String accountId);
+
+ List<Invoice> getInvoicesBySubscription(final String subscriptionId);
- @SqlQuery
- Invoice getInvoice(@Bind final String invoiceId);
+ List<UUID> getInvoicesForPayment(final Date targetDate,
+ final int numberOfDays);
- @SqlUpdate
- void createInvoice(@BindBean final Invoice invoice);
+ void notifySuccessfulPayment(final String invoiceId,
+ final BigDecimal paymentAmount,
+ final String currency,
+ final String paymentId,
+ final Date paymentDate);
- @SqlUpdate
- void addPayment(@Bind final String invoiceId, @Bind final BigDecimal paymentAmount);
+ void notifyFailedPayment(final String invoiceId,
+ final String paymentId,
+ final Date paymentAttemptDate);
- @SqlQuery
- int test();
+ void test();
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.java
new file mode 100644
index 0000000..a89749e
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemSqlDao.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.invoice.dao;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import com.ning.billing.util.entity.EntityCollectionDao;
+import com.ning.billing.util.entity.EntityDao;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.*;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import java.lang.annotation.*;
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper(InvoiceItemSqlDao.InvoiceItemMapper.class)
+public interface InvoiceItemSqlDao extends EntityDao<InvoiceItem> {
+ @SqlQuery
+ List<InvoiceItem> getInvoiceItemsByInvoice(@Bind("invoiceId") final String invoiceId);
+
+ @SqlQuery
+ List<InvoiceItem> getInvoiceItemsByAccount(@Bind("accountId") final String accountId);
+
+ @SqlQuery
+ List<InvoiceItem> getInvoiceItemsBySubscription(@Bind("subscriptionId") final String subscriptionId);
+
+ @Override
+ @SqlUpdate
+ void save(@InvoiceItemBinder final InvoiceItem invoiceItem);
+
+ @SqlBatch
+ void save(@InvoiceItemBinder final List<InvoiceItem> items);
+
+ @BindingAnnotation(InvoiceItemBinder.InvoiceItemBinderFactory.class)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.PARAMETER})
+ public @interface InvoiceItemBinder {
+ public static class InvoiceItemBinderFactory implements BinderFactory {
+ public Binder build(Annotation annotation) {
+ return new Binder<InvoiceItemBinder, InvoiceItem>() {
+ public void bind(SQLStatement q, InvoiceItemBinder bind, InvoiceItem item) {
+ q.bind("id", item.getId().toString());
+ q.bind("invoiceId", item.getInvoiceId().toString());
+ q.bind("subscriptionId", item.getSubscriptionId().toString());
+ q.bind("startDate", item.getStartDate().toDate());
+ q.bind("endDate", item.getEndDate().toDate());
+ q.bind("description", item.getDescription());
+ q.bind("amount", item.getAmount());
+ q.bind("rate", item.getRate());
+ q.bind("currency", item.getCurrency().toString());
+ }
+ };
+ }
+ }
+ }
+
+ public static class InvoiceItemMapper implements ResultSetMapper<InvoiceItem> {
+ @Override
+ public InvoiceItem map(int index, ResultSet result, StatementContext context) throws SQLException {
+ UUID id = UUID.fromString(result.getString("id"));
+ UUID invoiceId = UUID.fromString(result.getString("invoice_id"));
+ UUID subscriptionId = UUID.fromString(result.getString("subscription_id"));
+ DateTime startDate = new DateTime(result.getTimestamp("start_date"));
+ DateTime endDate = new DateTime(result.getTimestamp("end_date"));
+ String description = result.getString("description");
+ BigDecimal amount = result.getBigDecimal("amount");
+ BigDecimal rate = result.getBigDecimal("rate");
+ Currency currency = Currency.valueOf(result.getString("currency"));
+
+ return new DefaultInvoiceItem(id, invoiceId, subscriptionId, startDate, endDate, description, amount, rate , currency);
+ }
+ }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
new file mode 100644
index 0000000..aa0051a
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.dao;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.util.UuidMapper;
+import com.ning.billing.util.entity.EntityDao;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+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.lang.annotation.*;
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+@ExternalizedSqlViaStringTemplate3()
+@RegisterMapper({UuidMapper.class, InvoiceSqlDao.InvoiceMapper.class})
+public interface InvoiceSqlDao extends EntityDao<Invoice>, Transactional<InvoiceSqlDao>, Transmogrifier, CloseMe {
+ @Override
+ @SqlUpdate
+ void save(@InvoiceBinder Invoice invoice);
+
+ @SqlQuery
+ List<Invoice> getInvoicesByAccount(@Bind("accountId") final String accountId);
+
+ @SqlQuery
+ List<Invoice> getInvoicesBySubscription(@Bind("subscriptionId") final String subscriptionId);
+
+ @SqlQuery
+ List<UUID> getInvoicesForPayment(@Bind("targetDate") final Date targetDate,
+ @Bind("numberOfDays") final int numberOfDays);
+
+ @SqlUpdate
+ void notifySuccessfulPayment(@Bind("invoiceId") final String invoiceId,
+ @Bind("amount") final BigDecimal paymentAmount,
+ @Bind("currency") final String currency,
+ @Bind("paymentId") final String paymentId,
+ @Bind("paymentDate") final Date paymentDate);
+
+ @SqlUpdate
+ void notifyFailedPayment(@Bind("invoiceId") final String invoiceId,
+ @Bind("paymentId") final String paymentId,
+ @Bind("paymentAttemptDate") final Date paymentAttemptDate);
+
+ @BindingAnnotation(InvoiceBinder.InvoiceBinderFactory.class)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.PARAMETER})
+ public @interface InvoiceBinder {
+ public static class InvoiceBinderFactory implements BinderFactory {
+ public Binder build(Annotation annotation) {
+ return new Binder<InvoiceBinder, Invoice>() {
+ public void bind(SQLStatement q, InvoiceBinder bind, Invoice invoice) {
+ q.bind("id", invoice.getId().toString());
+ q.bind("accountId", invoice.getAccountId().toString());
+ q.bind("invoiceDate", invoice.getInvoiceDate().toDate());
+ q.bind("targetDate", invoice.getTargetDate().toDate());
+ q.bind("amountPaid", invoice.getAmountPaid());
+ q.bind("amountOutstanding", invoice.getAmountOutstanding());
+ DateTime last_payment_date = invoice.getLastPaymentAttempt();
+ q.bind("lastPaymentAttempt", last_payment_date == null ? null : last_payment_date.toDate());
+ q.bind("currency", invoice.getCurrency().toString());
+ }
+ };
+ }
+ }
+ }
+
+ public static class InvoiceMapper implements ResultSetMapper<Invoice> {
+ @Override
+ public Invoice map(int index, ResultSet result, StatementContext context) throws SQLException {
+ UUID id = UUID.fromString(result.getString("id"));
+ UUID accountId = UUID.fromString(result.getString("account_id"));
+ DateTime invoiceDate = new DateTime(result.getTimestamp("invoice_date"));
+ DateTime targetDate = new DateTime(result.getTimestamp("target_date"));
+ BigDecimal amountPaid = result.getBigDecimal("amount_paid");
+ if (amountPaid == null) {
+ amountPaid = BigDecimal.ZERO;
+ }
+ Timestamp lastPaymentAttemptTimeStamp = result.getTimestamp("last_payment_attempt");
+ DateTime lastPaymentAttempt = lastPaymentAttemptTimeStamp == null ? null : new DateTime(lastPaymentAttemptTimeStamp);
+ Currency currency = Currency.valueOf(result.getString("currency"));
+
+ return new DefaultInvoice(id, accountId, invoiceDate, targetDate, currency, lastPaymentAttempt, amountPaid, new ArrayList<InvoiceItem>());
+ }
+ }
+}
+
diff --git a/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java b/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java
new file mode 100644
index 0000000..54990c5
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.glue;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.invoice.api.InvoicePaymentApi;
+import com.ning.billing.invoice.api.invoice.DefaultInvoicePaymentApi;
+import com.ning.billing.invoice.api.user.DefaultInvoiceUserApi;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.invoice.dao.DefaultInvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceDao;
+
+public class InvoiceModule extends AbstractModule {
+ private void installInvoiceDao() {
+ bind(InvoiceDao.class).to(DefaultInvoiceDao.class).asEagerSingleton();
+ }
+
+ protected void installInvoiceUserApi() {
+ bind(InvoiceUserApi.class).to(DefaultInvoiceUserApi.class).asEagerSingleton();
+ }
+
+ protected void installInvoicePaymentApi() {
+ bind(InvoicePaymentApi.class).to(DefaultInvoicePaymentApi.class).asEagerSingleton();
+ }
+
+ @Override
+ protected void configure() {
+ installInvoiceDao();
+ installInvoiceUserApi();
+ installInvoicePaymentApi();
+ }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java b/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java
index d141f27..949f711 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java
@@ -21,7 +21,7 @@ import org.joda.time.DateTime;
import java.math.BigDecimal;
-public abstract class BillingModeBase implements IBillingMode {
+public abstract class BillingModeBase implements BillingMode {
@Override
public BigDecimal calculateNumberOfBillingCycles(final DateTime startDate, final DateTime endDate, final DateTime targetDate, final int billingCycleDay, final BillingPeriod billingPeriod) throws InvalidDateSequenceException {
if (endDate.isBefore(startDate)) {throw new InvalidDateSequenceException();}
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 e8e2c78..142210b 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,7 @@
package com.ning.billing.invoice.model;
+
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
@@ -31,19 +32,21 @@ import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.entitlement.api.billing.BillingEvent;
-import com.ning.billing.entitlement.api.billing.BillingMode;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
import com.ning.billing.invoice.api.BillingEventSet;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
-public class DefaultInvoiceGenerator implements IInvoiceGenerator {
+public class DefaultInvoiceGenerator implements InvoiceGenerator {
private static final Logger log = LoggerFactory.getLogger(DefaultInvoiceGenerator.class);
@Override
public Invoice generateInvoice(final UUID accountId, final BillingEventSet events, final InvoiceItemList existingItems, final DateTime targetDate, final Currency targetCurrency) {
- if (events == null) {return new Invoice(accountId, targetCurrency);}
- if (events.size() == 0) {return new Invoice(accountId, targetCurrency);}
+ if (events == null) {return new DefaultInvoice(accountId, targetDate, targetCurrency);}
+ if (events.size() == 0) {return new DefaultInvoice(accountId, targetDate, targetCurrency);}
- Invoice invoice = new Invoice(accountId, targetCurrency);
- InvoiceItemList currentItems = generateInvoiceItems(events, invoice.getInvoiceId(), targetDate, targetCurrency);
- InvoiceItemList itemsToPost = reconcileInvoiceItems(invoice.getInvoiceId(), currentItems, existingItems);
+ DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, targetCurrency);
+ InvoiceItemList currentItems = generateInvoiceItems(events, invoice.getId(), targetDate, targetCurrency);
+ InvoiceItemList itemsToPost = reconcileInvoiceItems(invoice.getId(), currentItems, existingItems);
invoice.add(itemsToPost);
return invoice;
@@ -52,7 +55,7 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
private InvoiceItemList reconcileInvoiceItems(final UUID invoiceId, final InvoiceItemList currentInvoiceItems, final InvoiceItemList existingInvoiceItems) {
InvoiceItemList currentItems = new InvoiceItemList();
for (InvoiceItem item : currentInvoiceItems) {
- currentItems.add(new InvoiceItem(item, invoiceId));
+ currentItems.add(new DefaultInvoiceItem(item, invoiceId));
}
InvoiceItemList existingItems = (InvoiceItemList) existingInvoiceItems.clone();
@@ -116,14 +119,15 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
}
private void processEvent(UUID invoiceId, BillingEvent event, List<InvoiceItem> items, DateTime targetDate, Currency targetCurrency) {
- try {
- BigDecimal rate = event.getRecurringPrice(targetCurrency);
- BigDecimal invoiceItemAmount = calculateInvoiceItemAmount(event, targetDate, rate);
- IBillingMode billingMode = getBillingMode(event.getBillingMode());
- DateTime billThroughDate = billingMode.calculateEffectiveEndDate(event.getEffectiveDate(), targetDate, event.getBillCycleDay(), event.getBillingPeriod());
-
- addInvoiceItem(invoiceId, items, event, billThroughDate, invoiceItemAmount, rate, targetCurrency);
- } catch (CatalogApiException e) {
+ try {
+ //TODO: Jeff getPrice() -> getRecurringPrice()
+ BigDecimal rate = event.getRecurringPrice(targetCurrency);
+ BigDecimal invoiceItemAmount = calculateInvoiceItemAmount(event, targetDate, rate);
+ BillingMode billingMode = getBillingMode(event.getBillingMode());
+ DateTime billThroughDate = billingMode.calculateEffectiveEndDate(event.getEffectiveDate(), targetDate, event.getBillCycleDay(), event.getBillingPeriod());
+
+ addInvoiceItem(invoiceId, items, event, billThroughDate, invoiceItemAmount, rate, targetCurrency);
+ } catch (CatalogApiException e) {
log.error(String.format("Encountered a catalog error processing invoice %s for billing event on date %s",
invoiceId.toString(),
ISODateTimeFormat.basicDateTime().print(event.getEffectiveDate())), e);
@@ -131,15 +135,16 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
}
private void processEvents(UUID invoiceId, BillingEvent firstEvent, BillingEvent secondEvent, List<InvoiceItem> items, DateTime targetDate, Currency targetCurrency) {
- try {
- BigDecimal rate = firstEvent.getRecurringPrice(targetCurrency);
- BigDecimal invoiceItemAmount = calculateInvoiceItemAmount(firstEvent, secondEvent, targetDate, rate);
- IBillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
- DateTime billThroughDate = billingMode.calculateEffectiveEndDate(firstEvent.getEffectiveDate(), secondEvent.getEffectiveDate(), targetDate, firstEvent.getBillCycleDay(), firstEvent.getBillingPeriod());
-
- addInvoiceItem(invoiceId, items, firstEvent, billThroughDate, invoiceItemAmount, rate, targetCurrency);
- } catch (CatalogApiException e) {
- log.error(String.format("Encountered a catalog error processing invoice %s for billing event on date %s",
+ //TODO: Jeff getPrice() -> getRecurringPrice()
+ try {
+ BigDecimal rate = firstEvent.getRecurringPrice(targetCurrency);
+ BigDecimal invoiceItemAmount = calculateInvoiceItemAmount(firstEvent, secondEvent, targetDate, rate);
+ BillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
+ DateTime billThroughDate = billingMode.calculateEffectiveEndDate(firstEvent.getEffectiveDate(), secondEvent.getEffectiveDate(), targetDate, firstEvent.getBillCycleDay(), firstEvent.getBillingPeriod());
+
+ addInvoiceItem(invoiceId, items, firstEvent, billThroughDate, invoiceItemAmount, rate, targetCurrency);
+ } catch (CatalogApiException e) {
+ log.error(String.format("Encountered a catalog error processing invoice %s for billing event on date %s",
invoiceId.toString(),
ISODateTimeFormat.basicDateTime().print(firstEvent.getEffectiveDate())), e);
}
@@ -147,13 +152,13 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
private void addInvoiceItem(UUID invoiceId, List<InvoiceItem> items, BillingEvent event, DateTime billThroughDate, BigDecimal amount, BigDecimal rate, Currency currency) {
if (!(amount.compareTo(BigDecimal.ZERO) == 0)) {
- InvoiceItem item = new InvoiceItem(invoiceId, event.getSubscriptionId(), event.getEffectiveDate(), billThroughDate, event.getDescription(), amount, rate, currency);
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, event.getSubscriptionId(), event.getEffectiveDate(), billThroughDate, event.getDescription(), amount, rate, currency);
items.add(item);
}
}
private BigDecimal calculateInvoiceItemAmount(BillingEvent event, DateTime targetDate, BigDecimal rate){
- IBillingMode billingMode = getBillingMode(event.getBillingMode());
+ BillingMode billingMode = getBillingMode(event.getBillingMode());
DateTime startDate = event.getEffectiveDate();
int billingCycleDay = event.getBillCycleDay();
BillingPeriod billingPeriod = event.getBillingPeriod();
@@ -169,7 +174,7 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
}
private BigDecimal calculateInvoiceItemAmount(BillingEvent firstEvent, BillingEvent secondEvent, DateTime targetDate, BigDecimal rate) {
- IBillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
+ BillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
DateTime startDate = firstEvent.getEffectiveDate();
int billingCycleDay = firstEvent.getBillCycleDay();
BillingPeriod billingPeriod = firstEvent.getBillingPeriod();
@@ -186,8 +191,8 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
}
}
- private IBillingMode getBillingMode(BillingMode billingMode) {
- switch (billingMode) {
+ private BillingMode getBillingMode(BillingModeType billingModeType) {
+ switch (billingModeType) {
case IN_ADVANCE:
return new InAdvanceBillingMode();
default:
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
index 679c735..fb82f06 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
@@ -16,6 +16,8 @@
package com.ning.billing.invoice.model;
+import com.ning.billing.invoice.api.InvoiceItem;
+
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
new file mode 100644
index 0000000..490d075
--- /dev/null
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
@@ -0,0 +1,40 @@
+group InvoiceItemDao;
+
+getById() ::= <<
+ SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+ FROM invoice_items
+ WHERE id = :id;
+>>
+
+getInvoiceItemsByInvoice() ::= <<
+ SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+ FROM invoice_items
+ WHERE invoice_id = :invoiceId;
+>>
+
+getInvoiceItemsByAccount() ::= <<
+ SELECT ii.id, ii.invoice_id, ii.subscription_id, ii.start_date, ii.end_date, ii.description, ii.amount, ii.rate, ii.currency
+ FROM invoice_items ii
+ INNER JOIN invoices i ON i.id = ii.invoice_id
+ WHERE i.account_id = :accountId;
+>>
+
+getInvoiceItemsBySubscription() ::= <<
+ SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+ FROM invoice_items
+ WHERE subscription_id = :subscriptionId;
+>>
+
+save() ::= <<
+ INSERT INTO invoice_items(id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency)
+ VALUES(:id, :invoiceId, :subscriptionId, :startDate, :endDate, :description, :amount, :rate, :currency)
+ ON DUPLICATE KEY UPDATE
+ start_date = :startDate, end_date = :endDate, description = :description,
+ amount = :amount, rate = :rate, currency = :currency''
+>>
+
+test() ::= <<
+ SELECT 1
+ FROM invoice_items;
+>>
+;
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
new file mode 100644
index 0000000..0323040
--- /dev/null
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
@@ -0,0 +1,76 @@
+group InvoiceDao;
+
+get() ::= <<
+ SELECT i.id, i.account_id, i.invoice_date, i.target_date, i.currency, SUM(ii.amount) AS amount,
+ SUM(ip.amount) AS amount_paid, MAX(ip.payment_date) AS last_payment_attempt
+ FROM invoices i
+ LEFT JOIN invoice_payments ip ON ip.invoice_id = i.id
+ LEFT JOIN invoice_items ii ON ii.invoice_id = i.id
+ GROUP BY i.id, i.account_id, i.invoice_date, i.target_date, i.currency
+ ORDER BY i.invoice_date ASC;
+>>
+
+getInvoicesByAccount() ::= <<
+ SELECT i.id, i.account_id, i.invoice_date, i.target_date, i.currency, SUM(ii.amount) AS amount,
+ SUM(ip.amount) AS amount_paid, MAX(ip.payment_date) AS last_payment_attempt
+ FROM invoices i
+ LEFT JOIN invoice_payments ip ON ip.invoice_id = i.id
+ LEFT JOIN invoice_items ii ON ii.invoice_id = i.id
+ WHERE i.account_id = :accountId
+ GROUP BY i.id, i.account_id, i.invoice_date, i.target_date, i.currency
+ ORDER BY i.invoice_date ASC;
+>>
+
+getInvoicesBySubscription() ::= <<
+ SELECT i.id, i.account_id, i.invoice_date, i.target_date, i.currency, SUM(ii.amount) AS amount,
+ SUM(ip.amount) AS amount_paid, MAX(ip.payment_date) AS last_payment_attempt
+ FROM invoices i
+ LEFT JOIN invoice_items ii ON i.id = ii.invoice_id
+ LEFT JOIN invoice_payments ip ON ip.invoice_id = i.id
+ WHERE ii.subscription_id = :subscriptionId
+ GROUP BY i.id, i.account_id, i.invoice_date, i.target_date, i.currency;
+>>
+
+getInvoicesForPayment() ::= <<
+ SELECT i.id
+ FROM invoices i
+ LEFT JOIN invoice_payment_summary ips ON ips.invoice_id = i.id
+ LEFT JOIN invoice_item_summary iis ON iis.invoice_id = i.id
+ WHERE ((ips.last_payment_date IS NULL) OR (DATEDIFF(:targetDate, ips.last_payment_date) >= :numberOfDays))
+ AND ((ips.total_paid IS NULL) OR (iis.total_amount >= ips.total_paid))
+ AND ((iis.total_amount IS NOT NULL) AND (iis.total_amount > 0))
+ GROUP BY i.id, i.account_id, i.invoice_date, i.target_date, i.currency;
+>>
+
+getById() ::= <<
+ SELECT i.id, i.account_id, i.invoice_date, i.target_date, i.currency, SUM(ii.amount) AS amount,
+ SUM(ip.amount) AS amount_paid, MAX(ip.payment_date) AS last_payment_attempt
+ FROM invoices i
+ LEFT JOIN invoice_items ii ON i.id = ii.invoice_id
+ LEFT JOIN invoice_payments ip ON ip.invoice_id = i.id
+ WHERE i.id = :id
+ GROUP BY i.id, i.account_id, i.invoice_date, i.target_date, i.currency;
+>>
+
+save() ::= <<
+ INSERT INTO invoices(id, account_id, invoice_date, target_date, currency)
+ VALUES (:id, :accountId, :invoiceDate, :targetDate, :currency)
+ ON DUPLICATE KEY UPDATE
+ invoice_date = :invoiceDate, target_date = :targetDate, currency = :currency;
+>>
+
+notifySuccessfulPayment() ::= <<
+ INSERT INTO invoice_payments(invoice_id, payment_id, payment_date, amount, currency)
+ VALUES(:invoiceId, :paymentId, :paymentDate, :amount, :currency);
+>>
+
+notifyFailedPayment() ::= <<
+ INSERT INTO invoice_payments(invoice_id, payment_id, payment_date)
+ VALUES(:invoiceId, :paymentId, :paymentAttemptDate);
+>>
+
+test() ::= <<
+ SELECT 1
+ FROM invoices;
+>>
+;
\ No newline at end of file
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 1a851a0..a3ff37d 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
+++ b/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
@@ -1,7 +1,6 @@
DROP TABLE IF EXISTS invoice_items;
CREATE TABLE invoice_items (
- id int(11) unsigned NOT NULL AUTO_INCREMENT,
- invoice_item_id char(36) NOT NULL,
+ id char(36) NOT NULL,
invoice_id char(36) NOT NULL,
subscription_id char(36) NOT NULL,
start_date datetime NOT NULL,
@@ -9,7 +8,7 @@ CREATE TABLE invoice_items (
description varchar(100) NOT NULL,
amount numeric(10,4) NOT NULL,
rate numeric(10,4) NOT NULL,
- currency varchar(5) NOT NULL,
+ currency char(3) NOT NULL,
PRIMARY KEY(id)
) ENGINE=innodb;
@@ -17,18 +16,35 @@ CREATE INDEX invoice_items_subscription_id ON invoice_items(subscription_id ASC)
DROP TABLE IF EXISTS invoices;
CREATE TABLE invoices (
- id int(11) unsigned NOT NULL AUTO_INCREMENT,
- invoice_id char(36) NOT NULL,
+ id char(36) NOT NULL,
account_id char(36) NOT NULL,
invoice_date datetime NOT NULL,
- amount_paid numeric(10,4) NOT NULL DEFAULT 0,
- amount_outstanding numeric(10,4) NOT NULL,
- last_payment_attempt datetime DEFAULT NULL,
+ target_date datetime NOT NULL,
+ currency char(3) NOT NULL,
PRIMARY KEY(id)
) ENGINE=innodb;
CREATE INDEX invoices_account_id ON invoices(account_id ASC);
-CREATE INDEX invoices_invoice_id ON invoices(invoice_id ASC);
+DROP TABLE IF EXISTS invoice_payments;
+CREATE TABLE invoice_payments (
+ invoice_id char(36) NOT NULL,
+ payment_id char(36) NOT NULL,
+ payment_date datetime NOT NULL,
+ amount numeric(10,4),
+ currency char(3),
+ PRIMARY KEY(invoice_id, payment_id)
+) ENGINE=innodb;
+CREATE UNIQUE INDEX invoice_payments_unique ON invoice_payments(invoice_id, payment_id);
+DROP VIEW IF EXISTS invoice_payment_summary;
+CREATE VIEW invoice_payment_summary AS
+SELECT invoice_id, SUM(amount) AS total_paid, MAX(payment_date) AS last_payment_date
+FROM invoice_payments
+GROUP BY invoice_id;
+DROP VIEW IF EXISTS invoice_item_summary;
+CREATE VIEW invoice_item_summary AS
+SELECT invoice_id, SUM(amount) AS total_amount
+FROM invoice_items
+GROUP BY invoice_id;
\ No newline at end of file
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
new file mode 100644
index 0000000..268aaf5
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.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.invoice.dao;
+
+import java.io.IOException;
+import org.apache.commons.io.IOUtils;
+import org.testng.annotations.BeforeClass;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.invoice.glue.InvoiceModuleMock;
+import com.ning.billing.util.eventbus.DefaultEventBusService;
+import com.ning.billing.util.eventbus.EventBusService;
+
+import static org.testng.Assert.fail;
+
+public abstract class InvoiceDaoTestBase {
+ protected InvoiceDao invoiceDao;
+ protected InvoiceItemSqlDao invoiceItemDao;
+
+ @BeforeClass()
+ protected void setup() throws IOException {
+ // Health check test to make sure MySQL is setup properly
+ try {
+ InvoiceModuleMock module = new InvoiceModuleMock();
+ final String ddl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
+ module.createDb(ddl);
+
+ final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
+
+ invoiceDao = injector.getInstance(InvoiceDao.class);
+ invoiceDao.test();
+
+ invoiceItemDao = module.getInvoiceItemDao();
+
+ EventBusService busService = injector.getInstance(EventBusService.class);
+ ((DefaultEventBusService) busService).startBus();
+ }
+ catch (Throwable t) {
+ fail(t.toString());
+ }
+ }
+}
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 5447094..0666ada 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,50 +16,287 @@
package com.ning.billing.invoice.dao;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import org.joda.time.DateTime;
+import org.joda.time.Days;
import org.testng.annotations.Test;
+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.model.DefaultInvoice;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import com.ning.billing.util.clock.DefaultClock;
-@Test(groups = {"invoicing", "invoicing-dao"})
-public class InvoiceDaoTests {
-// private final MysqlTestingHelper helper = new MysqlTestingHelper();
-// private InvoiceDao dao;
-//
-// @BeforeClass(alwaysRun = true)
-// private void setup() {
-// final String ddl = IOUtils.toString(InvoiceDao.class.getResourceAsStream("/ddl.sql"));
-//
-// helper.startMysql();
-// helper.initDb();
-//
-// final IDBI dbi = helper.getDBI();
-// dao = dbi.onDemand(EventDao.class);
-//
-// // Healthcheck test to make sure MySQL is setup properly
-// try {
-// dao.test();
-// }
-// catch (Throwable t) {
-// Assert.fail(t.toString());
-// }
-// }
-//
-// @Test
-// public void testCreationAndRetrievalByAccount() {
-// InvoiceDao dao = dbi.onDemand(InvoiceDao.class);
-// UUID accountId = UUID.randomUUID();
-// Invoice invoice = new Invoice(accountId, Currency.USD);
-// DateTime invoiceDate = invoice.getInvoiceDate();
-//
-// dao.createInvoice(invoice);
-//
-// List<Invoice> invoices = dao.getInvoicesByAccount(accountId.toString());
-// assertNotNull(invoices);
-// assertEquals(invoices.size(), 1);
-// Invoice thisInvoice = invoices.get(0);
-// assertEquals(invoice.getAccountId(), accountId);
-// assertTrue(thisInvoice.getInvoiceDate().equals(invoiceDate));
-// assertEquals(thisInvoice.getCurrency(), Currency.USD);
-// assertEquals(thisInvoice.getNumberOfItems(), 0);
-// assertTrue(thisInvoice.getTotalAmount().compareTo(BigDecimal.ZERO) == 0);
-// }
+import static org.testng.Assert.assertEquals;
+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 {
+ private final int NUMBER_OF_DAY_BETWEEN_RETRIES = 8;
+
+ @Test
+ public void testCreationAndRetrievalByAccount() {
+ UUID accountId = UUID.randomUUID();
+ Invoice invoice = new DefaultInvoice(accountId, new DefaultClock().getUTCNow(), Currency.USD);
+ DateTime invoiceDate = invoice.getInvoiceDate();
+
+ invoiceDao.save(invoice);
+
+ List<Invoice> invoices = invoiceDao.getInvoicesByAccount(accountId.toString());
+ assertNotNull(invoices);
+ assertEquals(invoices.size(), 1);
+ Invoice thisInvoice = invoices.get(0);
+ assertEquals(invoice.getAccountId(), accountId);
+ assertTrue(thisInvoice.getInvoiceDate().compareTo(invoiceDate) == 0);
+ assertEquals(thisInvoice.getCurrency(), Currency.USD);
+ assertEquals(thisInvoice.getNumberOfItems(), 0);
+ assertTrue(thisInvoice.getTotalAmount().compareTo(BigDecimal.ZERO) == 0);
+ }
+
+ @Test
+ public void testInvoicePayment() {
+ UUID accountId = UUID.randomUUID();
+ Invoice invoice = new DefaultInvoice(accountId, new DefaultClock().getUTCNow(), Currency.USD);
+ UUID invoiceId = invoice.getId();
+ UUID subscriptionId = UUID.randomUUID();
+ DateTime startDate = new DateTime(2010, 1, 1, 0, 0, 0, 0);
+ DateTime endDate = new DateTime(2010, 4, 1, 0, 0, 0, 0);
+ InvoiceItem invoiceItem = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", new BigDecimal("21.00"), new BigDecimal("7.00"), Currency.USD);
+ invoice.add(invoiceItem);
+ invoiceDao.save(invoice);
+
+ Invoice savedInvoice = invoiceDao.getById(invoiceId.toString());
+ assertNotNull(savedInvoice);
+ assertEquals(savedInvoice.getTotalAmount().compareTo(new BigDecimal("21.00")), 0);
+ assertEquals(savedInvoice.getAmountOutstanding().compareTo(new BigDecimal("21.00")), 0);
+ assertEquals(savedInvoice.getAmountPaid(), BigDecimal.ZERO);
+ assertEquals(savedInvoice.getItems().size(), 1);
+
+ BigDecimal paymentAmount = new BigDecimal("11.00");
+ String paymentId = UUID.randomUUID().toString();
+ invoiceDao.notifySuccessfulPayment(invoiceId.toString(), paymentAmount, Currency.USD.toString(), paymentId, new DefaultClock().getUTCNow().plusDays(12).toDate());
+
+ Invoice retrievedInvoice = invoiceDao.getById(invoiceId.toString());
+ assertNotNull(retrievedInvoice);
+ assertEquals(retrievedInvoice.getItems().size(), 1);
+ assertEquals(retrievedInvoice.getTotalAmount().compareTo(new BigDecimal("21.00")), 0);
+ assertEquals(retrievedInvoice.getAmountOutstanding().compareTo(new BigDecimal("10.00")), 0);
+ assertEquals(retrievedInvoice.getAmountPaid().compareTo(new BigDecimal("11.00")), 0);
+ }
+
+ @Test
+ public void testRetrievalForNonExistentInvoiceId() {
+ Invoice invoice = invoiceDao.getById(UUID.randomUUID().toString());
+ assertNull(invoice);
+ }
+
+ @Test
+ public void testAddPayment() {
+ UUID accountId = UUID.randomUUID();
+ DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+ Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+ String paymentId = UUID.randomUUID().toString();
+ DateTime paymentAttemptDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
+ BigDecimal paymentAmount = new BigDecimal("14.0");
+
+ invoiceDao.save(invoice);
+ invoiceDao.notifySuccessfulPayment(invoice.getId().toString(), paymentAmount, Currency.USD.toString(), paymentId, paymentAttemptDate.toDate());
+
+ invoice = invoiceDao.getById(invoice.getId().toString());
+// assertEquals(invoice.getAmountPaid().compareTo(paymentAmount), 0);
+// assertTrue(invoice.getLastPaymentAttempt().equals(paymentAttemptDate));
+ }
+
+ @Test
+ public void testAddPaymentAttempt() {
+ UUID accountId = UUID.randomUUID();
+ DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+ Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+ DateTime paymentAttemptDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
+
+ invoiceDao.save(invoice);
+ invoiceDao.notifyFailedPayment(invoice.getId().toString(), UUID.randomUUID().toString(), paymentAttemptDate.toDate());
+
+ invoice = invoiceDao.getById(invoice.getId().toString());
+// assertTrue(invoice.getLastPaymentAttempt().equals(paymentAttemptDate));
+ }
+
+ @Test
+ public void testGetInvoicesForPaymentWithNoResults() {
+ DateTime notionalDate = new DateTime();
+ DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+
+ // determine the number of existing invoices available for payment (to avoid side effects from other tests)
+ List<UUID> invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ int existingInvoiceCount = invoices.size();
+
+ UUID accountId = UUID.randomUUID();
+ Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+ invoiceDao.save(invoice);
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ assertEquals(invoices.size(), existingInvoiceCount);
+ }
+
+ @Test
+ public void testGetInvoicesForPayment() {
+ List<UUID> invoices;
+ DateTime notionalDate = new DateTime();
+
+ // create a new invoice with one item
+ UUID accountId = UUID.randomUUID();
+ DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+ Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+ UUID invoiceId = invoice.getId();
+ UUID subscriptionId = UUID.randomUUID();
+ DateTime endDate = targetDate.plusMonths(3);
+ BigDecimal rate = new BigDecimal("9.0");
+ BigDecimal amount = rate.multiply(new BigDecimal("3.0"));
+
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, targetDate, endDate, "test", amount, rate, Currency.USD);
+ invoice.add(item);
+ invoiceDao.save(invoice);
+
+ // ensure that the number of invoices for payment has increased by 1
+ int count;
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ List<Invoice> invoicesDue = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate);
+ count = invoicesDue.size();
+ assertEquals(invoices.size(), count);
+
+ // attempt a payment; ensure that the number of invoices for payment has decreased by 1
+ // (no retries for NUMBER_OF_DAYS_BETWEEN_RETRIES days)
+ invoiceDao.notifyFailedPayment(invoice.getId().toString(), UUID.randomUUID().toString(), notionalDate.toDate());
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ count = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate).size();
+ assertEquals(invoices.size(), count);
+
+ // advance clock by NUMBER_OF_DAYS_BETWEEN_RETRIES days
+ // ensure that number of invoices for payment has increased by 1 (retry)
+ notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ count = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate).size();
+ assertEquals(invoices.size(), count);
+
+ // post successful partial payment; ensure that number of invoices for payment has decreased by 1
+ invoiceDao.notifySuccessfulPayment(invoiceId.toString(), new BigDecimal("22.0000"), Currency.USD.toString(), UUID.randomUUID().toString(), notionalDate.toDate());
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ count = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate).size();
+ assertEquals(invoices.size(), count);
+
+ // get invoice; verify amount paid is correct
+ invoice = invoiceDao.getById(invoiceId.toString());
+ assertEquals(invoice.getAmountPaid().compareTo(new BigDecimal("22.0")), 0);
+
+ // advance clock NUMBER_OF_DAYS_BETWEEN_RETRIES days
+ // ensure that number of invoices for payment has increased by 1 (retry)
+ notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ count = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate).size();
+ assertEquals(invoices.size(), count);
+
+ // post completed payment; ensure that the number of invoices for payment has decreased by 1
+ invoiceDao.notifySuccessfulPayment(invoiceId.toString(), new BigDecimal("5.0000"), Currency.USD.toString(), UUID.randomUUID().toString(), notionalDate.toDate());
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ count = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate).size();
+ assertEquals(invoices.size(), count);
+
+ // get invoice; verify amount paid is correct
+ invoice = invoiceDao.getById(invoiceId.toString());
+ count = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate).size();
+ assertEquals(invoice.getAmountPaid().compareTo(new BigDecimal("27.0")), 0);
+
+ // advance clock by NUMBER_OF_DAYS_BETWEEN_RETRIES days
+ // ensure that the number of invoices for payment hasn't changed
+ notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
+ invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+ count = getInvoicesDueForPaymentAttempt(invoiceDao.get(), notionalDate).size();
+ assertEquals(invoices.size(), count);
+ }
+
+ private List<Invoice> getInvoicesDueForPaymentAttempt(List<Invoice> invoices, DateTime date) {
+ List<Invoice> invoicesDue= new ArrayList<Invoice>();
+
+ for (Invoice invoice : invoices) {
+ if (invoice.isDueForPayment(date, NUMBER_OF_DAY_BETWEEN_RETRIES)) {
+ invoicesDue.add(invoice);
+ }
+ }
+
+ return invoicesDue;
+ }
+
+ @Test
+ public void testGetInvoicesBySubscription() {
+ UUID accountId = UUID.randomUUID();
+
+ UUID subscriptionId1 = UUID.randomUUID(); BigDecimal rate1 = new BigDecimal("17.0");
+ UUID subscriptionId2 = UUID.randomUUID(); BigDecimal rate2 = new BigDecimal("42.0");
+ UUID subscriptionId3 = UUID.randomUUID(); BigDecimal rate3 = new BigDecimal("3.0");
+ UUID subscriptionId4 = UUID.randomUUID(); BigDecimal rate4 = new BigDecimal("12.0");
+
+ DateTime targetDate = new DateTime(2011, 5, 23, 0, 0, 0, 0);
+
+
+ // create invoice 1 (subscriptions 1-4)
+ Invoice invoice1 = new DefaultInvoice(accountId, targetDate, Currency.USD);
+ invoiceDao.save(invoice1);
+
+ UUID invoiceId1 = invoice1.getId();
+
+ DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+ DateTime endDate = startDate.plusMonths(1);
+
+ DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoiceId1, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
+ invoiceItemDao.save(item1);
+
+ DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoiceId1, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
+ invoiceItemDao.save(item2);
+
+ DefaultInvoiceItem item3 = new DefaultInvoiceItem(invoiceId1, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
+ invoiceItemDao.save(item3);
+
+ DefaultInvoiceItem item4 = new DefaultInvoiceItem(invoiceId1, subscriptionId4, startDate, endDate, "test D", rate4, rate4, Currency.USD);
+ invoiceItemDao.save(item4);
+
+ // create invoice 2 (subscriptions 1-3)
+ DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+ invoiceDao.save(invoice);
+
+ UUID invoiceId2 = invoice.getId();
+
+ startDate = endDate;
+ endDate = startDate.plusMonths(1);
+
+ DefaultInvoiceItem item5 = new DefaultInvoiceItem(invoiceId2, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
+ invoiceItemDao.save(item5);
+
+ DefaultInvoiceItem item6 = new DefaultInvoiceItem(invoiceId2, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
+ invoiceItemDao.save(item6);
+
+ DefaultInvoiceItem item7 = new DefaultInvoiceItem(invoiceId2, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
+ invoiceItemDao.save(item7);
+
+ // check that each subscription returns the correct number of invoices
+ List<Invoice> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1.toString());
+ assertEquals(items1.size(), 2);
+
+ List<Invoice> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2.toString());
+ assertEquals(items2.size(), 2);
+
+ List<Invoice> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3.toString());
+ assertEquals(items3.size(), 2);
+
+ List<Invoice> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4.toString());
+ assertEquals(items4.size(), 1);
+ }
+
}
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
new file mode 100644
index 0000000..0f30753
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.dao;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.glue.InvoiceModuleMock;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import static org.testng.Assert.*;
+
+public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
+ @Test
+ public void testInvoiceItemCreation() {
+ UUID invoiceId = 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");
+
+ InvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", rate, rate, Currency.USD);
+ invoiceItemDao.save(item);
+
+ InvoiceItem thisItem = invoiceItemDao.getById(item.getId().toString());
+ assertNotNull(thisItem);
+ assertEquals(thisItem.getId(), item.getId());
+ assertEquals(thisItem.getInvoiceId(), item.getInvoiceId());
+ assertEquals(thisItem.getSubscriptionId(), item.getSubscriptionId());
+ assertEquals(thisItem.getStartDate(), item.getStartDate());
+ assertEquals(thisItem.getEndDate(), item.getEndDate());
+ assertEquals(thisItem.getDescription(), item.getDescription());
+ assertEquals(thisItem.getAmount().compareTo(item.getAmount()), 0);
+ assertEquals(thisItem.getRate().compareTo(item.getRate()), 0);
+ assertEquals(thisItem.getCurrency(), item.getCurrency());
+ }
+
+ @Test
+ public void testGetInvoiceItemsBySubscriptionId() {
+ UUID subscriptionId = 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();
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate.plusMonths(i), startDate.plusMonths(i + 1), "test", rate, rate, Currency.USD);
+ invoiceItemDao.save(item);
+ }
+
+ List<InvoiceItem> items = invoiceItemDao.getInvoiceItemsBySubscription(subscriptionId.toString());
+ assertEquals(items.size(), 3);
+ }
+
+ @Test
+ public void testGetInvoiceItemsByInvoiceId() {
+ UUID invoiceId = 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));
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", amount, amount, Currency.USD);
+ invoiceItemDao.save(item);
+ }
+
+ List<InvoiceItem> items = invoiceItemDao.getInvoiceItemsByInvoice(invoiceId.toString());
+ assertEquals(items.size(), 5);
+ }
+
+ @Test
+ public void testGetInvoiceItemsByAccountId() {
+ UUID accountId = UUID.randomUUID();
+ DateTime targetDate = new DateTime(2011, 5, 23, 0, 0, 0, 0);
+ DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+ invoiceDao.save(invoice);
+
+ UUID invoiceId = invoice.getId();
+ DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+ BigDecimal rate = new BigDecimal("20.00");
+
+ UUID subscriptionId = UUID.randomUUID();
+ DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", rate, rate, Currency.USD);
+ invoiceItemDao.save(item);
+
+ List<InvoiceItem> items = invoiceItemDao.getInvoiceItemsByAccount(accountId.toString());
+ assertEquals(items.size(), 1);
+ }
+}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java
new file mode 100644
index 0000000..c2f7585
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.glue;
+
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.invoice.dao.InvoiceItemSqlDao;
+import com.ning.billing.util.glue.EventBusModule;
+import org.skife.jdbi.v2.IDBI;
+
+import java.io.IOException;
+
+public class InvoiceModuleMock extends InvoiceModule {
+ private final MysqlTestingHelper helper = new MysqlTestingHelper();
+ private IDBI dbi;
+
+ public void createDb(String ddl) throws IOException {
+ helper.startMysql();
+ helper.initDb(ddl);
+ }
+
+ public InvoiceItemSqlDao getInvoiceItemDao() {
+ return dbi.onDemand(InvoiceItemSqlDao.class);
+ }
+
+ @Override
+ public void configure() {
+ dbi = helper.getDBI();
+ bind(IDBI.class).toInstance(dbi);
+ super.configure();
+ install(new EventBusModule());
+ }
+}
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 134ca4e..8321daf 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
@@ -28,18 +28,19 @@ import org.testng.annotations.Test;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.entitlement.api.billing.BillingEvent;
-import com.ning.billing.entitlement.api.billing.BillingMode;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
import com.ning.billing.invoice.api.BillingEventSet;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
-import com.ning.billing.invoice.model.IInvoiceGenerator;
-import com.ning.billing.invoice.model.Invoice;
-import com.ning.billing.invoice.model.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import com.ning.billing.invoice.model.InvoiceGenerator;
import com.ning.billing.invoice.model.InvoiceItemList;
@Test(groups = {"invoicing", "invoiceGenerator"})
public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
- private final IInvoiceGenerator generator = new DefaultInvoiceGenerator();
+ private final InvoiceGenerator generator = new DefaultInvoiceGenerator();
@Test
public void testWithNullEventSetAndNullInvoiceSet() {
@@ -74,8 +75,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
String phaseName = "Build Space Laser";
BillingEvent event = new DefaultBillingEvent(subscriptionId, startDate, planName, phaseName,
new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE, "Test");
-
+ 1, BillingModeType.IN_ADVANCE, "Test");
events.add(event);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -100,8 +100,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BigDecimal rate = TEN;
BillingEvent event = new DefaultBillingEvent(subscriptionId, startDate, planName, phaseName,
new InternationalPriceMock(ZERO), new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
- 15, BillingMode.IN_ADVANCE,"Test");
-
+ 15, BillingModeType.IN_ADVANCE,"Test");
events.add(event);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -126,13 +125,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BillingEvent event1 = new DefaultBillingEvent(UUID.randomUUID(), buildDateTime(2011, 9, 1),
"World Domination", "Build Space Laser",
new InternationalPriceMock(ZERO), new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE, "Test");
+ 1, BillingModeType.IN_ADVANCE, "Test");
events.add(event1);
BillingEvent event2 = new DefaultBillingEvent(UUID.randomUUID(), buildDateTime(2011, 10, 1),
"Groceries", "Pick Up Milk",
new InternationalPriceMock(ZERO), new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE,"Test");
+ 1, BillingModeType.IN_ADVANCE,"Test");
events.add(event2);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -153,13 +152,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BillingEvent event1 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 9, 1),
"World Domination", "Build Space Laser",
new InternationalPriceMock(ZERO),new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE,"Test");
+ 1, BillingModeType.IN_ADVANCE,"Test");
events.add(event1);
BillingEvent event2 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 10, 15),
"World Domination", "Incinerate James Bond",
new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 15, BillingMode.IN_ADVANCE,"Test");
+ 15, BillingModeType.IN_ADVANCE,"Test");
events.add(event2);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -191,19 +190,19 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BillingEvent event1 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 9, 1),
"World Domination", "Build Space Laser",
new InternationalPriceMock(ZERO),new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE,"Test");
+ 1, BillingModeType.IN_ADVANCE,"Test");
events.add(event1);
BillingEvent event2 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 10, 1),
"World Domination", "Incinerate James Bond",
new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE,"Test");
+ 1, BillingModeType.IN_ADVANCE,"Test");
events.add(event2);
BillingEvent event3 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 11, 1),
"World Domination", "Cackle Gleefully",
new InternationalPriceMock(ZERO),new InternationalPriceMock(THIRTY), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE,"Test");
+ 1, BillingModeType.IN_ADVANCE,"Test");
events.add(event3);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -227,11 +226,11 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BillingEvent event1 = new DefaultBillingEvent(subscriptionId, startDate,
"World Domination", "Build Space Laser",
new InternationalPriceMock(ZERO),new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
- 1, BillingMode.IN_ADVANCE,"Test");
+ 1, BillingModeType.IN_ADVANCE,"Test");
events.add(event1);
InvoiceItemList existingInvoiceItems = new InvoiceItemList();
- InvoiceItem invoiceItem = new InvoiceItem(UUID.randomUUID(), subscriptionId, startDate, buildDateTime(2012, 1, 1), "",
+ InvoiceItem invoiceItem = new DefaultInvoiceItem(UUID.randomUUID(), subscriptionId, startDate, buildDateTime(2012, 1, 1), "",
rate.multiply(FOUR), rate, Currency.USD);
existingInvoiceItems.add(invoiceItem);
@@ -400,16 +399,14 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
BigDecimal rate, int billCycleDay) {
return new DefaultBillingEvent(subscriptionId, startDate, planName, planPhaseName,
new InternationalPriceMock(ZERO),new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
- billCycleDay, BillingMode.IN_ADVANCE,"Test");
-
+ billCycleDay, BillingModeType.IN_ADVANCE,"Test");
}
private DefaultBillingEvent createAnnualBillingEvent(UUID subscriptionId, DateTime startDate, String planName, String planPhaseName,
BigDecimal rate, int billCycleDay) {
return new DefaultBillingEvent(subscriptionId, startDate, planName, planPhaseName,
new InternationalPriceMock(ZERO),new InternationalPriceMock(rate), BillingPeriod.ANNUAL,
- billCycleDay, BillingMode.IN_ADVANCE,"Test");
-
+ billCycleDay, BillingModeType.IN_ADVANCE,"Test");
}
private void testInvoiceGeneration(BillingEventSet events, InvoiceItemList existingInvoiceItems, DateTime targetDate, int expectedNumberOfItems, BigDecimal expectedAmount) {
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 2948557..14392a8 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,7 +16,7 @@
package com.ning.billing.invoice.tests.inAdvance;
-import com.ning.billing.invoice.model.IBillingMode;
+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;
@@ -24,7 +24,7 @@ import org.testng.annotations.Test;
@Test(groups = {"invoicing", "proRation"})
public abstract class ProRationInAdvanceTestBase extends ProRationTestBase {
@Override
- protected IBillingMode getBillingMode() {
+ protected BillingMode getBillingMode() {
return new InAdvanceBillingMode();
}
}
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 c57fe32..9de01bd 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
@@ -17,7 +17,7 @@
package com.ning.billing.invoice.tests.inAdvance;
import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.IBillingMode;
+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;
@@ -35,7 +35,7 @@ public class ValidationProRationTests extends ProRationTestBase {
}
@Override
- protected IBillingMode getBillingMode() {
+ protected BillingMode getBillingMode() {
return new InAdvanceBillingMode();
}
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 835836e..174017b 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
@@ -17,7 +17,7 @@
package com.ning.billing.invoice.tests;
import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.IBillingMode;
+import com.ning.billing.invoice.model.BillingMode;
import com.ning.billing.invoice.model.InvalidDateSequenceException;
import org.joda.time.DateTime;
@@ -27,7 +27,7 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
public abstract class ProRationTestBase extends InvoicingTestBase{
- protected abstract IBillingMode getBillingMode();
+ protected abstract BillingMode getBillingMode();
protected abstract BillingPeriod getBillingPeriod();
protected void testCalculateNumberOfBillingCycles(DateTime startDate, DateTime targetDate, int billingCycleDay, BigDecimal expectedValue) throws InvalidDateSequenceException {
payment/pom.xml 2(+1 -1)
diff --git a/payment/pom.xml b/payment/pom.xml
index 770e297..aca06a2 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 30745fd..f64b324 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
<packaging>pom</packaging>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<name>killbill</name>
<description>Library for managing recurring subscriptions and the associated billing</description>
<url>http://github.com/ning/killbill</url>
util/pom.xml 2(+1 -1)
diff --git a/util/pom.xml b/util/pom.xml
index c7b6110..5152ab7 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.17-SNAPSHOT</version>
+ <version>0.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>
diff --git a/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java b/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java
index 8d61ba5..8280a15 100644
--- a/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java
+++ b/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java
@@ -16,13 +16,12 @@
package com.ning.billing.util.clock;
-import java.util.ArrayList;
-import java.util.List;
-
+import com.ning.billing.catalog.api.Duration;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
-import com.ning.billing.catalog.api.Duration;
+import java.util.ArrayList;
+import java.util.List;
public class DefaultClock implements Clock {
@@ -42,21 +41,21 @@ public class DefaultClock implements Clock {
return input.minus(input.getMillisOfSecond());
}
- public static DateTime addDuration(DateTime input, List<Duration> durations) {
+ public static DateTime addOrRemoveDuration(DateTime input, List<Duration> durations, boolean add) {
DateTime result = input;
for (Duration cur : durations) {
switch (cur.getUnit()) {
case DAYS:
- result = result.plusDays(cur.getNumber());
+ result = add ? result.plusDays(cur.getNumber()) : result.minusDays(cur.getNumber());
break;
case MONTHS:
- result = result.plusMonths(cur.getNumber());
+ result = add ? result.plusMonths(cur.getNumber()) : result.minusMonths(cur.getNumber());
break;
case YEARS:
- result = result.plusYears(cur.getNumber());
+ result = add ? result.plusYears(cur.getNumber()) : result.minusYears(cur.getNumber());
break;
case UNLIMITED:
default:
@@ -66,9 +65,23 @@ public class DefaultClock implements Clock {
return result;
}
+ public static DateTime addDuration(DateTime input, List<Duration> durations) {
+ return addOrRemoveDuration(input, durations, true);
+ }
+
+ public static DateTime removeDuration(DateTime input, List<Duration> durations) {
+ return addOrRemoveDuration(input, durations, false);
+ }
+
public static DateTime addDuration(DateTime input, Duration duration) {
List<Duration> list = new ArrayList<Duration>();
list.add(duration);
- return addDuration(input, list);
+ return addOrRemoveDuration(input, list, true);
+ }
+
+ public static DateTime removeDuration(DateTime input, Duration duration) {
+ List<Duration> list = new ArrayList<Duration>();
+ list.add(duration);
+ return addOrRemoveDuration(input, list, false);
}
}
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidationError.java b/util/src/main/java/com/ning/billing/util/config/ValidationError.java
index 33af867..cd1ae4d 100644
--- a/util/src/main/java/com/ning/billing/util/config/ValidationError.java
+++ b/util/src/main/java/com/ning/billing/util/config/ValidationError.java
@@ -15,10 +15,10 @@
*/
package com.ning.billing.util.config;
-import java.net.URI;
-
import org.slf4j.Logger;
+import java.net.URI;
+
public class ValidationError {
private final String description;
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java b/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
index 19e4270..c8145d2 100644
--- a/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
+++ b/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
@@ -16,11 +16,11 @@
package com.ning.billing.util.config;
+import org.slf4j.Logger;
+
import java.net.URI;
import java.util.ArrayList;
-import org.slf4j.Logger;
-
public class ValidationErrors extends ArrayList<ValidationError>{
private static final long serialVersionUID = 1L;
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 9ed3bce..d0487b8 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
@@ -16,9 +16,10 @@
package com.ning.billing.util.config;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
@@ -28,12 +29,9 @@ import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
-
-import com.ning.billing.catalog.api.InvalidConfigException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
public class XMLLoader {
public static Logger log = LoggerFactory.getLogger(XMLLoader.class);
diff --git a/util/src/main/java/com/ning/billing/util/customfield/CustomizableEntityBase.java b/util/src/main/java/com/ning/billing/util/customfield/CustomizableEntityBase.java
new file mode 100644
index 0000000..05d0137
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/customfield/CustomizableEntityBase.java
@@ -0,0 +1,52 @@
+/*
+ * 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.customfield;
+
+import java.util.List;
+import java.util.UUID;
+import com.ning.billing.util.entity.EntityBase;
+
+public abstract class CustomizableEntityBase extends EntityBase implements CustomizableEntity {
+ protected final FieldStore fields;
+
+ public CustomizableEntityBase(UUID id) {
+ super(id);
+ fields = DefaultFieldStore.create(getId(), getObjectName());
+ }
+
+ @Override
+ public String getFieldValue(String fieldName) {
+ return fields.getValue(fieldName);
+ }
+
+ @Override
+ public void setFieldValue(String fieldName, String fieldValue) {
+ fields.setValue(fieldName, fieldValue);
+ }
+
+ @Override
+ public List<CustomField> getFieldList() {
+ return fields.getEntityList();
+ }
+
+ @Override
+ public void clearFields() {
+ fields.clear();
+ }
+
+ public abstract String getObjectName();
+}
diff --git a/util/src/main/java/com/ning/billing/util/customfield/DefaultFieldStore.java b/util/src/main/java/com/ning/billing/util/customfield/DefaultFieldStore.java
new file mode 100644
index 0000000..4a31dd4
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/customfield/DefaultFieldStore.java
@@ -0,0 +1,51 @@
+/*
+ * 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.customfield;
+
+import java.util.UUID;
+import com.ning.billing.util.entity.EntityCollectionBase;
+
+public class DefaultFieldStore extends EntityCollectionBase<CustomField> implements FieldStore {
+ public DefaultFieldStore(UUID objectId, String objectType) {
+ super(objectId, objectType);
+ }
+
+ public static DefaultFieldStore create(UUID objectId, String objectType) {
+ return new DefaultFieldStore(objectId, objectType);
+ }
+
+ @Override
+ public String getEntityKey(CustomField entity) {
+ return entity.getName();
+ }
+
+ public void setValue(String fieldName, String fieldValue) {
+ if (entities.containsKey(fieldName)) {
+ entities.get(fieldName).setValue(fieldValue);
+ } else {
+ entities.put(fieldName, new StringCustomField(fieldName, fieldValue));
+ }
+ }
+
+ public String getValue(String fieldName) {
+ if (entities.containsKey(fieldName)) {
+ return entities.get(fieldName).getValue();
+ } else {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/entity/EntityBase.java b/util/src/main/java/com/ning/billing/util/entity/EntityBase.java
new file mode 100644
index 0000000..3cb71f8
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/entity/EntityBase.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.util.entity;
+
+import java.util.UUID;
+
+public abstract class EntityBase<T> implements Entity {
+ protected final UUID id;
+
+ public EntityBase(UUID id) {
+ this.id = id;
+ }
+
+ public EntityBase() {
+ this(UUID.randomUUID());
+ }
+
+ @Override
+ public UUID getId() {
+ return id;
+ }
+}
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/entity/EntityCollectionBase.java b/util/src/main/java/com/ning/billing/util/entity/EntityCollectionBase.java
new file mode 100644
index 0000000..369f255
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/entity/EntityCollectionBase.java
@@ -0,0 +1,64 @@
+/*
+ * 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.entity;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public abstract class EntityCollectionBase<T extends Entity> implements EntityCollection<T> {
+ protected Map<String, T> entities = new HashMap<String, T>();
+ protected final UUID objectId;
+ protected final String objectType;
+
+ public EntityCollectionBase(UUID objectId, String objectType) {
+ this.objectId = objectId;
+ this.objectType = objectType;
+ }
+
+ @Override
+ public void clear() {
+ entities.clear();
+ }
+
+ @Override
+ public abstract String getEntityKey(T entity);
+
+ @Override
+ public void add(T entity) {
+ entities.put(getEntityKey(entity), entity);
+ }
+
+ @Override
+ public void add(List<T> entities) {
+ for (T entity : entities) {
+ add(entity);
+ }
+ }
+
+ @Override
+ public void remove(T entity) {
+ entities.remove(entity);
+ }
+
+ @Override
+ public List<T> getEntityList() {
+ return new ArrayList<T>(entities.values());
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/entity/EntityCollectionDao.java b/util/src/main/java/com/ning/billing/util/entity/EntityCollectionDao.java
new file mode 100644
index 0000000..8a7a8c5
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/entity/EntityCollectionDao.java
@@ -0,0 +1,40 @@
+/*
+ * 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.entity;
+
+import org.skife.jdbi.v2.sqlobject.*;
+
+import java.util.List;
+
+/**
+ * provides consistent semantics for entity collections
+ * note: this is intended to be extended by an interface which provides @ExternalizedSqlViaStringTemplate3 and mappers
+ * @param <T>
+ */
+public interface EntityCollectionDao<T extends Entity> {
+ @SqlBatch
+ public void save(@Bind("objectId") final String objectId,
+ @Bind("objectType") final String objectType,
+ @BindBean final List<T> entities);
+
+ @SqlQuery
+ public List<T> load(@Bind("objectId") final String objectId,
+ @Bind("objectType") final String objectType);
+
+ @SqlUpdate
+ public void test();
+}
diff --git a/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java b/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java
index d7f876d..259736d 100644
--- a/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java
+++ b/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java
@@ -16,16 +16,15 @@
package com.ning.billing.util.eventbus;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicBoolean;
-
+import com.google.common.eventbus.AsyncEventBus;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.eventbus.AsyncEventBus;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicBoolean;
public class MemoryEventBus implements EventBus {
diff --git a/util/src/main/java/com/ning/billing/util/glue/TagDescriptionDaoProvider.java b/util/src/main/java/com/ning/billing/util/glue/TagDescriptionDaoProvider.java
new file mode 100644
index 0000000..31fb306
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/TagDescriptionDaoProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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 com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.ning.billing.util.tag.dao.TagDescriptionDao;
+import org.skife.jdbi.v2.IDBI;
+
+public class TagDescriptionDaoProvider implements Provider<TagDescriptionDao>
+{
+ private final IDBI dbi;
+
+ @Inject
+ public TagDescriptionDaoProvider(final IDBI dbi)
+ {
+ this.dbi = dbi;
+ }
+
+ @Override
+ public TagDescriptionDao get()
+ {
+ return dbi.onDemand(TagDescriptionDao.class);
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/TagStoreDaoProvider.java b/util/src/main/java/com/ning/billing/util/glue/TagStoreDaoProvider.java
new file mode 100644
index 0000000..2c612e6
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/TagStoreDaoProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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 com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.ning.billing.util.tag.dao.TagStoreDao;
+import org.skife.jdbi.v2.IDBI;
+
+public class TagStoreDaoProvider implements Provider<TagStoreDao>
+{
+ private final IDBI dbi;
+
+ @Inject
+ public TagStoreDaoProvider(final IDBI dbi)
+ {
+ this.dbi = dbi;
+ }
+
+ @Override
+ public TagStoreDao get()
+ {
+ return dbi.onDemand(TagStoreDao.class);
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/TagStoreModule.java b/util/src/main/java/com/ning/billing/util/glue/TagStoreModule.java
new file mode 100644
index 0000000..ae14782
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/TagStoreModule.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.util.glue;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.util.tag.dao.TagDescriptionDao;
+import com.ning.billing.util.tag.dao.TagStoreDao;
+
+public class TagStoreModule extends AbstractModule
+{
+ @Override
+ protected void configure()
+ {
+ bind(TagDescriptionDao.class).toProvider(TagDescriptionDaoProvider.class).asEagerSingleton();
+ bind(TagStoreDao.class).toProvider(TagStoreDaoProvider.class).asEagerSingleton();
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDescriptionDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDescriptionDao.java
new file mode 100644
index 0000000..4938d49
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDescriptionDao.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.util.tag.dao;
+
+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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+import com.ning.billing.util.entity.EntityDao;
+import com.ning.billing.util.tag.DefaultTagDescription;
+import com.ning.billing.util.tag.TagDescription;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(TagDescriptionDao.TagDescriptionMapper.class)
+public interface TagDescriptionDao extends EntityDao<TagDescription> {
+ @Override
+ @SqlUpdate
+ public void save(@TagDescriptionBinder TagDescription entity);
+
+ public class TagDescriptionMapper implements ResultSetMapper<TagDescription> {
+ @Override
+ public TagDescription map(int index, ResultSet result, StatementContext context) throws SQLException {
+ UUID id = UUID.fromString(result.getString("id"));
+ String name = result.getString("name");
+ String description = result.getString("description");
+ boolean processPayment = result.getBoolean("process_payment");
+ boolean generateInvoice = result.getBoolean("generate_invoice");
+ String createdBy = result.getString("created_by");
+ DateTime creationDate = new DateTime(result.getTimestamp("creation_date"));
+ return new DefaultTagDescription(id, name, description, processPayment, generateInvoice, createdBy, creationDate);
+ }
+ }
+
+ @BindingAnnotation(TagDescriptionBinder.TagDescriptionBinderFactory.class)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.PARAMETER})
+ public @interface TagDescriptionBinder {
+ public static class TagDescriptionBinderFactory implements BinderFactory {
+ public Binder build(Annotation annotation) {
+ return new Binder<TagDescriptionBinder, TagDescription>() {
+ public void bind(SQLStatement q, TagDescriptionBinder bind, TagDescription tagDescription) {
+ q.bind("id", tagDescription.getId().toString());
+ q.bind("name", tagDescription.getName());
+ q.bind("createdBy", tagDescription.getCreatedBy());
+ q.bind("creationDate", tagDescription.getCreationDate().toDate());
+ q.bind("description", tagDescription.getDescription());
+ q.bind("generateInvoice", tagDescription.getGenerateInvoice());
+ q.bind("processPayment", tagDescription.getProcessPayment());
+ }
+ };
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagStoreDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagStoreDao.java
new file mode 100644
index 0000000..14cd047
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagStoreDao.java
@@ -0,0 +1,90 @@
+/*
+ * 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.tag.dao;
+
+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.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;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlBatch;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+import com.ning.billing.util.entity.EntityCollectionDao;
+import com.ning.billing.util.tag.DefaultTag;
+import com.ning.billing.util.tag.DefaultTagDescription;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDescription;
+
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(TagStoreDao.TagMapper.class)
+public interface TagStoreDao extends EntityCollectionDao<Tag> {
+ @Override
+ @SqlBatch
+ public void save(@Bind("objectId") final String objectId,
+ @Bind("objectType") final String objectType,
+ @TagBinder final List<Tag> entities);
+
+ public class TagMapper implements ResultSetMapper<Tag> {
+ @Override
+ public Tag map(int index, ResultSet result, StatementContext context) throws SQLException {
+ UUID tagDescriptionId = UUID.fromString(result.getString("tag_description_id"));
+ String name = result.getString("tag_description_name");
+ String description = result.getString("tag_description");
+ boolean processPayment = result.getBoolean("process_payment");
+ boolean generateInvoice = result.getBoolean("generate_invoice");
+ String createdBy = result.getString("created_by");
+ DateTime creationDate = new DateTime(result.getDate("creation_date"));
+ TagDescription tagDescription = new DefaultTagDescription(tagDescriptionId, name, description, processPayment, generateInvoice, createdBy, creationDate);
+
+ UUID id = UUID.fromString(result.getString("id"));
+ String addedBy = result.getString("added_by");
+ DateTime dateAdded = new DateTime(result.getTimestamp("date_added"));
+ return new DefaultTag(id, tagDescription, addedBy, dateAdded);
+ }
+ }
+
+ @BindingAnnotation(TagBinder.TagBinderFactory.class)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.PARAMETER})
+ public @interface TagBinder {
+ public static class TagBinderFactory implements BinderFactory {
+ public Binder build(Annotation annotation) {
+ return new Binder<TagBinder, Tag>() {
+ public void bind(SQLStatement q, TagBinder bind, Tag tag) {
+ q.bind("id", tag.getId().toString());
+ q.bind("tagDescriptionId", tag.getTagDescriptionId().toString());
+ q.bind("dateAdded", tag.getDateAdded().toDate());
+ q.bind("addedBy", tag.getAddedBy());
+ }
+ };
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultTag.java b/util/src/main/java/com/ning/billing/util/tag/DefaultTag.java
new file mode 100644
index 0000000..6fdb02d
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultTag.java
@@ -0,0 +1,81 @@
+/*
+ * 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.tag;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultTag extends EntityBase implements Tag {
+ private final UUID tagDescriptionId;
+ private final boolean processPayment;
+ private final boolean generateInvoice;
+ private final String addedBy;
+ private final DateTime dateAdded;
+ private final String name;
+
+ public DefaultTag(UUID id, UUID tagDescriptionId, String name, boolean processPayment, boolean generateInvoice,
+ String addedBy, DateTime dateAdded) {
+ super(id);
+ this.tagDescriptionId = tagDescriptionId;
+ this.name = name;
+ this.processPayment = processPayment;
+ this.generateInvoice = generateInvoice;
+ this.addedBy = addedBy;
+ this.dateAdded = dateAdded;
+ }
+
+ public DefaultTag(UUID id, TagDescription tagDescription, String addedBy, DateTime dateAdded) {
+ this(id, tagDescription.getId(), tagDescription.getName(), tagDescription.getProcessPayment(),
+ tagDescription.getGenerateInvoice(), addedBy, dateAdded);
+ }
+
+ public DefaultTag(TagDescription tagDescription, String addedBy, DateTime dateAdded) {
+ this(UUID.randomUUID(), tagDescription.getId(), tagDescription.getName(), tagDescription.getProcessPayment(),
+ tagDescription.getGenerateInvoice(), addedBy, dateAdded);
+ }
+
+ @Override
+ public UUID getTagDescriptionId() {
+ return tagDescriptionId;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean getProcessPayment() {
+ return processPayment;
+ }
+
+ @Override
+ public boolean getGenerateInvoice() {
+ return generateInvoice;
+ }
+
+ @Override
+ public String getAddedBy() {
+ return addedBy;
+ }
+
+ @Override
+ public DateTime getDateAdded() {
+ return dateAdded;
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultTagDescription.java b/util/src/main/java/com/ning/billing/util/tag/DefaultTagDescription.java
new file mode 100644
index 0000000..83c418b
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultTagDescription.java
@@ -0,0 +1,78 @@
+/*
+ * 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.tag;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultTagDescription extends EntityBase implements TagDescription {
+ private String name;
+ private String description;
+ private boolean generateInvoice;
+ private boolean processPayment;
+ private String createdBy;
+ private DateTime creationDate;
+
+ public DefaultTagDescription(String name, String description,
+ boolean processPayment, boolean generateInvoice,
+ String createdBy, DateTime creationDate) {
+ this(UUID.randomUUID(), name, description, processPayment, generateInvoice, createdBy, creationDate);
+ }
+
+ public DefaultTagDescription(UUID id, String name, String description,
+ boolean processPayment, boolean generateInvoice,
+ String createdBy, DateTime creationDate) {
+ super(id);
+ this.name = name;
+ this.description = description;
+ this.processPayment = processPayment;
+ this.generateInvoice = generateInvoice;
+ this.createdBy = createdBy;
+ this.creationDate = creationDate;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ @Override
+ public DateTime getCreationDate() {
+ return creationDate;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public boolean getGenerateInvoice() {
+ return generateInvoice;
+ }
+
+ @Override
+ public boolean getProcessPayment() {
+ return processPayment;
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultTagStore.java b/util/src/main/java/com/ning/billing/util/tag/DefaultTagStore.java
new file mode 100644
index 0000000..6a3062e
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultTagStore.java
@@ -0,0 +1,75 @@
+/*
+ * 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.tag;
+
+import java.util.UUID;
+import com.ning.billing.util.entity.EntityCollectionBase;
+
+public class DefaultTagStore extends EntityCollectionBase<Tag> implements TagStore {
+ public DefaultTagStore(UUID objectId, String objectType) {
+ super(objectId, objectType);
+ }
+
+ @Override
+ public String getEntityKey(Tag entity) {
+ return entity.getName();
+ }
+
+ @Override
+ /***
+ * Collates the contents of the TagStore to determine if payments should be processed
+ * @return true is no tags contraindicate payment processing
+ */
+ public boolean processPayment() {
+ for (Tag tag : entities.values()) {
+ if (!tag.getProcessPayment()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /***
+ * Collates the contents of the TagStore to determine if invoices should be generated
+ * @return true is no tags contraindicate invoice generation
+ */
+ @Override
+ public boolean generateInvoice() {
+ for (Tag tag : entities.values()) {
+ if (!tag.getGenerateInvoice()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void remove(String tagName) {
+ entities.remove(entities.get(tagName));
+ }
+
+ @Override
+ public boolean containsTag(String tagName) {
+ for (Tag tag : entities.values()) {
+ if (tag.getName() == tagName) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/tag/TagBuilder.java b/util/src/main/java/com/ning/billing/util/tag/TagBuilder.java
new file mode 100644
index 0000000..cd4247f
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/tag/TagBuilder.java
@@ -0,0 +1,69 @@
+/*
+ * 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.tag;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+
+public class TagBuilder {
+ private UUID id = UUID.randomUUID();
+ private UUID tagDescriptionId;
+ private String name;
+ private boolean processPayment;
+ private boolean generateInvoice;
+ private String addedBy;
+ private DateTime dateAdded;
+
+ public TagBuilder id(UUID id) {
+ this.id = id;
+ return this;
+ }
+
+ public TagBuilder tagDescriptionId(UUID tagDescriptionId) {
+ this.tagDescriptionId = tagDescriptionId;
+ return this;
+ }
+
+ public TagBuilder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public TagBuilder processPayment(boolean processPayment) {
+ this.processPayment = processPayment;
+ return this;
+ }
+
+ public TagBuilder generateInvoice(boolean generateInvoice) {
+ this.generateInvoice = generateInvoice;
+ return this;
+ }
+
+ public TagBuilder addedBy(String addedBy) {
+ this.addedBy = addedBy;
+ return this;
+ }
+
+ public TagBuilder dateAdded(DateTime dateAdded) {
+ this.dateAdded = dateAdded;
+ return this;
+ }
+
+ public Tag build() {
+ return new DefaultTag(id, tagDescriptionId, name, processPayment, generateInvoice, addedBy, dateAdded);
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/UuidMapper.java b/util/src/main/java/com/ning/billing/util/UuidMapper.java
new file mode 100644
index 0000000..6b44ec1
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/UuidMapper.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.util;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+public class UuidMapper implements ResultSetMapper<UUID> {
+ @Override
+ public UUID map(final int index, ResultSet resultSet, StatementContext statementContext) throws SQLException {
+ return UUID.fromString(resultSet.getString(1));
+ }
+}
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagDescriptionDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagDescriptionDao.sql.stg
new file mode 100644
index 0000000..bdde261
--- /dev/null
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagDescriptionDao.sql.stg
@@ -0,0 +1,19 @@
+group TagDescriptionDao;
+
+save() ::= <<
+ INSERT INTO tag_descriptions(id, name, created_by, creation_date, description, generate_invoice, process_payment)
+ VALUES(:id, :name, :createdBy, :creationDate, :description, :generateInvoice, :processPayment)
+ ON DUPLICATE KEY UPDATE
+ name = :name, created_by = :createdBy, creation_date = :creationDate,
+ description := description, generate_invoice = :generateInvoice,
+ process_payment = :processPayment
+>>
+
+load() ::= <<
+ SELECT id, name, created_by, creation_date, description, generate_invoice, process_payment
+ FROM tag_descriptions
+ WHERE id = :id;
+>>
+;
+
+
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagStoreDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagStoreDao.sql.stg
new file mode 100644
index 0000000..3b53b2e
--- /dev/null
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagStoreDao.sql.stg
@@ -0,0 +1,23 @@
+group TagStoreDao;
+
+save() ::= <<
+ INSERT INTO tags(id, tag_description_id, object_id, object_type, date_added, added_by)
+ VALUES (:id, :tagDescriptionId, :objectId, :objectType, :dateAdded, :addedBy)
+ ON DUPLICATE KEY UPDATE
+ tag_description_id = :tagDescriptionId, object_id = :objectId, object_type = :objectType,
+ date_added = :dateAdded, added_by = :addedBy;
+>>
+
+load() ::= <<
+ SELECT t.id, t.tag_description_id, t.object_id, t.object_type, t.date_added, t.added_by,
+ td.name AS tag_description_name, td.description AS tag_description, td.process_payment, td.generate_invoice,
+ td.created_by, td.creation_date
+ FROM tags t
+ INNER JOIN tag_descriptions td ON t.tag_description_id = td.id
+ WHERE t.object_id = :objectId AND t.object_type = :objectType;
+>>
+
+test() ::= <<
+ SELECT 1 FROM tags;
+>>
+;
\ No newline at end of file
diff --git a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
index 127f0b6..0fb473d 100644
--- a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
+++ b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
@@ -16,13 +16,12 @@
package com.ning.billing.util.clock;
-import java.util.ArrayList;
-import java.util.List;
-
+import com.ning.billing.catalog.api.Duration;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
-import com.ning.billing.catalog.api.Duration;
+import java.util.ArrayList;
+import java.util.List;
// STEPH should really be in tests but not accessible from other sub modules
public class ClockMock extends DefaultClock {
diff --git a/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java b/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
index 30b8ee3..6721ee8 100644
--- a/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
+++ b/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
@@ -16,23 +16,19 @@
package com.ning.billing.util.config;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Date;
-
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
-import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
-
-import com.ning.billing.catalog.api.InvalidConfigException;
+import static org.testng.Assert.assertEquals;
public class TestXMLLoader {
diff --git a/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java b/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java
index 1a24e41..47691be 100644
--- a/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java
+++ b/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java
@@ -16,6 +16,7 @@
package com.ning.billing.util.eventbus;
+import com.google.common.eventbus.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
@@ -23,8 +24,6 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import com.google.common.eventbus.Subscribe;
-
public class TestEventBus {
private static final Logger log = LoggerFactory.getLogger(TestEventBus.class);