diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index 9f497c6..6704b4d 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -20,13 +20,15 @@ import java.util.UUID;
import org.joda.time.DateTimeZone;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.junction.api.BlockingState;
import com.ning.billing.util.entity.EntityBase;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
public class DefaultAccount extends EntityBase implements Account {
+
// Default values. When updating an account object, null values are
// interpreted as "no change". You can use these defaults to reset
// some fields
@@ -214,12 +216,23 @@ public class DefaultAccount extends EntityBase implements Account {
@Override
public Account mergeWithDelegate(final Account delegate) {
final DefaultMutableAccountData accountData = new DefaultMutableAccountData(this);
- accountData.setExternalKey(Objects.firstNonNull(externalKey, delegate.getExternalKey()));
+
+ if (externalKey != null ? !externalKey.equals(delegate.getExternalKey()) : delegate.getExternalKey() != null) {
+ throw new IllegalArgumentException(String.format("Killbill doesn't support updating the account external key yet: this=%s, delegate=%s",
+ externalKey, delegate.getExternalKey()));
+ }
+ if (currency != null ? !currency.equals(delegate.getCurrency()) : delegate.getCurrency() != null) {
+ throw new IllegalArgumentException(String.format("Killbill doesn't support updating the account currency yet: this=%s, delegate=%s",
+ currency, delegate.getCurrency()));
+ }
+ if (billCycleDay != null ? !billCycleDay.equals(delegate.getBillCycleDay()) : delegate.getBillCycleDay() != null) {
+ throw new IllegalArgumentException(String.format("Killbill doesn't support updating the account BCD yet: this=%s, delegate=%s",
+ billCycleDay, delegate.getBillCycleDay()));
+ }
+
accountData.setEmail(Objects.firstNonNull(email, delegate.getEmail()));
accountData.setName(Objects.firstNonNull(name, delegate.getName()));
accountData.setFirstNameLength(Objects.firstNonNull(firstNameLength, delegate.getFirstNameLength()));
- accountData.setCurrency(Objects.firstNonNull(currency, delegate.getCurrency()));
- accountData.setBillCycleDay(Objects.firstNonNull(billCycleDay, delegate.getBillCycleDay()));
accountData.setPaymentMethodId(Optional.<UUID>fromNullable(paymentMethodId)
.or(Optional.<UUID>fromNullable(delegate.getPaymentMethodId())).orNull());
accountData.setTimeZone(Objects.firstNonNull(timeZone, delegate.getTimeZone()));
@@ -241,23 +254,119 @@ public class DefaultAccount extends EntityBase implements Account {
@Override
public String toString() {
return "DefaultAccount [externalKey=" + externalKey +
- ", email=" + email +
- ", name=" + name +
- ", firstNameLength=" + firstNameLength +
- ", phone=" + phone +
- ", currency=" + currency +
- ", billCycleDay=" + billCycleDay +
- ", paymentMethodId=" + paymentMethodId +
- ", timezone=" + timeZone +
- ", locale=" + locale +
- ", address1=" + address1 +
- ", address2=" + address2 +
- ", companyName=" + companyName +
- ", city=" + city +
- ", stateOrProvince=" + stateOrProvince +
- ", postalCode=" + postalCode +
- ", country=" + country +
- "]";
+ ", email=" + email +
+ ", name=" + name +
+ ", firstNameLength=" + firstNameLength +
+ ", phone=" + phone +
+ ", currency=" + currency +
+ ", billCycleDay=" + billCycleDay +
+ ", paymentMethodId=" + paymentMethodId +
+ ", timezone=" + timeZone +
+ ", locale=" + locale +
+ ", address1=" + address1 +
+ ", address2=" + address2 +
+ ", companyName=" + companyName +
+ ", city=" + city +
+ ", stateOrProvince=" + stateOrProvince +
+ ", postalCode=" + postalCode +
+ ", country=" + country +
+ "]";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultAccount that = (DefaultAccount) o;
+
+ if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) {
+ return false;
+ }
+ if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) {
+ return false;
+ }
+ if (billCycleDay != null ? !billCycleDay.equals(that.billCycleDay) : that.billCycleDay != null) {
+ return false;
+ }
+ if (city != null ? !city.equals(that.city) : that.city != null) {
+ return false;
+ }
+ if (companyName != null ? !companyName.equals(that.companyName) : that.companyName != null) {
+ return false;
+ }
+ if (country != null ? !country.equals(that.country) : that.country != null) {
+ return false;
+ }
+ if (currency != that.currency) {
+ return false;
+ }
+ if (email != null ? !email.equals(that.email) : that.email != null) {
+ return false;
+ }
+ if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
+ return false;
+ }
+ if (firstNameLength != null ? !firstNameLength.equals(that.firstNameLength) : that.firstNameLength != null) {
+ return false;
+ }
+ if (isMigrated != null ? !isMigrated.equals(that.isMigrated) : that.isMigrated != null) {
+ return false;
+ }
+ if (isNotifiedForInvoices != null ? !isNotifiedForInvoices.equals(that.isNotifiedForInvoices) : that.isNotifiedForInvoices != null) {
+ return false;
+ }
+ if (locale != null ? !locale.equals(that.locale) : that.locale != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (paymentMethodId != null ? !paymentMethodId.equals(that.paymentMethodId) : that.paymentMethodId != null) {
+ return false;
+ }
+ if (phone != null ? !phone.equals(that.phone) : that.phone != null) {
+ return false;
+ }
+ if (postalCode != null ? !postalCode.equals(that.postalCode) : that.postalCode != null) {
+ return false;
+ }
+ if (stateOrProvince != null ? !stateOrProvince.equals(that.stateOrProvince) : that.stateOrProvince != null) {
+ return false;
+ }
+ if (timeZone != null ? !timeZone.equals(that.timeZone) : that.timeZone != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = externalKey != null ? externalKey.hashCode() : 0;
+ result = 31 * result + (email != null ? email.hashCode() : 0);
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (firstNameLength != null ? firstNameLength.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
+ result = 31 * result + (billCycleDay != null ? billCycleDay.hashCode() : 0);
+ result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
+ result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
+ result = 31 * result + (locale != null ? locale.hashCode() : 0);
+ result = 31 * result + (address1 != null ? address1.hashCode() : 0);
+ result = 31 * result + (address2 != null ? address2.hashCode() : 0);
+ result = 31 * result + (companyName != null ? companyName.hashCode() : 0);
+ result = 31 * result + (city != null ? city.hashCode() : 0);
+ result = 31 * result + (stateOrProvince != null ? stateOrProvince.hashCode() : 0);
+ result = 31 * result + (country != null ? country.hashCode() : 0);
+ result = 31 * result + (postalCode != null ? postalCode.hashCode() : 0);
+ result = 31 * result + (phone != null ? phone.hashCode() : 0);
+ result = 31 * result + (isMigrated != null ? isMigrated.hashCode() : 0);
+ result = 31 * result + (isNotifiedForInvoices != null ? isNotifiedForInvoices.hashCode() : 0);
+ return result;
}
@Override
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
index 68e6796..fd82926 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
@@ -30,12 +30,13 @@ import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.account.api.AccountData;
import com.ning.billing.account.api.AccountEmail;
+import com.ning.billing.account.api.BillCycleDay;
import com.ning.billing.account.api.DefaultAccount;
import com.ning.billing.account.api.DefaultAccountEmail;
import com.ning.billing.account.api.DefaultBillCycleDay;
+import com.ning.billing.account.api.MutableAccountData;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.mock.MockAccountBuilder;
-import com.ning.billing.mock.api.MockBillCycleDay;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.customfield.CustomField;
import com.ning.billing.util.customfield.StringCustomField;
@@ -55,8 +56,12 @@ import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-@Test(groups = {"slow", "account-dao"})
public class TestAccountDao extends AccountDaoTestBase {
+
+ private Account createTestAccount() {
+ return createTestAccount(5, UUID.randomUUID().toString().substring(0, 5));
+ }
+
private Account createTestAccount(final int billCycleDay) {
return createTestAccount(billCycleDay, "123-456-7890");
}
@@ -77,7 +82,7 @@ public class TestAccountDao extends AccountDaoTestBase {
phone, false, false);
}
- @Test
+ @Test(groups = "slow")
public void testBasic() throws EntityPersistenceException {
final Account a = createTestAccount(5);
accountDao.create(a, context);
@@ -97,7 +102,7 @@ public class TestAccountDao extends AccountDaoTestBase {
}
// simple test to ensure long phone numbers can be stored
- @Test
+ @Test(groups = "slow")
public void testLongPhoneNumber() throws EntityPersistenceException {
final Account account = createTestAccount(1, "123456789012345678901234");
accountDao.create(account, context);
@@ -107,13 +112,13 @@ public class TestAccountDao extends AccountDaoTestBase {
}
// simple test to ensure excessively long phone numbers cannot be stored
- @Test(expectedExceptions = {EntityPersistenceException.class})
+ @Test(groups = "slow", expectedExceptions = EntityPersistenceException.class)
public void testOverlyLongPhoneNumber() throws EntityPersistenceException {
final Account account = createTestAccount(1, "12345678901234567890123456");
accountDao.create(account, context);
}
- @Test
+ @Test(groups = "slow")
public void testGetById() throws EntityPersistenceException {
Account account = createTestAccount(1);
final UUID id = account.getId();
@@ -131,7 +136,7 @@ public class TestAccountDao extends AccountDaoTestBase {
assertEquals(account.getFirstNameLength(), firstNameLength);
}
- @Test
+ @Test(groups = "slow")
public void testCustomFields() throws EntityPersistenceException {
final String fieldName = "testField1";
final String fieldValue = "testField1_value";
@@ -149,7 +154,7 @@ public class TestAccountDao extends AccountDaoTestBase {
assertEquals(customField.getValue(), fieldValue);
}
- @Test
+ @Test(groups = "slow")
public void testTags() throws EntityPersistenceException, TagApiException {
final Account account = createTestAccount(1);
final TagDefinition definition = new DefaultTagDefinition("Test Tag", "For testing only", false);
@@ -165,7 +170,7 @@ public class TestAccountDao extends AccountDaoTestBase {
assertEquals(tagMap.values().iterator().next().getTagDefinitionId(), definition.getId());
}
- @Test
+ @Test(groups = "slow")
public void testGetIdFromKey() throws EntityPersistenceException {
final Account account = createTestAccount(1);
accountDao.create(account, context);
@@ -178,13 +183,13 @@ public class TestAccountDao extends AccountDaoTestBase {
}
}
- @Test(expectedExceptions = AccountApiException.class)
+ @Test(groups = "slow", expectedExceptions = AccountApiException.class)
public void testGetIdFromKeyForNullKey() throws AccountApiException {
final String key = null;
accountDao.getIdFromKey(key);
}
- @Test
+ @Test(groups = "slow")
public void testUpdate() throws Exception {
final Account account = createTestAccount(1);
accountDao.create(account, context);
@@ -217,7 +222,7 @@ public class TestAccountDao extends AccountDaoTestBase {
assertEquals(savedAccount.getPhone(), updatedAccount.getPhone());
}
- @Test
+ @Test(groups = "slow")
public void testAddingContactInformation() throws Exception {
final UUID accountId = UUID.randomUUID();
final DefaultAccount account = new DefaultAccount(accountId, "extKey123456", "myemail123456@glam.com",
@@ -257,27 +262,65 @@ public class TestAccountDao extends AccountDaoTestBase {
assertEquals(savedAccount.getPhone(), phone);
}
- @Test
- public void testExternalKeyCannotBeUpdated() throws Exception {
- final UUID accountId = UUID.randomUUID();
- final String originalExternalKey = "extKey1337";
+ @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
+ public void testShouldntBeAbleToUpdateExternalKey() throws Exception {
+ final Account account = createTestAccount();
+ accountDao.create(account, context);
- final DefaultAccount account = new DefaultAccount(accountId, originalExternalKey, "myemail1337@glam.com",
- "John Smith", 4, Currency.USD, new DefaultBillCycleDay(15), null,
- null, null, null, null, null, null, null, null, null, null,
- false, false);
+ final MutableAccountData otherAccount = account.toMutableAccountData();
+ otherAccount.setExternalKey(UUID.randomUUID().toString());
+
+ accountDao.update(new DefaultAccount(account.getId(), otherAccount), context);
+ }
+
+ @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
+ public void testShouldntBeAbleToUpdateCurrency() throws Exception {
+ final Account account = createTestAccount();
+ accountDao.create(account, context);
+
+ final MutableAccountData otherAccount = account.toMutableAccountData();
+ otherAccount.setCurrency(Currency.GBP);
+
+ accountDao.update(new DefaultAccount(account.getId(), otherAccount), context);
+ }
+
+ @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
+ public void testShouldntBeAbleToUpdateBillCycleDay() throws Exception {
+ final Account account = createTestAccount();
accountDao.create(account, context);
- final String buggyKey = "extKey1338";
- final DefaultAccount updatedAccountData = new DefaultAccount(accountId, buggyKey, "myemail1337@glam.com",
- "John Smith", 4, Currency.USD, new DefaultBillCycleDay(15), null,
- null, null, null, null, null, null, null, null, null, null,
- false, false);
- accountDao.update(updatedAccountData, context);
- Assert.assertNull(accountDao.getAccountByKey(buggyKey));
+ final MutableAccountData otherAccount = account.toMutableAccountData();
+ otherAccount.setBillCycleDay(new BillCycleDay() {
+ @Override
+ public int getDayOfMonthUTC() {
+ return account.getBillCycleDay().getDayOfMonthUTC() + 2;
+ }
+
+ @Override
+ public int getDayOfMonthLocal() {
+ return account.getBillCycleDay().getDayOfMonthLocal() + 2;
+ }
+ });
+
+ accountDao.update(new DefaultAccount(account.getId(), otherAccount), context);
+ }
+
+ @Test(groups = "slow")
+ public void testShouldBeAbleToUpdateSomeFields() throws Exception {
+ final Account account = createTestAccount();
+ accountDao.create(account, context);
+
+ final MutableAccountData otherAccount = account.toMutableAccountData();
+ otherAccount.setAddress1(UUID.randomUUID().toString());
+ otherAccount.setEmail(UUID.randomUUID().toString());
+
+ final DefaultAccount newAccount = new DefaultAccount(account.getId(), otherAccount);
+ accountDao.update(newAccount, context);
+
+ Assert.assertEquals(accountDao.getById(account.getId()), newAccount);
}
- @Test
+ @Test(groups = "slow")
public void testAccountEmail() {
List<AccountEmail> emails = new ArrayList<AccountEmail>();
@@ -315,7 +358,7 @@ public class TestAccountDao extends AccountDaoTestBase {
verifyAccountEmailAuditAndHistoryCount(accountId, 4);
}
- @Test
+ @Test(groups = "slow")
public void testAddAndRemoveAccountEmail() {
final UUID accountId = UUID.randomUUID();
final String email1 = UUID.randomUUID().toString();