killbill-aplcache
Changes
account/src/test/java/com/ning/billing/account/api/user/DefaultAccountUserApiTestWithDB.java 106(+106 -0)
Details
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index cb2188f..27efd2e 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
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
+import com.ning.billing.account.dao.AccountModelDao;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.junction.api.BlockingState;
import com.ning.billing.util.entity.EntityBase;
@@ -63,10 +64,6 @@ public class DefaultAccount extends EntityBase implements Account {
private final Boolean isMigrated;
private final Boolean isNotifiedForInvoices;
- public DefaultAccount(final AccountData data) {
- this(UUID.randomUUID(), data);
- }
-
/**
* This call is used to update an existing account
*
@@ -129,6 +126,15 @@ public class DefaultAccount extends EntityBase implements Account {
this.isNotifiedForInvoices = isNotifiedForInvoices;
}
+ public DefaultAccount(final AccountModelDao accountModelDao) {
+ this(accountModelDao.getId(), accountModelDao.getCreatedDate(), accountModelDao.getUpdatedDate(), accountModelDao.getExternalKey(),
+ accountModelDao.getEmail(), accountModelDao.getName(), accountModelDao.getFirstNameLength(), accountModelDao.getCurrency(),
+ new DefaultBillCycleDay(accountModelDao.getBillingCycleDayLocal(), accountModelDao.getBillingCycleDayUTC()), accountModelDao.getPaymentMethodId(),
+ accountModelDao.getTimeZone(), accountModelDao.getLocale(), accountModelDao.getAddress1(), accountModelDao.getAddress2(),
+ accountModelDao.getCompanyName(), accountModelDao.getCity(), accountModelDao.getStateOrProvince(), accountModelDao.getCountry(),
+ accountModelDao.getPostalCode(), accountModelDao.getPhone(), accountModelDao.getMigrated(), accountModelDao.getIsNotifiedForInvoices());
+ }
+
@Override
public String getExternalKey() {
return Objects.firstNonNull(externalKey, DEFAULT_STRING_VALUE);
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccountEmail.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccountEmail.java
index b738270..d0bbbe3 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccountEmail.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccountEmail.java
@@ -31,10 +31,6 @@ public class DefaultAccountEmail extends EntityBase implements AccountEmail {
this.email = email;
}
- public DefaultAccountEmail(final AccountEmail source, final String newEmail) {
- this(source.getAccountId(), newEmail);
- }
-
public DefaultAccountEmail(final UUID id, final UUID accountId, final String email) {
super(id);
this.accountId = accountId;
diff --git a/account/src/main/java/com/ning/billing/account/api/svcs/DefaultAccountInternalApi.java b/account/src/main/java/com/ning/billing/account/api/svcs/DefaultAccountInternalApi.java
index d75cc23..2dc669b 100644
--- a/account/src/main/java/com/ning/billing/account/api/svcs/DefaultAccountInternalApi.java
+++ b/account/src/main/java/com/ning/billing/account/api/svcs/DefaultAccountInternalApi.java
@@ -29,6 +29,7 @@ import com.ning.billing.account.api.AccountEmail;
import com.ning.billing.account.api.DefaultAccount;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.AccountEmailDao;
+import com.ning.billing.account.dao.AccountModelDao;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.svcapi.account.AccountInternalApi;
@@ -46,24 +47,32 @@ public class DefaultAccountInternalApi implements AccountInternalApi {
@Override
public Account getAccountById(final UUID accountId, final InternalTenantContext context) throws AccountApiException {
- final Account account = accountDao.getById(accountId, context);
+ final AccountModelDao account = accountDao.getById(accountId, context);
if (account == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
}
- return account;
+ return new DefaultAccount(account);
}
@Override
public Account getAccountByRecordId(final Long recordId, final InternalTenantContext context) throws AccountApiException {
- return accountDao.getByRecordId(recordId, context);
+ final AccountModelDao account = accountDao.getByRecordId(recordId, context);
+ return new DefaultAccount(account);
}
@Override
public void updateAccount(final String externalKey, final AccountData accountData,
final InternalCallContext context) throws AccountApiException {
- final Account account = getAccountByKey(externalKey, context);
- final Account updatedAccount = new DefaultAccount(account.getId(), accountData);
- accountDao.update(updatedAccount, context);
+ final Account currentAccount = getAccountByKey(externalKey, context);
+ if (currentAccount == null) {
+ throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_KEY, externalKey);
+ }
+
+ // Set unspecified (null) fields to their current values
+ final Account updatedAccount = new DefaultAccount(currentAccount.getId(), accountData);
+ final AccountModelDao accountToUpdate = new AccountModelDao(currentAccount.getId(), updatedAccount.mergeWithDelegate(currentAccount));
+
+ accountDao.update(accountToUpdate, context);
}
@Override
@@ -74,11 +83,11 @@ public class DefaultAccountInternalApi implements AccountInternalApi {
@Override
public Account getAccountByKey(final String key, final InternalTenantContext context) throws AccountApiException {
- final Account account = accountDao.getAccountByKey(key, context);
- if (account == null) {
+ final AccountModelDao accountModelDao = accountDao.getAccountByKey(key, context);
+ if (accountModelDao == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_KEY, key);
}
- return account;
+ return new DefaultAccount(accountModelDao);
}
@Override
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
index 2d8ed85..f7d67f0 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
@@ -20,8 +20,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.DefaultChangedField;
+import com.ning.billing.account.dao.AccountModelDao;
import com.ning.billing.util.events.AccountChangeInternalEvent;
import com.ning.billing.util.events.ChangedField;
import com.ning.billing.util.events.DefaultBusInternalEvent;
@@ -49,7 +49,7 @@ public class DefaultAccountChangeEvent extends DefaultBusInternalEvent implement
this.changedFields = changedFields;
}
- public DefaultAccountChangeEvent(final UUID id, final UUID userToken, final Account oldData, final Account newData,
+ public DefaultAccountChangeEvent(final UUID id, final UUID userToken, final AccountModelDao oldData, final AccountModelDao newData,
final Long accountRecordId, final Long tenantRecordId) {
super(userToken, accountRecordId, tenantRecordId);
this.accountId = id;
@@ -134,7 +134,7 @@ public class DefaultAccountChangeEvent extends DefaultBusInternalEvent implement
return true;
}
- private List<ChangedField> calculateChangedFields(final Account oldData, final Account newData) {
+ private List<ChangedField> calculateChangedFields(final AccountModelDao oldData, final AccountModelDao newData) {
final List<ChangedField> tmpChangedFields = new ArrayList<ChangedField>();
@@ -152,8 +152,12 @@ public class DefaultAccountChangeEvent extends DefaultBusInternalEvent implement
(newData.getCurrency() != null) ? newData.getCurrency().toString() : null);
addIfValueChanged(tmpChangedFields,
- "billCycleDay",
- oldData.getBillCycleDay().toString(), newData.getBillCycleDay().toString());
+ "billCycleDayLocal",
+ String.valueOf(oldData.getBillingCycleDayLocal()), String.valueOf(newData.getBillingCycleDayLocal()));
+
+ addIfValueChanged(tmpChangedFields,
+ "billCycleDayUTC",
+ String.valueOf(oldData.getBillingCycleDayUTC()), String.valueOf(newData.getBillingCycleDayUTC()));
addIfValueChanged(tmpChangedFields, "paymentMethodId",
(oldData.getPaymentMethodId() != null) ? oldData.getPaymentMethodId().toString() : null,
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
index 6980388..a43baaa 100644
--- 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
@@ -20,10 +20,10 @@ import java.util.UUID;
import org.joda.time.DateTimeZone;
-import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountData;
import com.ning.billing.account.api.BillCycleDay;
import com.ning.billing.account.api.DefaultBillCycleDay;
+import com.ning.billing.account.dao.AccountModelDao;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.util.events.AccountCreationInternalEvent;
import com.ning.billing.util.events.DefaultBusInternalEvent;
@@ -48,7 +48,7 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
this.data = data;
}
- public DefaultAccountCreationEvent(final Account data, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
+ public DefaultAccountCreationEvent(final AccountModelDao data, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
super(userToken, accountRecordId, tenantRecordId);
this.id = data.getId();
this.data = new DefaultAccountData(data);
@@ -130,12 +130,12 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
private final boolean isMigrated;
private final boolean isNotifiedForInvoices;
- public DefaultAccountData(final Account d) {
+ public DefaultAccountData(final AccountModelDao d) {
this(d.getExternalKey() != null ? d.getExternalKey() : null,
d.getName(),
d.getFirstNameLength(),
d.getEmail(),
- new DefaultBillCycleDay(d.getBillCycleDay()),
+ new DefaultBillCycleDay(d.getBillingCycleDayLocal(), d.getBillingCycleDayUTC()),
d.getCurrency() != null ? d.getCurrency().name() : null,
d.getPaymentMethodId(),
d.getTimeZone() != null ? d.getTimeZone().getID() : null,
@@ -148,8 +148,8 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
d.getPostalCode(),
d.getCountry(),
d.getPhone(),
- d.isMigrated(),
- d.isNotifiedForInvoices());
+ d.getMigrated(),
+ d.getIsNotifiedForInvoices());
}
@JsonCreator
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
index 5986385..3e00949 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
@@ -19,6 +19,8 @@ package com.ning.billing.account.api.user;
import java.util.List;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.joda.time.DateTime;
import com.ning.billing.ErrorCode;
@@ -32,11 +34,15 @@ import com.ning.billing.account.api.DefaultAccountEmail;
import com.ning.billing.account.api.MigrationAccountData;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.AccountEmailDao;
+import com.ning.billing.account.dao.AccountModelDao;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallContextFactory;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.callcontext.TenantContext;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
public class DefaultAccountUserApi implements AccountUserApi {
@@ -62,35 +68,41 @@ public class DefaultAccountUserApi implements AccountUserApi {
throw new AccountApiException(ErrorCode.ACCOUNT_ALREADY_EXISTS, data.getExternalKey());
}
- final Account account = new DefaultAccount(data);
+ final AccountModelDao account = new AccountModelDao(data);
accountDao.create(account, internalCallContextFactory.createInternalCallContext(account.getId(), context));
- return account;
+ return new DefaultAccount(account);
}
@Override
public Account getAccountByKey(final String key, final TenantContext context) throws AccountApiException {
- final Account account = accountDao.getAccountByKey(key, internalCallContextFactory.createInternalTenantContext(context));
+ final AccountModelDao account = accountDao.getAccountByKey(key, internalCallContextFactory.createInternalTenantContext(context));
if (account == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_KEY, key);
}
- return account;
+ return new DefaultAccount(account);
}
@Override
public Account getAccountById(final UUID id, final TenantContext context) throws AccountApiException {
- final Account account = accountDao.getById(id, internalCallContextFactory.createInternalTenantContext(context));
+ final AccountModelDao account = accountDao.getById(id, internalCallContextFactory.createInternalTenantContext(context));
if (account == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, id);
}
- return account;
+ return new DefaultAccount(account);
}
@Override
public List<Account> getAccounts(final TenantContext context) {
- return accountDao.get(internalCallContextFactory.createInternalTenantContext(context));
+ final List<AccountModelDao> accountModelDaos = accountDao.get(internalCallContextFactory.createInternalTenantContext(context));
+ return ImmutableList.<Account>copyOf(Collections2.transform(accountModelDaos, new Function<AccountModelDao, Account>() {
+ @Override
+ public Account apply(@Nullable final AccountModelDao input) {
+ return new DefaultAccount(input);
+ }
+ }));
}
@Override
@@ -100,22 +112,35 @@ public class DefaultAccountUserApi implements AccountUserApi {
@Override
public void updateAccount(final Account account, final CallContext context) throws AccountApiException {
- accountDao.update(account, internalCallContextFactory.createInternalCallContext(account.getId(), context));
+ updateAccount(account.getId(), account, context);
}
@Override
public void updateAccount(final UUID accountId, final AccountData accountData, final CallContext context) throws AccountApiException {
- final Account account = new DefaultAccount(accountId, accountData);
- updateAccount(account, context);
+ final Account currentAccount = getAccountById(accountId, context);
+ if (currentAccount == null) {
+ throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
+ }
+
+ updateAccount(currentAccount, accountData, context);
}
@Override
public void updateAccount(final String externalKey, final AccountData accountData, final CallContext context) throws AccountApiException {
- final UUID accountId = getIdFromKey(externalKey, context);
- if (accountId == null) {
+ final Account currentAccount = getAccountByKey(externalKey, context);
+ if (currentAccount == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_KEY, externalKey);
}
- updateAccount(accountId, accountData, context);
+
+ updateAccount(currentAccount, accountData, context);
+ }
+
+ private void updateAccount(final Account currentAccount, final AccountData accountData, final CallContext context) throws AccountApiException {
+ // Set unspecified (null) fields to their current values
+ final Account updatedAccount = new DefaultAccount(currentAccount.getId(), accountData);
+ final AccountModelDao accountToUpdate = new AccountModelDao(currentAccount.getId(), updatedAccount.mergeWithDelegate(currentAccount));
+
+ accountDao.update(accountToUpdate, internalCallContextFactory.createInternalCallContext(accountToUpdate.getId(), context));
}
@Override
@@ -126,7 +151,7 @@ public class DefaultAccountUserApi implements AccountUserApi {
final CallContext migrationContext = callContextFactory.toMigrationCallContext(context, createdDate, updatedDate);
// Create the account
- final Account account = new DefaultAccount(data);
+ final Account account = new DefaultAccount(UUID.randomUUID(), data);
createAccount(account, migrationContext);
// Add associated contact emails
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 3935b19..1755dfd 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
@@ -18,15 +18,14 @@ package com.ning.billing.account.dao;
import java.util.UUID;
-import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.entity.dao.EntityDao;
-public interface AccountDao extends EntityDao<Account, AccountApiException> {
+public interface AccountDao extends EntityDao<AccountModelDao, AccountApiException> {
- public Account getAccountByKey(String key, InternalTenantContext context);
+ public AccountModelDao getAccountByKey(String key, InternalTenantContext context);
/**
* @throws AccountApiException when externalKey is null
@@ -39,5 +38,5 @@ public interface AccountDao extends EntityDao<Account, AccountApiException> {
*/
public void updatePaymentMethod(UUID accountId, UUID paymentMethodId, InternalCallContext context) throws AccountApiException;
- public void update(Account account, InternalCallContext context) throws AccountApiException;
+ public void update(AccountModelDao account, InternalCallContext context) throws AccountApiException;
}
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountEmailSqlDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountEmailSqlDao.java
index 7beb12f..ee830d4 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountEmailSqlDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountEmailSqlDao.java
@@ -26,8 +26,10 @@ import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
import com.ning.billing.account.api.AccountEmail;
+import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.entity.dao.Audited;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
@@ -36,6 +38,7 @@ import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
public interface AccountEmailSqlDao extends EntitySqlDao<AccountEmail> {
@SqlUpdate
+ @Audited(ChangeType.DELETE)
public void delete(@BindBean final AccountEmail accountEmail,
@BindBean final InternalCallContext context);
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountModelDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountModelDao.java
new file mode 100644
index 0000000..5a06b52
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountModelDao.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2010-2012 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 javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.entity.EntityBase;
+
+public class AccountModelDao extends EntityBase {
+
+ private final String externalKey;
+ private final String email;
+ private final String name;
+ private final Integer firstNameLength;
+ private final Currency currency;
+ private final int billingCycleDayLocal;
+ private final int billingCycleDayUTC;
+ private final UUID paymentMethodId;
+ private final DateTimeZone timeZone;
+ private final String locale;
+ private final String address1;
+ private final String address2;
+ private final String companyName;
+ private final String city;
+ private final String stateOrProvince;
+ private final String country;
+ private final String postalCode;
+ private final String phone;
+ private final Boolean isMigrated;
+ private final Boolean isNotifiedForInvoices;
+
+ public AccountModelDao(final UUID id, final DateTime createdDate, final DateTime updatedDate, final String externalKey,
+ final String email, final String name, final Integer firstNameLength, final Currency currency,
+ final int billingCycleDayLocal, final int billingCycleDayUTC, final UUID paymentMethodId, final DateTimeZone timeZone,
+ final String locale, final String address1, final String address2, final String companyName,
+ final String city, final String stateOrProvince, final String country, final String postalCode,
+ final String phone, final Boolean migrated, final Boolean notifiedForInvoices) {
+ super(id, createdDate, updatedDate);
+ this.externalKey = externalKey;
+ this.email = email;
+ this.name = name;
+ this.firstNameLength = firstNameLength;
+ this.currency = currency;
+ this.billingCycleDayLocal = billingCycleDayLocal;
+ this.billingCycleDayUTC = billingCycleDayUTC;
+ this.paymentMethodId = paymentMethodId;
+ this.timeZone = timeZone;
+ this.locale = locale;
+ this.address1 = address1;
+ this.address2 = address2;
+ this.companyName = companyName;
+ this.city = city;
+ this.stateOrProvince = stateOrProvince;
+ this.country = country;
+ this.postalCode = postalCode;
+ this.phone = phone;
+ this.isMigrated = migrated;
+ this.isNotifiedForInvoices = notifiedForInvoices;
+ }
+
+ public AccountModelDao(final UUID id, @Nullable final DateTime createdDate, final DateTime updatedDate, final AccountData account) {
+ this(id, createdDate, updatedDate, account.getExternalKey(),
+ account.getEmail(), account.getName(), account.getFirstNameLength(), account.getCurrency(), account.getBillCycleDay() == null ? 0 : account.getBillCycleDay().getDayOfMonthLocal(),
+ account.getBillCycleDay() == null ? 0 : account.getBillCycleDay().getDayOfMonthUTC(), account.getPaymentMethodId(), account.getTimeZone(), account.getLocale(), account.getAddress1(), account.getAddress2(),
+ account.getCompanyName(), account.getCity(), account.getStateOrProvince(), account.getCountry(), account.getPostalCode(),
+ account.getPhone(), account.isMigrated(), account.isNotifiedForInvoices());
+ }
+
+ public AccountModelDao(final UUID id, final AccountData account) {
+ this(id, null, null, account);
+ }
+
+ public AccountModelDao(final AccountData account) {
+ this(UUID.randomUUID(), account);
+ }
+
+ public String getExternalKey() {
+ return externalKey;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Integer getFirstNameLength() {
+ return firstNameLength;
+ }
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public int getBillingCycleDayLocal() {
+ return billingCycleDayLocal;
+ }
+
+ public int getBillingCycleDayUTC() {
+ return billingCycleDayUTC;
+ }
+
+ public UUID getPaymentMethodId() {
+ return paymentMethodId;
+ }
+
+ public DateTimeZone getTimeZone() {
+ return timeZone;
+ }
+
+ public String getLocale() {
+ return locale;
+ }
+
+ public String getAddress1() {
+ return address1;
+ }
+
+ public String getAddress2() {
+ return address2;
+ }
+
+ public String getCompanyName() {
+ return companyName;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public String getStateOrProvince() {
+ return stateOrProvince;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public String getPostalCode() {
+ return postalCode;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public Boolean getMigrated() {
+ return isMigrated;
+ }
+
+ // TODO Required for making the BindBeanFactory with Introspector work
+ // see Introspector line 571; they look at public method.
+ public Boolean getIsNotifiedForInvoices() {
+ return isNotifiedForInvoices;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("AccountModelDao");
+ sb.append("{externalKey='").append(externalKey).append('\'');
+ sb.append(", email='").append(email).append('\'');
+ sb.append(", name='").append(name).append('\'');
+ sb.append(", firstNameLength=").append(firstNameLength);
+ sb.append(", currency=").append(currency);
+ sb.append(", billingCycleDayLocal=").append(billingCycleDayLocal);
+ sb.append(", billingCycleDayUTC=").append(billingCycleDayUTC);
+ sb.append(", paymentMethodId=").append(paymentMethodId);
+ sb.append(", timeZone=").append(timeZone);
+ sb.append(", locale='").append(locale).append('\'');
+ sb.append(", address1='").append(address1).append('\'');
+ sb.append(", address2='").append(address2).append('\'');
+ sb.append(", companyName='").append(companyName).append('\'');
+ sb.append(", city='").append(city).append('\'');
+ sb.append(", stateOrProvince='").append(stateOrProvince).append('\'');
+ sb.append(", country='").append(country).append('\'');
+ sb.append(", postalCode='").append(postalCode).append('\'');
+ sb.append(", phone='").append(phone).append('\'');
+ sb.append(", isMigrated=").append(isMigrated);
+ sb.append(", isNotifiedForInvoices=").append(isNotifiedForInvoices);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ final AccountModelDao that = (AccountModelDao) o;
+
+ if (billingCycleDayLocal != that.billingCycleDayLocal) {
+ return false;
+ }
+ if (billingCycleDayUTC != that.billingCycleDayUTC) {
+ return false;
+ }
+ 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 (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 = super.hashCode();
+ result = 31 * 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 + billingCycleDayLocal;
+ result = 31 * result + billingCycleDayUTC;
+ 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;
+ }
+}
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
index efc0a0a..7e86da0 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
@@ -19,53 +19,39 @@ package com.ning.billing.account.dao;
import java.util.UUID;
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 com.ning.billing.account.api.Account;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
-import com.ning.billing.util.callcontext.InternalTenantContextBinder;
-import com.ning.billing.util.dao.EntityHistory;
import com.ning.billing.util.dao.UuidMapper;
import com.ning.billing.util.entity.dao.Audited;
+import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
-import com.ning.billing.util.entity.dao.UpdatableEntitySqlDao;
@EntitySqlDaoStringTemplate
-@RegisterMapper({UuidMapper.class, AccountMapper.class})
-public interface AccountSqlDao extends UpdatableEntitySqlDao<Account> {
+@RegisterMapper({UuidMapper.class, AccountModelDaoMapper.class})
+public interface AccountSqlDao extends EntitySqlDao<AccountModelDao> {
@SqlQuery
- public Account getAccountByKey(@Bind("externalKey") final String key,
- @InternalTenantContextBinder final InternalTenantContext context);
+ public AccountModelDao getAccountByKey(@Bind("externalKey") final String key,
+ @BindBean final InternalTenantContext context);
@SqlQuery
public UUID getIdFromKey(@Bind("externalKey") final String key,
- @InternalTenantContextBinder final InternalTenantContext context);
+ @BindBean final InternalTenantContext context);
- @Override
- @SqlUpdate
- @Audited(ChangeType.INSERT)
- public void create(@AccountBinder Account account,
- @InternalTenantContextBinder final InternalCallContext context);
-
- @Override
@SqlUpdate
@Audited(ChangeType.UPDATE)
- public void update(@AccountBinder Account account,
- @InternalTenantContextBinder final InternalCallContext context);
+ public void update(@BindBean final AccountModelDao account,
+ @BindBean final InternalCallContext context);
@SqlUpdate
@Audited(ChangeType.UPDATE)
public void updatePaymentMethod(@Bind("id") String accountId,
@Bind("paymentMethodId") String paymentMethodId,
- @InternalTenantContextBinder final InternalCallContext context);
-
- @Override
- @SqlUpdate
- public void addHistoryFromTransaction(@AccountHistoryBinder final EntityHistory<Account> account,
- @InternalTenantContextBinder final InternalCallContext context);
+ @BindBean final InternalCallContext context);
}
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
index b23bfe1..aa80504 100644
--- a/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
@@ -24,7 +24,6 @@ import org.slf4j.LoggerFactory;
import com.ning.billing.BillingExceptionBase;
import com.ning.billing.ErrorCode;
-import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.account.api.user.DefaultAccountChangeEvent;
import com.ning.billing.account.api.user.DefaultAccountCreationEvent;
@@ -45,7 +44,7 @@ import com.ning.billing.util.svcsapi.bus.InternalBus.EventBusException;
import com.google.inject.Inject;
-public class DefaultAccountDao extends EntityDaoBase<Account, AccountApiException> implements AccountDao {
+public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, AccountApiException> implements AccountDao {
private static final Logger log = LoggerFactory.getLogger(DefaultAccountDao.class);
@@ -60,12 +59,12 @@ public class DefaultAccountDao extends EntityDaoBase<Account, AccountApiExceptio
}
@Override
- protected AccountApiException generateAlreadyExistsException(final Account account, final InternalCallContext context) {
+ protected AccountApiException generateAlreadyExistsException(final AccountModelDao account, final InternalCallContext context) {
return new AccountApiException(ErrorCode.ACCOUNT_ALREADY_EXISTS, account.getExternalKey());
}
@Override
- protected void postBusEventFromTransaction(final Account account, final Account savedAccount, final ChangeType changeType,
+ protected void postBusEventFromTransaction(final AccountModelDao account, final AccountModelDao savedAccount, final ChangeType changeType,
final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalCallContext context) throws BillingExceptionBase {
// This is only called for the create call (see update below)
switch (changeType) {
@@ -90,10 +89,10 @@ public class DefaultAccountDao extends EntityDaoBase<Account, AccountApiExceptio
}
@Override
- public Account getAccountByKey(final String key, final InternalTenantContext context) {
- return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Account>() {
+ public AccountModelDao getAccountByKey(final String key, final InternalTenantContext context) {
+ return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<AccountModelDao>() {
@Override
- public Account inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+ public AccountModelDao inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
return entitySqlDaoWrapperFactory.become(AccountSqlDao.class).getAccountByKey(key, context);
}
});
@@ -114,26 +113,24 @@ public class DefaultAccountDao extends EntityDaoBase<Account, AccountApiExceptio
}
@Override
- public void update(final Account specifiedAccount, final InternalCallContext context) throws AccountApiException {
+ public void update(final AccountModelDao specifiedAccount, final InternalCallContext context) throws AccountApiException {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
- public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws InternalBus.EventBusException, AccountApiException {
+ public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws EventBusException, AccountApiException {
final AccountSqlDao transactional = entitySqlDaoWrapperFactory.become(AccountSqlDao.class);
final UUID accountId = specifiedAccount.getId();
- final Account currentAccount = transactional.getById(accountId.toString(), context);
+ final AccountModelDao currentAccount = transactional.getById(accountId.toString(), context);
if (currentAccount == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
}
- // Set unspecified (null) fields to their current values
- final Account account = specifiedAccount.mergeWithDelegate(currentAccount);
- transactional.update(account, context);
+ transactional.update(specifiedAccount, context);
final AccountChangeInternalEvent changeEvent = new DefaultAccountChangeEvent(accountId,
context.getUserToken(),
currentAccount,
- account,
+ specifiedAccount,
context.getAccountRecordId(),
context.getTenantRecordId());
if (changeEvent.hasChanges()) {
@@ -153,17 +150,17 @@ public class DefaultAccountDao extends EntityDaoBase<Account, AccountApiExceptio
public void updatePaymentMethod(final UUID accountId, final UUID paymentMethodId, final InternalCallContext context) throws AccountApiException {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
- public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws EntityPersistenceException, InternalBus.EventBusException {
+ public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws EntityPersistenceException, EventBusException {
final AccountSqlDao transactional = entitySqlDaoWrapperFactory.become(AccountSqlDao.class);
- final Account currentAccount = transactional.getById(accountId.toString(), context);
+ final AccountModelDao currentAccount = transactional.getById(accountId.toString(), context);
if (currentAccount == null) {
throw new EntityPersistenceException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
}
final String thePaymentMethodId = paymentMethodId != null ? paymentMethodId.toString() : null;
transactional.updatePaymentMethod(accountId.toString(), thePaymentMethodId, context);
- final Account account = transactional.getById(accountId.toString(), context);
+ final AccountModelDao account = transactional.getById(accountId.toString(), context);
final AccountChangeInternalEvent changeEvent = new DefaultAccountChangeEvent(accountId, context.getUserToken(), currentAccount, account,
context.getAccountRecordId(), context.getTenantRecordId());
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountEmailSqlDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountEmailSqlDao.sql.stg
index aab878c..db12678 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/AccountEmailSqlDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountEmailSqlDao.sql.stg
@@ -1,5 +1,8 @@
-group account_emails: EntitySqlDao;
+group AccountEmailSqlDao: EntitySqlDao;
+tableName() ::= "account_emails"
+
+historyTableName() ::= "account_email_history"
tableFields(prefix) ::= <<
account_id
@@ -20,8 +23,6 @@ tableValues() ::= <<
, :updatedDate
>>
-historyTableName() ::= "account_email_history"
-
getEmailByAccountId() ::= <<
select
<allTableFields()>
@@ -31,19 +32,7 @@ where account_id = :accountId
;
>>
-updateFromTransaction() ::= <<
- UPDATE account_emails
- SET email = :email, updated_by = :userName, updated_date = :updatedDate
- WHERE id = :id <AND_CHECK_TENANT()>;
->>
-
-deleteFromTransaction() ::= <<
+delete() ::= <<
DELETE FROM account_emails
WHERE id = :id <AND_CHECK_TENANT()>;
>>
-
-
-getByAccountId() ::= <<
- SELECT <fields()> FROM account_emails WHERE account_id = :accountId <AND_CHECK_TENANT()>;
->>
-
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
index e50cc57..88f3ec4 100644
--- 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
@@ -1,7 +1,8 @@
-group AccountDaoSql: EntitySqlDao;
+group AccountSqlDao: EntitySqlDao;
-tableName() ::= "accounts";
-historyTableName() ::= "account_history";
+tableName() ::= "accounts"
+
+historyTableName() ::= "account_history"
tableFields(prefix) ::= <<
<prefix>external_key
@@ -54,7 +55,8 @@ tableValues() ::= <<
, :createdBy
, :createdDate
, :updatedBy
- >>
+, :updatedDate
+>>
/** The accounts table doesn't have an account_record_id column (it's the record_id) **/
accountRecordIdFieldWithComma(prefix) ::= ""
@@ -67,7 +69,7 @@ update() ::= <<
payment_method_id = :paymentMethodId, time_zone = :timeZone, locale = :locale,
address1 = :address1, address2 = :address2, company_name = :companyName, city = :city, state_or_province = :stateOrProvince,
country = :country, postal_code = :postalCode, phone = :phone,
- is_notified_for_invoices = :isNotifiedForInvoices, updated_date = :updatedDate, updated_by = :userName
+ is_notified_for_invoices = :isNotifiedForInvoices, updated_date = :updatedDate, updated_by = :updatedBy
WHERE id = :id <AND_CHECK_TENANT()>;
>>
@@ -76,14 +78,14 @@ updatePaymentMethod() ::= <<
UPDATE accounts
SET payment_method_id = :paymentMethodId
, updated_date = :updatedDate
- , updated_by = :userName
+ , updated_by = :updatedBy
WHERE id = :id <AND_CHECK_TENANT()>;
>>
getAccountByKey() ::= <<
- select <accountFields()>
+ select <allTableFields()>
from accounts
where external_key = :externalKey <AND_CHECK_TENANT()>;
>>
diff --git a/account/src/test/java/com/ning/billing/account/api/user/DefaultAccountUserApiTestWithDB.java b/account/src/test/java/com/ning/billing/account/api/user/DefaultAccountUserApiTestWithDB.java
new file mode 100644
index 0000000..acbc9a3
--- /dev/null
+++ b/account/src/test/java/com/ning/billing/account/api/user/DefaultAccountUserApiTestWithDB.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010-2012 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 java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.BillCycleDay;
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.account.api.DefaultMutableAccountData;
+import com.ning.billing.account.api.MutableAccountData;
+import com.ning.billing.account.dao.AccountDaoTestBase;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+
+public class DefaultAccountUserApiTestWithDB extends AccountDaoTestBase {
+
+ private AccountUserApi accountUserApi;
+
+ @BeforeMethod(groups = "slow")
+ public void setUp() throws Exception {
+ final DefaultCallContextFactory callContextFactory = new DefaultCallContextFactory(clock);
+ accountUserApi = new DefaultAccountUserApi(callContextFactory, internalCallContextFactory, accountDao, accountEmailDao);
+ }
+
+ @Test(groups = "slow")
+ public void testShouldBeAbleToPassNullForSomeFieldsToAvoidUpdate() throws Exception {
+ final Account account = accountUserApi.createAccount(new DefaultAccount(createTestAccount()), callContext);
+
+ // Update the address and leave other fields null
+ final MutableAccountData mutableAccountData = new DefaultMutableAccountData(null, null, null, 0, null, null, null,
+ null, null, null, null, null, null, null,
+ null, null, null, null, false, false);
+ final String newAddress1 = UUID.randomUUID().toString();
+ mutableAccountData.setAddress1(newAddress1);
+
+ accountUserApi.updateAccount(account.getId(), mutableAccountData, callContext);
+
+ final Account retrievedAccount = accountUserApi.getAccountById(account.getId(), callContext);
+ Assert.assertEquals(retrievedAccount.getAddress1(), newAddress1);
+ Assert.assertEquals(retrievedAccount.getAddress2(), account.getAddress2());
+ Assert.assertEquals(retrievedAccount.getCurrency(), account.getCurrency());
+ Assert.assertEquals(retrievedAccount.getExternalKey(), account.getExternalKey());
+ Assert.assertEquals(retrievedAccount.getBillCycleDay().getDayOfMonthLocal(), account.getBillCycleDay().getDayOfMonthLocal());
+ Assert.assertEquals(retrievedAccount.getBillCycleDay().getDayOfMonthUTC(), account.getBillCycleDay().getDayOfMonthUTC());
+ }
+
+ @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
+ public void testShouldntBeAbleToUpdateBillCycleDay() throws Exception {
+ final Account account = accountUserApi.createAccount(new DefaultAccount(createTestAccount()), callContext);
+
+ final MutableAccountData otherAccount = new DefaultAccount(account.getId(), account).toMutableAccountData();
+ otherAccount.setBillCycleDay(new BillCycleDay() {
+ @Override
+ public int getDayOfMonthUTC() {
+ return account.getBillCycleDay().getDayOfMonthUTC() + 2;
+ }
+
+ @Override
+ public int getDayOfMonthLocal() {
+ return account.getBillCycleDay().getDayOfMonthLocal() + 2;
+ }
+ });
+
+ accountUserApi.updateAccount(new DefaultAccount(account.getId(), otherAccount), callContext);
+ }
+
+ @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
+ public void testShouldntBeAbleToUpdateCurrency() throws Exception {
+ final Account account = accountUserApi.createAccount(new DefaultAccount(createTestAccount()), callContext);
+
+ final MutableAccountData otherAccount = new DefaultAccount(account.getId(), account).toMutableAccountData();
+ otherAccount.setCurrency(Currency.GBP);
+
+ accountUserApi.updateAccount(new DefaultAccount(account.getId(), otherAccount), callContext);
+ }
+
+ @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
+ public void testShouldntBeAbleToUpdateExternalKey() throws Exception {
+ final Account account = accountUserApi.createAccount(new DefaultAccount(createTestAccount()), callContext);
+
+ final MutableAccountData otherAccount = new DefaultAccount(account.getId(), account).toMutableAccountData();
+ otherAccount.setExternalKey(UUID.randomUUID().toString());
+
+ accountUserApi.updateAccount(new DefaultAccount(account.getId(), otherAccount), callContext);
+ }
+}
diff --git a/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java b/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java
index 9dd5f33..860ad1f 100644
--- a/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java
+++ b/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java
@@ -25,7 +25,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.ning.billing.account.AccountTestSuite;
-import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountData;
import com.ning.billing.account.api.AccountEmail;
import com.ning.billing.account.api.BillCycleDay;
@@ -34,6 +33,7 @@ import com.ning.billing.account.api.DefaultAccountEmail;
import com.ning.billing.account.api.DefaultBillCycleDay;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.AccountEmailDao;
+import com.ning.billing.account.dao.AccountModelDao;
import com.ning.billing.account.dao.MockAccountDao;
import com.ning.billing.account.dao.MockAccountEmailDao;
import com.ning.billing.catalog.api.Currency;
@@ -89,13 +89,14 @@ public class TestDefaultAccountUserApi extends AccountTestSuite {
accountUserApi.createAccount(data, callContext);
- final Account account = accountDao.getAccountByKey(externalKey, tenantContext);
+ final AccountModelDao account = accountDao.getAccountByKey(externalKey, tenantContext);
Assert.assertEquals(account.getExternalKey(), externalKey);
Assert.assertEquals(account.getEmail(), email);
Assert.assertEquals(account.getName(), name);
Assert.assertEquals(account.getFirstNameLength(), firstNameLength);
Assert.assertEquals(account.getCurrency(), currency);
- Assert.assertEquals(account.getBillCycleDay(), billCycleDay);
+ Assert.assertEquals(account.getBillingCycleDayLocal(), billCycleDay.getDayOfMonthLocal());
+ Assert.assertEquals(account.getBillingCycleDayUTC(), billCycleDay.getDayOfMonthUTC());
Assert.assertEquals(account.getPaymentMethodId(), paymentMethodId);
Assert.assertEquals(account.getTimeZone(), timeZone);
Assert.assertEquals(account.getLocale(), locale);
@@ -107,8 +108,8 @@ public class TestDefaultAccountUserApi extends AccountTestSuite {
Assert.assertEquals(account.getCountry(), country);
Assert.assertEquals(account.getPostalCode(), postalCode);
Assert.assertEquals(account.getPhone(), phone);
- Assert.assertEquals(account.isMigrated(), isMigrated);
- Assert.assertEquals(account.isNotifiedForInvoices(), isNotifiedForInvoices);
+ Assert.assertEquals(account.getMigrated(), isMigrated);
+ Assert.assertEquals(account.getIsNotifiedForInvoices(), isNotifiedForInvoices);
}
@Test(groups = "fast")
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
index 1f8a9cb..3b7b32f 100644
--- a/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
+++ b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
@@ -17,14 +17,18 @@
package com.ning.billing.account.dao;
import java.io.IOException;
+import java.util.UUID;
+import org.joda.time.DateTimeZone;
import org.skife.jdbi.v2.IDBI;
import org.testng.annotations.BeforeClass;
import com.ning.billing.account.AccountTestSuiteWithEmbeddedDB;
+import com.ning.billing.catalog.api.Currency;
import com.ning.billing.util.bus.DefaultBusService;
import com.ning.billing.util.bus.InMemoryInternalBus;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.svcsapi.bus.BusService;
import com.ning.billing.util.svcsapi.bus.InternalBus;
@@ -35,9 +39,11 @@ import static org.testng.Assert.fail;
public abstract class AccountDaoTestBase extends AccountTestSuiteWithEmbeddedDB {
protected final TagEventBuilder tagEventBuilder = new TagEventBuilder();
+ protected final Clock clock = new ClockMock();
protected AccountDao accountDao;
protected AccountEmailDao accountEmailDao;
+ protected InternalCallContextFactory internalCallContextFactory;
protected IDBI dbi;
protected InternalBus bus;
@@ -50,7 +56,8 @@ public abstract class AccountDaoTestBase extends AccountTestSuiteWithEmbeddedDB
final BusService busService = new DefaultBusService(bus);
((DefaultBusService) busService).startBus();
- accountDao = new DefaultAccountDao(dbi, bus, new InternalCallContextFactory(dbi, new ClockMock()));
+ internalCallContextFactory = new InternalCallContextFactory(dbi, clock);
+ accountDao = new DefaultAccountDao(dbi, bus, internalCallContextFactory);
// Health check test to make sure MySQL is setup properly
accountDao.test(internalCallContext);
@@ -61,4 +68,27 @@ public abstract class AccountDaoTestBase extends AccountTestSuiteWithEmbeddedDB
fail(t.toString());
}
}
+
+ protected AccountModelDao createTestAccount() {
+ return createTestAccount(5, UUID.randomUUID().toString().substring(0, 5));
+ }
+
+ protected AccountModelDao createTestAccount(final int billCycleDay) {
+ return createTestAccount(billCycleDay, "123-456-7890");
+ }
+
+ protected AccountModelDao createTestAccount(final int billCycleDay, final String phone) {
+ final String thisKey = "test" + UUID.randomUUID().toString();
+ final String lastName = UUID.randomUUID().toString();
+ final String thisEmail = "me@me.com" + " " + UUID.randomUUID();
+ final String firstName = "Bob";
+ final String name = firstName + " " + lastName;
+ final String locale = "EN-US";
+ final DateTimeZone timeZone = DateTimeZone.forID("America/Los_Angeles");
+ final int firstNameLength = firstName.length();
+
+ return new AccountModelDao(UUID.randomUUID(), null, null, thisKey, thisEmail, name, firstNameLength, Currency.USD,
+ billCycleDay, billCycleDay, UUID.randomUUID(), timeZone, locale,
+ null, null, null, null, null, null, null, phone, false, false);
+ }
}
diff --git a/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
index adab356..9f93178 100644
--- a/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
@@ -20,13 +20,13 @@ import java.util.Map;
import java.util.UUID;
import com.ning.billing.ErrorCode;
-import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.account.api.DefaultAccount;
import com.ning.billing.account.api.DefaultMutableAccountData;
import com.ning.billing.account.api.user.DefaultAccountChangeEvent;
import com.ning.billing.account.api.user.DefaultAccountCreationEvent;
import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.entity.dao.MockEntityDaoBase;
import com.ning.billing.util.events.AccountChangeInternalEvent;
@@ -35,7 +35,7 @@ import com.ning.billing.util.svcsapi.bus.InternalBus.EventBusException;
import com.google.inject.Inject;
-public class MockAccountDao extends MockEntityDaoBase<Account, AccountApiException> implements AccountDao {
+public class MockAccountDao extends MockEntityDaoBase<AccountModelDao, AccountApiException> implements AccountDao {
private final InternalBus eventBus;
@@ -45,23 +45,29 @@ public class MockAccountDao extends MockEntityDaoBase<Account, AccountApiExcepti
}
@Override
- public void create(final Account account, final InternalCallContext context) throws AccountApiException {
+ public void create(final AccountModelDao account, final InternalCallContext context) throws AccountApiException {
super.create(account, context);
try {
- eventBus.post(new DefaultAccountCreationEvent(account, null, getRecordId(account.getId(), context), context.getTenantRecordId()), context);
+ final Long accountRecordId = getRecordId(account.getId(), context);
+ final long tenantRecordId = context == null ? InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID
+ : context.getTenantRecordId();
+ eventBus.post(new DefaultAccountCreationEvent(account, null, accountRecordId, tenantRecordId), context);
} catch (final EventBusException ex) {
throw new RuntimeException(ex);
}
}
@Override
- public void update(final Account account, final InternalCallContext context) {
- final Account currentAccount = getById(account.getId(), context);
+ public void update(final AccountModelDao account, final InternalCallContext context) {
+ final AccountModelDao currentAccount = getById(account.getId(), context);
super.update(account, context);
+ final Long accountRecordId = getRecordId(account.getId(), context);
+ final long tenantRecordId = context == null ? InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID
+ : context.getTenantRecordId();
final AccountChangeInternalEvent changeEvent = new DefaultAccountChangeEvent(account.getId(), null, currentAccount, account,
- getRecordId(account.getId(), context), context.getTenantRecordId());
+ accountRecordId, tenantRecordId);
if (changeEvent.hasChanges()) {
try {
eventBus.post(changeEvent, context);
@@ -72,9 +78,9 @@ public class MockAccountDao extends MockEntityDaoBase<Account, AccountApiExcepti
}
@Override
- public Account getAccountByKey(final String externalKey, final InternalTenantContext context) {
- for (final Map<Long, Account> accountRow : entities.values()) {
- final Account account = accountRow.values().iterator().next();
+ public AccountModelDao getAccountByKey(final String externalKey, final InternalTenantContext context) {
+ for (final Map<Long, AccountModelDao> accountRow : entities.values()) {
+ final AccountModelDao account = accountRow.values().iterator().next();
if (account.getExternalKey().equals(externalKey)) {
return account;
}
@@ -85,20 +91,21 @@ public class MockAccountDao extends MockEntityDaoBase<Account, AccountApiExcepti
@Override
public UUID getIdFromKey(final String externalKey, final InternalTenantContext context) {
- final Account account = getAccountByKey(externalKey, context);
+ final AccountModelDao account = getAccountByKey(externalKey, context);
return account == null ? null : account.getId();
}
@Override
public void updatePaymentMethod(final UUID accountId, final UUID paymentMethodId, final InternalCallContext context) throws AccountApiException {
- final Account currentAccount = getById(accountId, context);
- if (currentAccount == null) {
+ final AccountModelDao currentAccountModelDao = getById(accountId, context);
+ if (currentAccountModelDao == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
}
+ final DefaultAccount currentAccount = new DefaultAccount(currentAccountModelDao);
final DefaultMutableAccountData updatedAccount = new DefaultMutableAccountData(currentAccount);
updatedAccount.setPaymentMethodId(paymentMethodId);
- update(new DefaultAccount(updatedAccount), context);
+ update(new AccountModelDao(accountId, updatedAccount), context);
}
}
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 e69f69a..f4197a7 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
@@ -16,18 +16,17 @@
package com.ning.billing.account.dao;
-import java.util.ArrayList;
+import java.sql.SQLException;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
import org.joda.time.DateTimeZone;
-import org.skife.jdbi.v2.Handle;
+import org.skife.jdbi.v2.exceptions.TransactionFailedException;
import org.testng.Assert;
import org.testng.annotations.Test;
+import com.ning.billing.ErrorCode;
import com.ning.billing.ObjectType;
-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;
@@ -35,17 +34,21 @@ 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.DefaultMutableAccountData;
import com.ning.billing.account.api.MutableAccountData;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.mock.MockAccountBuilder;
+import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.CustomFieldApiException;
import com.ning.billing.util.api.TagApiException;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.dao.AuditDao;
+import com.ning.billing.util.audit.dao.DefaultAuditDao;
import com.ning.billing.util.clock.DefaultClock;
import com.ning.billing.util.customfield.CustomField;
import com.ning.billing.util.customfield.StringCustomField;
import com.ning.billing.util.customfield.dao.AuditedCustomFieldDao;
import com.ning.billing.util.customfield.dao.CustomFieldDao;
+import com.ning.billing.util.dao.TableName;
import com.ning.billing.util.entity.EntityPersistenceException;
import com.ning.billing.util.tag.ControlTagType;
import com.ning.billing.util.tag.DefaultControlTag;
@@ -65,37 +68,13 @@ import static org.testng.Assert.fail;
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");
- }
-
- private Account createTestAccount(final int billCycleDay, final String phone) {
- final String thisKey = "test" + UUID.randomUUID().toString();
- final String lastName = UUID.randomUUID().toString();
- final String thisEmail = "me@me.com" + " " + UUID.randomUUID();
- final String firstName = "Bob";
- final String name = firstName + " " + lastName;
- final String locale = "EN-US";
- final DateTimeZone timeZone = DateTimeZone.forID("America/Los_Angeles");
- final int firstNameLength = firstName.length();
-
- return new DefaultAccount(UUID.randomUUID(), thisKey, thisEmail, name, firstNameLength, Currency.USD,
- new DefaultBillCycleDay(billCycleDay, billCycleDay), UUID.randomUUID(), timeZone, locale,
- null, null, null, null, null, null, null, // add null address fields
- phone, false, false);
- }
-
@Test(groups = "slow")
public void testBasic() throws AccountApiException {
- final Account a = createTestAccount(5);
+ final AccountModelDao a = createTestAccount(5);
accountDao.create(a, internalCallContext);
final String key = a.getExternalKey();
- Account r = accountDao.getAccountByKey(key, internalCallContext);
+ AccountModelDao r = accountDao.getAccountByKey(key, internalCallContext);
assertNotNull(r);
assertEquals(r.getExternalKey(), a.getExternalKey());
@@ -103,7 +82,7 @@ public class TestAccountDao extends AccountDaoTestBase {
assertNotNull(r);
assertEquals(r.getExternalKey(), a.getExternalKey());
- final List<Account> all = accountDao.get(internalCallContext);
+ final List<AccountModelDao> all = accountDao.get(internalCallContext);
assertNotNull(all);
assertTrue(all.size() >= 1);
}
@@ -111,23 +90,28 @@ public class TestAccountDao extends AccountDaoTestBase {
// simple test to ensure long phone numbers can be stored
@Test(groups = "slow")
public void testLongPhoneNumber() throws AccountApiException {
- final Account account = createTestAccount(1, "123456789012345678901234");
+ final AccountModelDao account = createTestAccount(1, "123456789012345678901234");
accountDao.create(account, internalCallContext);
- final Account saved = accountDao.getAccountByKey(account.getExternalKey(), internalCallContext);
+ final AccountModelDao saved = accountDao.getAccountByKey(account.getExternalKey(), internalCallContext);
assertNotNull(saved);
}
// simple test to ensure excessively long phone numbers cannot be stored
- @Test(groups = "slow", expectedExceptions = AccountApiException.class)
+ @Test(groups = "slow")
public void testOverlyLongPhoneNumber() throws AccountApiException {
- final Account account = createTestAccount(1, "12345678901234567890123456");
- accountDao.create(account, internalCallContext);
+ final AccountModelDao account = createTestAccount(1, "12345678901234567890123456");
+ try {
+ accountDao.create(account, internalCallContext);
+ Assert.fail();
+ } catch (RuntimeException e) {
+ Assert.assertTrue(e.getCause() instanceof SQLException);
+ }
}
@Test(groups = "slow")
public void testGetById() throws AccountApiException {
- Account account = createTestAccount(1);
+ AccountModelDao account = createTestAccount(1);
final UUID id = account.getId();
final String key = account.getExternalKey();
final String name = account.getName();
@@ -163,7 +147,7 @@ public class TestAccountDao extends AccountDaoTestBase {
@Test(groups = "slow")
public void testTags() throws EntityPersistenceException, TagApiException {
- final Account account = createTestAccount(1);
+ final AccountModelDao account = createTestAccount(1);
final TagDefinition definition = new DefaultTagDefinition("Test Tag", "For testing only", false);
final TagDefinitionSqlDao tagDefinitionDao = dbi.onDemand(TagDefinitionSqlDao.class);
tagDefinitionDao.create(definition, internalCallContext);
@@ -184,7 +168,7 @@ public class TestAccountDao extends AccountDaoTestBase {
@Test(groups = "slow")
public void testGetIdFromKey() throws AccountApiException {
- final Account account = createTestAccount(1);
+ final AccountModelDao account = createTestAccount(1);
accountDao.create(account, internalCallContext);
try {
@@ -203,25 +187,26 @@ public class TestAccountDao extends AccountDaoTestBase {
@Test(groups = "slow")
public void testUpdate() throws Exception {
- final Account account = createTestAccount(1);
+ final AccountModelDao account = createTestAccount(1);
accountDao.create(account, internalCallContext);
- final AccountData accountData = new MockAccountBuilder(account).migrated(false)
- .isNotifiedForInvoices(false)
- .timeZone(DateTimeZone.forID("Australia/Darwin"))
- .locale("FR-CA")
- .build();
+ final AccountData accountData = new MockAccountBuilder(new DefaultAccount(account)).migrated(false)
+ .isNotifiedForInvoices(false)
+ .timeZone(DateTimeZone.forID("Australia/Darwin"))
+ .locale("FR-CA")
+ .build();
- final Account updatedAccount = new DefaultAccount(account.getId(), accountData);
+ final AccountModelDao updatedAccount = new AccountModelDao(account.getId(), accountData);
accountDao.update(updatedAccount, internalCallContext);
- final Account savedAccount = accountDao.getAccountByKey(account.getExternalKey(), internalCallContext);
+ final AccountModelDao savedAccount = accountDao.getAccountByKey(account.getExternalKey(), internalCallContext);
assertNotNull(savedAccount);
assertEquals(savedAccount.getName(), updatedAccount.getName());
assertEquals(savedAccount.getEmail(), updatedAccount.getEmail());
assertEquals(savedAccount.getPaymentMethodId(), updatedAccount.getPaymentMethodId());
- assertEquals(savedAccount.getBillCycleDay(), updatedAccount.getBillCycleDay());
+ assertEquals(savedAccount.getBillingCycleDayLocal(), updatedAccount.getBillingCycleDayLocal());
+ assertEquals(savedAccount.getBillingCycleDayUTC(), updatedAccount.getBillingCycleDayUTC());
assertEquals(savedAccount.getFirstNameLength(), updatedAccount.getFirstNameLength());
assertEquals(savedAccount.getTimeZone(), updatedAccount.getTimeZone());
assertEquals(savedAccount.getLocale(), updatedAccount.getLocale());
@@ -236,19 +221,19 @@ public class TestAccountDao extends AccountDaoTestBase {
@Test(groups = "slow")
public void testUpdatePaymentMethod() throws Exception {
- final Account account = createTestAccount(1);
+ final AccountModelDao account = createTestAccount(1);
accountDao.create(account, internalCallContext);
final UUID newPaymentMethodId = UUID.randomUUID();
accountDao.updatePaymentMethod(account.getId(), newPaymentMethodId, internalCallContext);
- final Account newAccount = accountDao.getById(account.getId(), internalCallContext);
+ final AccountModelDao newAccount = accountDao.getById(account.getId(), internalCallContext);
assertEquals(newAccount.getPaymentMethodId(), newPaymentMethodId);
// And then set it to null
accountDao.updatePaymentMethod(account.getId(), null, internalCallContext);
- final Account newAccountWithPMNull = accountDao.getById(account.getId(), internalCallContext);
+ final AccountModelDao newAccountWithPMNull = accountDao.getById(account.getId(), internalCallContext);
assertNull(newAccountWithPMNull.getPaymentMethodId());
}
@@ -260,7 +245,7 @@ public class TestAccountDao extends AccountDaoTestBase {
"John Smith", 4, Currency.USD, new DefaultBillCycleDay(15), null,
DateTimeZone.forID("America/Cambridge_Bay"), "EN-CA",
null, null, null, null, null, null, null, null, false, false);
- accountDao.create(account, internalCallContext);
+ accountDao.create(new AccountModelDao(accountId, account), internalCallContext);
final String address1 = "123 address 1";
final String address2 = "456 address 2";
@@ -277,9 +262,9 @@ public class TestAccountDao extends AccountDaoTestBase {
address1, address2, companyName, city, stateOrProvince, country,
postalCode, phone, false, false);
- accountDao.update(updatedAccount, internalCallContext);
+ accountDao.update(new AccountModelDao(accountId, updatedAccount), internalCallContext);
- final Account savedAccount = accountDao.getById(accountId, internalCallContext);
+ final AccountModelDao savedAccount = accountDao.getById(accountId, internalCallContext);
assertNotNull(savedAccount);
assertEquals(savedAccount.getId(), accountId);
@@ -293,132 +278,72 @@ public class TestAccountDao extends AccountDaoTestBase {
assertEquals(savedAccount.getPhone(), phone);
}
- @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
- public void testShouldntBeAbleToUpdateExternalKey() throws Exception {
- final Account account = createTestAccount();
- accountDao.create(account, internalCallContext);
-
- final MutableAccountData otherAccount = account.toMutableAccountData();
- otherAccount.setExternalKey(UUID.randomUUID().toString());
-
- accountDao.update(new DefaultAccount(account.getId(), otherAccount), internalCallContext);
- }
-
- @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
- public void testShouldntBeAbleToUpdateCurrency() throws Exception {
- final Account account = createTestAccount();
- accountDao.create(account, internalCallContext);
-
- final MutableAccountData otherAccount = account.toMutableAccountData();
- otherAccount.setCurrency(Currency.GBP);
-
- accountDao.update(new DefaultAccount(account.getId(), otherAccount), internalCallContext);
- }
-
- @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
- public void testShouldntBeAbleToUpdateBillCycleDay() throws Exception {
- final Account account = createTestAccount();
- accountDao.create(account, internalCallContext);
-
- 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), internalCallContext);
- }
-
@Test(groups = "slow")
public void testShouldBeAbleToUpdateSomeFields() throws Exception {
- final Account account = createTestAccount();
+ final AccountModelDao account = createTestAccount();
accountDao.create(account, internalCallContext);
- final MutableAccountData otherAccount = account.toMutableAccountData();
+ final MutableAccountData otherAccount = new DefaultAccount(account).toMutableAccountData();
otherAccount.setAddress1(UUID.randomUUID().toString());
otherAccount.setEmail(UUID.randomUUID().toString());
- final DefaultAccount newAccount = new DefaultAccount(account.getId(), otherAccount);
- accountDao.update(newAccount, internalCallContext);
-
- Assert.assertEquals(accountDao.getById(account.getId(), internalCallContext), newAccount);
- }
-
- @Test(groups = "slow")
- public void testShouldBeAbleToPassNullForSomeFieldsToAvoidUpdate() throws Exception {
- final Account account = createTestAccount();
- accountDao.create(account, internalCallContext);
-
- // Update the address and leave other fields null
- final MutableAccountData mutableAccountData = new DefaultMutableAccountData(null, null, null, 0, null, null, null,
- null, null, null, null, null, null, null,
- null, null, null, null, false, false);
- final String newAddress1 = UUID.randomUUID().toString();
- mutableAccountData.setAddress1(newAddress1);
-
- final DefaultAccount newAccount = new DefaultAccount(account.getId(), mutableAccountData);
+ final AccountModelDao newAccount = new AccountModelDao(account.getId(), otherAccount);
accountDao.update(newAccount, internalCallContext);
- Assert.assertEquals(accountDao.getById(account.getId(), internalCallContext).getAddress1(), newAddress1);
- Assert.assertEquals(accountDao.getById(account.getId(), internalCallContext).getAddress2(), account.getAddress2());
- Assert.assertEquals(accountDao.getById(account.getId(), internalCallContext).getCurrency(), account.getCurrency());
- Assert.assertEquals(accountDao.getById(account.getId(), internalCallContext).getExternalKey(), account.getExternalKey());
- Assert.assertEquals(accountDao.getById(account.getId(), internalCallContext).getBillCycleDay(), account.getBillCycleDay());
+ final AccountModelDao retrievedAccount = accountDao.getById(account.getId(), internalCallContext);
+ Assert.assertEquals(retrievedAccount.getAddress1(), newAccount.getAddress1());
+ Assert.assertEquals(retrievedAccount.getEmail(), newAccount.getEmail());
}
@Test(groups = "slow")
public void testShouldBeAbleToHandleOtherBCDClass() throws Exception {
- final Account account = createTestAccount();
+ final AccountModelDao account = createTestAccount();
accountDao.create(account, internalCallContext);
- final MutableAccountData otherAccount = account.toMutableAccountData();
+ final MutableAccountData otherAccount = new DefaultAccount(account).toMutableAccountData();
otherAccount.setAddress1(UUID.randomUUID().toString());
otherAccount.setEmail(UUID.randomUUID().toString());
// Same BCD, but not .equals method
otherAccount.setBillCycleDay(new BillCycleDay() {
@Override
public int getDayOfMonthUTC() {
- return account.getBillCycleDay().getDayOfMonthUTC();
+ return account.getBillingCycleDayUTC();
}
@Override
public int getDayOfMonthLocal() {
- return account.getBillCycleDay().getDayOfMonthLocal();
+ return account.getBillingCycleDayLocal();
}
});
- final DefaultAccount newAccount = new DefaultAccount(account.getId(), otherAccount);
+ final AccountModelDao newAccount = new AccountModelDao(account.getId(), otherAccount);
accountDao.update(newAccount, internalCallContext);
- final Account newFetchedAccount = accountDao.getById(account.getId(), internalCallContext);
+ final AccountModelDao newFetchedAccount = accountDao.getById(account.getId(), internalCallContext);
Assert.assertEquals(newFetchedAccount.getAddress1(), newAccount.getAddress1());
Assert.assertEquals(newFetchedAccount.getEmail(), newAccount.getEmail());
// Same BCD
- Assert.assertEquals(newFetchedAccount.getBillCycleDay(), account.getBillCycleDay());
+ Assert.assertEquals(newFetchedAccount.getBillingCycleDayUTC(), account.getBillingCycleDayUTC());
+ Assert.assertEquals(newFetchedAccount.getBillingCycleDayLocal(), account.getBillingCycleDayLocal());
}
@Test(groups = "slow")
public void testShouldBeAbleToHandleBCDOfZeroZero() throws Exception {
- final Account account = createTestAccount(0);
+ final AccountModelDao account = createTestAccount(0);
accountDao.create(account, internalCallContext);
- final Account fetchedAccount = accountDao.getById(account.getId(), internalCallContext);
+ final AccountModelDao fetchedAccount = accountDao.getById(account.getId(), internalCallContext);
- final MutableAccountData otherAccount = account.toMutableAccountData();
+ final MutableAccountData otherAccount = new DefaultAccount(fetchedAccount).toMutableAccountData();
// Set BCD to null
otherAccount.setBillCycleDay(null);
- final DefaultAccount newAccount = new DefaultAccount(account.getId(), otherAccount);
+ final AccountModelDao newAccount = new AccountModelDao(account.getId(), otherAccount);
accountDao.update(newAccount, internalCallContext);
// Same BCD (zero/zero)
- Assert.assertEquals(accountDao.getById(account.getId(), internalCallContext), fetchedAccount);
+ final AccountModelDao retrievedAccount = accountDao.getById(account.getId(), internalCallContext);
+ Assert.assertEquals(retrievedAccount.getBillingCycleDayUTC(), fetchedAccount.getBillingCycleDayUTC());
+ Assert.assertEquals(retrievedAccount.getBillingCycleDayLocal(), fetchedAccount.getBillingCycleDayLocal());
}
@Test(groups = "slow")
@@ -430,13 +355,18 @@ public class TestAccountDao extends AccountDaoTestBase {
accountEmailDao.create(email, internalCallContext);
Assert.assertEquals(accountEmailDao.getByAccountId(accountId, internalCallContext).size(), 1);
- accountEmailDao.create(email, internalCallContext);
- Assert.assertEquals(accountEmailDao.getByAccountId(accountId, internalCallContext).size(), 1);
+ try {
+ accountEmailDao.create(email, internalCallContext);
+ Assert.fail();
+ } catch (TransactionFailedException e) {
+ Assert.assertTrue(e.getCause() instanceof AccountApiException);
+ Assert.assertEquals(((AccountApiException) e.getCause()).getCode(), ErrorCode.ACCOUNT_EMAIL_ALREADY_EXISTS.getCode());
+ }
}
@Test(groups = "slow")
public void testAccountEmail() throws AccountApiException {
- List<AccountEmail> emails = new ArrayList<AccountEmail>();
+ List<AccountEmail> emails;
// generate random account id
final UUID accountId = UUID.randomUUID();
@@ -447,30 +377,16 @@ public class TestAccountDao extends AccountDaoTestBase {
emails = accountEmailDao.getByAccountId(accountId, internalCallContext);
assertEquals(emails.size(), 1);
- // verify that history and audit contain one entry
- verifyAccountEmailAuditAndHistoryCount(accountId, 1);
-
- // update e-mail
- final AccountEmail updatedEmail = new DefaultAccountEmail(email, "test2@gmail.com");
- emails.clear();
- emails.add(updatedEmail);
- accountEmailDao.create(updatedEmail, internalCallContext);
- emails = accountEmailDao.getByAccountId(accountId, internalCallContext);
- assertEquals(emails.size(), 1);
-
- // verify that history and audit contain three entries
- // two inserts and one delete
- verifyAccountEmailAuditAndHistoryCount(accountId, 3);
+ // verify that audit contains one entry
+ final AuditDao audit = new DefaultAuditDao(dbi);
+ final List<AuditLog> auditLogs = audit.getAuditLogsForId(TableName.ACCOUNT_EMAIL, email.getId(), AuditLevel.FULL, internalCallContext);
+ assertEquals(auditLogs.size(), 1);
// delete e-mail
accountEmailDao.delete(email, internalCallContext);
- accountEmailDao.delete(updatedEmail, internalCallContext);
emails = accountEmailDao.getByAccountId(accountId, internalCallContext);
assertEquals(emails.size(), 0);
-
- // verify that history and audit contain four entries
- verifyAccountEmailAuditAndHistoryCount(accountId, 4);
}
@Test(groups = "slow")
@@ -506,32 +422,5 @@ public class TestAccountDao extends AccountDaoTestBase {
assertEquals(thirdEmails.size(), 1);
assertEquals(thirdEmails.get(0).getAccountId(), accountId);
assertEquals(thirdEmails.get(0).getEmail(), email2);
-
- // Verify that history and audit contain three entries (2 inserts and one delete)
- verifyAccountEmailAuditAndHistoryCount(accountId, 3);
- }
-
- private void verifyAccountEmailAuditAndHistoryCount(final UUID accountId, final int expectedCount) {
- final Handle handle = dbi.open();
-
- // verify audit
- StringBuilder sb = new StringBuilder();
- sb.append("select * from audit_log a ");
- sb.append("inner join account_email_history aeh on a.record_id = aeh.history_record_id ");
- sb.append("where a.table_name = 'account_email_history' ");
- sb.append(String.format("and aeh.account_id='%s'", accountId.toString()));
- List<Map<String, Object>> result = handle.select(sb.toString());
- assertEquals(result.size(), expectedCount);
-
- // ***** NOT IDEAL
- // ... but this works after the email record has been deleted; will likely fail when multiple emails exist for the same account
- // verify history table
- sb = new StringBuilder();
- sb.append("select * from account_email_history aeh ");
- sb.append(String.format("where aeh.account_id='%s'", accountId.toString()));
- result = handle.select(sb.toString());
- assertEquals(result.size(), expectedCount);
-
- handle.close();
}
}
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 7a243cc..06af0da 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
@@ -33,6 +33,7 @@ import org.testng.annotations.Test;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.account.api.user.DefaultAccountCreationEvent;
+import com.ning.billing.account.dao.AccountModelDao;
import com.ning.billing.analytics.AnalyticsTestModule;
import com.ning.billing.analytics.AnalyticsTestSuiteWithEmbeddedDB;
import com.ning.billing.analytics.MockDuration;
@@ -219,7 +220,7 @@ public class TestAnalyticsService extends AnalyticsTestSuiteWithEmbeddedDB {
}
private void createAccountCreationEvent(final Account account) {
- accountCreationNotification = new DefaultAccountCreationEvent(account, null, 1L, 1L);
+ accountCreationNotification = new DefaultAccountCreationEvent(new AccountModelDao(account.getId(), account), null, 1L, 1L);
}
private void createInvoiceAndPaymentCreationEvents(final Account account) {
diff --git a/util/src/main/java/com/ning/billing/util/dao/DateTimeZoneArgumentFactory.java b/util/src/main/java/com/ning/billing/util/dao/DateTimeZoneArgumentFactory.java
new file mode 100644
index 0000000..97fe381
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/dao/DateTimeZoneArgumentFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010-2012 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.dao;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.joda.time.DateTimeZone;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.Argument;
+import org.skife.jdbi.v2.tweak.ArgumentFactory;
+
+public class DateTimeZoneArgumentFactory implements ArgumentFactory<DateTimeZone> {
+
+ @Override
+ public boolean accepts(final Class<?> expectedType, final Object value, final StatementContext ctx) {
+ return value instanceof DateTimeZone;
+ }
+
+ @Override
+ public Argument build(final Class<?> expectedType, final DateTimeZone value, final StatementContext ctx) {
+ return new DateTimeZoneArgument(value);
+ }
+
+ public class DateTimeZoneArgument implements Argument {
+
+ private final DateTimeZone value;
+
+ public DateTimeZoneArgument(final DateTimeZone value) {
+ this.value = value;
+ }
+
+ @Override
+ public void apply(final int position, final PreparedStatement statement, final StatementContext ctx) throws SQLException {
+ if (value != null) {
+ statement.setString(position, value.toString());
+ } else {
+ statement.setNull(position, Types.VARCHAR);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DateTimeZoneArgument");
+ sb.append("{value=").append(value);
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/entity/dao/EntityDaoBase.java b/util/src/main/java/com/ning/billing/util/entity/dao/EntityDaoBase.java
index 2a1c085..1356796 100644
--- a/util/src/main/java/com/ning/billing/util/entity/dao/EntityDaoBase.java
+++ b/util/src/main/java/com/ning/billing/util/entity/dao/EntityDaoBase.java
@@ -24,7 +24,6 @@ import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.entity.Entity;
-import com.ning.billing.util.entity.EntityPersistenceException;
public abstract class EntityDaoBase<T extends Entity, U extends BillingExceptionBase> implements EntityDao<T, U> {
@@ -56,7 +55,7 @@ public abstract class EntityDaoBase<T extends Entity, U extends BillingException
}
protected void postBusEventFromTransaction(T entity, T savedEntity, ChangeType changeType, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalCallContext context)
- throws BillingExceptionBase {
+ throws BillingExceptionBase {
}
protected abstract U generateAlreadyExistsException(final T entity, final InternalCallContext context);
diff --git a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java
index b360462..c914ba7 100644
--- a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java
@@ -29,7 +29,6 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
-import com.ning.billing.util.callcontext.InternalTenantContextBinder;
import com.ning.billing.util.dao.AuditSqlDao;
import com.ning.billing.util.dao.HistorySqlDao;
import com.ning.billing.util.entity.Entity;
@@ -56,7 +55,7 @@ public interface EntitySqlDao<T extends Entity> extends AuditSqlDao, HistorySqlD
@BindBean final InternalTenantContext context);
@SqlQuery
- public Long getHistoryRecordId(@Bind("recordId") final Long recordId,
+ public Long getHistoryRecordId(@Bind("targetRecordId") final Long targetRecordId,
@BindBean final InternalTenantContext context);
@SqlQuery
diff --git a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
index fbf6a1c..9ba0b85 100644
--- a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
+++ b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
@@ -73,10 +73,12 @@ public class EntitySqlDaoWrapperInvocationHandler<T extends EntitySqlDao<U>, U e
final StatementContext statementContext = ((StatementException) t.getCause()).getStatementContext();
if (statementContext != null) {
final PreparedStatement statement = statementContext.getStatement();
- // Note: we rely on the JDBC driver to have a sane toString() method...
- errorDuringTransaction(t.getCause().getCause(), method, statement.toString());
- // Never reached
- return null;
+ if (statement != null) {
+ // Note: we rely on the JDBC driver to have a sane toString() method...
+ errorDuringTransaction(t.getCause().getCause(), method, statement.toString());
+ // Never reached
+ return null;
+ }
}
}
errorDuringTransaction(t.getCause().getCause(), method);
diff --git a/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
index 1fca412..06d7657 100644
--- a/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
@@ -159,11 +159,11 @@ where <idField("t.")> = :id
;
>>
-getHistoryRecordId(recordId) ::= <<
+getHistoryRecordId(targetRecordId) ::= <<
select
max(<recordIdField("t.")>)
-from <tableName()> t
-where <recordIdField("t.")> = :recordId
+from <historyTableName()> t
+where <targetRecordIdField("t.")> = :targetRecordId
<AND_CHECK_TENANT("t.")>
;
>>
diff --git a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
index 6c827f7..c0c7661 100644
--- a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
+++ b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
@@ -20,10 +20,10 @@ import java.util.concurrent.TimeUnit;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.IDBI;
-import org.skife.jdbi.v2.sqlobject.customizers.RegisterArgumentFactory;
import org.skife.jdbi.v2.tweak.transactions.SerializableTransactionRunner;
import com.ning.billing.util.dao.DateTimeArgumentFactory;
+import com.ning.billing.util.dao.DateTimeZoneArgumentFactory;
import com.ning.billing.util.dao.EnumArgumentFactory;
import com.ning.billing.util.dao.UUIDArgumentFactory;
@@ -65,6 +65,7 @@ public class DBIProvider implements Provider<IDBI> {
final BoneCPDataSource ds = new BoneCPDataSource(dbConfig);
final DBI dbi = new DBI(ds);
dbi.registerArgumentFactory(new UUIDArgumentFactory());
+ dbi.registerArgumentFactory(new DateTimeZoneArgumentFactory());
dbi.registerArgumentFactory(new DateTimeArgumentFactory());
dbi.registerArgumentFactory(new EnumArgumentFactory());
diff --git a/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritance.java b/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritance.java
index 62ed6c5..5513d73 100644
--- a/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritance.java
+++ b/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritance.java
@@ -94,8 +94,8 @@ public class TestStringTemplateInheritance extends UtilTestSuite {
";");
Assert.assertEquals(kombucha.getInstanceOf("getHistoryRecordId").toString(), "select\n" +
" max(t.record_id)\n" +
- "from kombucha t\n" +
- "where t.record_id = :recordId\n" +
+ "from kombucha_history t\n" +
+ "where t.target_record_id = :targetRecordId\n" +
"and t.tenant_record_id = :tenantRecordId\n" +
";");
Assert.assertEquals(kombucha.getInstanceOf("get").toString(), "select\n" +