Details
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 057aaf6..0128490 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.google.inject.Inject;
@@ -155,4 +157,19 @@ public class DefaultAccountUserApi implements AccountUserApi {
public void removeEmail(final UUID accountId, final AccountEmail email, final CallContext context) {
accountEmailDao.removeEmail(accountId, email, context);
}
+
+ @Override
+ public void removePaymentMethod(final UUID accountId, final CallContext context) throws AccountApiException {
+ updatePaymentMethod(accountId, null, context);
+ }
+
+
+ @Override
+ public void updatePaymentMethod(final UUID accountId, @Nullable final UUID paymentMethodId, final CallContext context) throws AccountApiException {
+ try {
+ accountDao.updatePaymentMethod(accountId, paymentMethodId, context);
+ } catch (EntityPersistenceException e) {
+ throw new AccountApiException(e, e.getCode(), e.getMessage());
+ }
+ }
}
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 2f3cd25..0eb7907 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
@@ -20,6 +20,8 @@ import java.util.UUID;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.entity.EntityPersistenceException;
import com.ning.billing.util.entity.dao.UpdatableEntityDao;
public interface AccountDao extends UpdatableEntityDao<Account> {
@@ -31,4 +33,11 @@ public interface AccountDao extends UpdatableEntityDao<Account> {
* @throws AccountApiException when externalKey is null
*/
public UUID getIdFromKey(String externalKey) throws AccountApiException;
+
+ /**
+ *
+ * @param accountId the id of the account
+ * @param paymentMethodId the is of the current default paymentMethod
+ */
+ public void updatePaymentMethod(UUID accountId, UUID paymentMethodId, final CallContext context) throws EntityPersistenceException;
}
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 01b344a..8afc174 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
@@ -50,6 +50,9 @@ public interface AccountSqlDao extends UpdatableEntitySqlDao<Account>, Transacti
@SqlUpdate
public void update(@AccountBinder Account account, @CallContextBinder final CallContext context);
+ @SqlUpdate
+ public void updatePaymentMethod(@Bind("id") String accountId, @Bind("paymentMethodId") String paymentMethodId, @CallContextBinder final CallContext context);
+
@Override
@SqlUpdate
public void insertHistoryFromTransaction(@AccountHistoryBinder final EntityHistory<Account> account,
diff --git a/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
index 9e7faf8..3384230 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
@@ -171,4 +171,48 @@ public class AuditedAccountDao implements AccountDao {
public void test() {
accountSqlDao.test();
}
+
+ @Override
+ public void updatePaymentMethod(final UUID accountId, final UUID paymentMethodId, final CallContext context) throws EntityPersistenceException {
+ try {
+ accountSqlDao.inTransaction(new Transaction<Void, AccountSqlDao>() {
+ @Override
+ public Void inTransaction(final AccountSqlDao transactional, final TransactionStatus status) throws EntityPersistenceException, Bus.EventBusException {
+
+ final Account currentAccount = transactional.getById(accountId.toString());
+ 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());
+
+ final Long recordId = accountSqlDao.getRecordId(accountId.toString());
+ final EntityHistory<Account> history = new EntityHistory<Account>(accountId, recordId, account, ChangeType.UPDATE);
+ accountSqlDao.insertHistoryFromTransaction(history, context);
+
+ final Long historyRecordId = accountSqlDao.getHistoryRecordId(recordId);
+ final EntityAudit audit = new EntityAudit(TableName.ACCOUNT_HISTORY, historyRecordId, ChangeType.UPDATE);
+ accountSqlDao.insertAuditFromTransaction(audit, context);
+
+ final AccountChangeEvent changeEvent = new DefaultAccountChangeEvent(accountId, context.getUserToken(), currentAccount, account);
+ if (changeEvent.hasChanges()) {
+ try {
+ eventBus.postFromTransaction(changeEvent, transactional);
+ } catch (EventBusException e) {
+ log.warn("Failed to post account change event for account " + accountId, e);
+ }
+ }
+ return null;
+ }
+ });
+ } catch (RuntimeException re) {
+ if (re.getCause() instanceof EntityPersistenceException) {
+ throw (EntityPersistenceException) re.getCause();
+ } else {
+ throw re;
+ }
+ }
+ }
}
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 c6f3c83..8a8c0ce 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
@@ -49,6 +49,16 @@ update() ::= <<
WHERE id = :id;
>>
+
+updatePaymentMethod() ::= <<
+ UPDATE accounts
+ SET payment_method_id = :paymentMethodId
+ , updated_date = :updatedDate
+ , updated_by = :userName
+ WHERE id = :id;
+>>
+
+
historyFields() ::= <<
record_id,
id,
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 535dbbc..e525957 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
@@ -30,6 +30,7 @@ import com.ning.billing.account.api.user.DefaultAccountCreationEvent;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.entity.EntityPersistenceException;
public class MockAccountDao implements AccountDao {
private final Bus eventBus;
@@ -94,4 +95,11 @@ public class MockAccountDao implements AccountDao {
}
}
}
+
+ @Override
+ public void updatePaymentMethod(UUID accountId, UUID paymentMethodId,
+ CallContext context) throws EntityPersistenceException {
+ // TODO Auto-generated method stub
+
+ }
}
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 3c41f1d..be8abc4 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
@@ -54,6 +54,7 @@ import com.ning.billing.util.tag.dao.TagDefinitionSqlDao;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@@ -224,6 +225,25 @@ public class TestAccountDao extends AccountDaoTestBase {
}
@Test(groups = "slow")
+ public void testUpdatePaymentMethod() throws Exception {
+ final Account account = createTestAccount(1);
+ accountDao.create(account, context);
+
+ final UUID newPaymentMethodId = UUID.randomUUID();
+ accountDao.updatePaymentMethod(account.getId(), newPaymentMethodId, context);
+
+ final Account newAccount = accountDao.getById(account.getId());
+ assertEquals(newAccount.getPaymentMethodId(), newPaymentMethodId);
+
+ // And then set it to null
+ accountDao.updatePaymentMethod(account.getId(), null, context);
+
+ final Account newAccountWithPMNull = accountDao.getById(account.getId());
+ assertNull(newAccountWithPMNull.getPaymentMethodId());
+
+ }
+
+ @Test(groups = "slow")
public void testAddingContactInformation() throws Exception {
final UUID accountId = UUID.randomUUID();
final DefaultAccount account = new DefaultAccount(accountId, "extKey123456", "myemail123456@glam.com",
diff --git a/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java b/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
index 85e03cf..7a3868d 100644
--- a/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
+++ b/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
@@ -39,6 +39,10 @@ public interface AccountUserApi {
public void updateAccount(UUID accountId, AccountData accountData, CallContext context) throws AccountApiException;
+ public void removePaymentMethod(final UUID accountId, final CallContext context) throws AccountApiException;
+
+ public void updatePaymentMethod(UUID accountId, UUID paymentMethodId, CallContext context) throws AccountApiException;
+
public Account getAccountByKey(String key) throws AccountApiException;
public Account getAccountById(UUID accountId) throws AccountApiException;
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index bb9751c..e6d853c 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -161,7 +161,7 @@ public enum ErrorCode {
*/
TAG_DEFINITION_CONFLICTS_WITH_CONTROL_TAG(3900, "The tag definition name conflicts with a reserved %s"),
TAG_DEFINITION_ALREADY_EXISTS(3901, "The tag definition name already exists %s"),
- TAG_DEFINITION_DOES_NOT_EXIST(3902, "The tag definition name does not exist %s"),
+ TAG_DEFINITION_DOES_NOT_EXIST(3902, "The tag definition id does not exist %s"),
TAG_DEFINITION_IN_USE(3903, "The tag definition name is currently in use %s"),
CONTROL_TAG_DOES_NOT_EXIST(3904, "The control tag does not exist %s"),
@@ -172,6 +172,7 @@ public enum ErrorCode {
*
*/
TAG_DOES_NOT_EXIST(3950, "The tag does not exist (name: %s)"),
+ TAG_CANNOT_BE_REMOVED(3951, "The tag %s cannot be removed because %s"),
/*
*
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java b/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java
index bf38550..16c4c5f 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java
@@ -131,7 +131,7 @@ public interface PaymentApi {
public void updatePaymentMethod(final Account account, final UUID paymentMethodId, final PaymentMethodPlugin paymentMetghodInfo)
throws PaymentApiException;
- public void deletedPaymentMethod(final Account account, final UUID paymentMethodId, final CallContext context)
+ public void deletedPaymentMethod(final Account account, final UUID paymentMethodId, final boolean deleteDefaultPaymentMethodWithAutoPayOff, final CallContext context)
throws PaymentApiException;
public void setDefaultPaymentMethod(final Account account, final UUID paymentMethodId, final CallContext context)
diff --git a/api/src/main/java/com/ning/billing/util/tag/Tag.java b/api/src/main/java/com/ning/billing/util/tag/Tag.java
index 553ef5f..33584d9 100644
--- a/api/src/main/java/com/ning/billing/util/tag/Tag.java
+++ b/api/src/main/java/com/ning/billing/util/tag/Tag.java
@@ -18,6 +18,7 @@ package com.ning.billing.util.tag;
import java.util.UUID;
+
import com.ning.billing.util.entity.Entity;
public interface Tag extends Entity {
diff --git a/api/src/main/java/com/ning/billing/util/tag/TagDefinition.java b/api/src/main/java/com/ning/billing/util/tag/TagDefinition.java
index 88f9f1a..b00c46b 100644
--- a/api/src/main/java/com/ning/billing/util/tag/TagDefinition.java
+++ b/api/src/main/java/com/ning/billing/util/tag/TagDefinition.java
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.ning.billing.util.entity.Entity;
// TODO: needs to surface created date, created by, isControlTag
+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public interface TagDefinition extends Entity {
String getName();
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TagJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TagJson.java
new file mode 100644
index 0000000..531fd2b
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TagJson.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs.json;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.tag.TagDefinition;
+
+public class TagJson extends JsonBase {
+
+ private final String tagDefinitionId;
+ private final String tagDefinitionName;
+
+ @JsonCreator
+ public TagJson(@JsonProperty("tagDefinitionId") final String tagDefinitionId,
+ @JsonProperty("tagDefinitionName") final String tagDefinitionName,
+ @JsonProperty("auditLogs") @Nullable List<AuditLogJson> auditLogs) {
+ super(auditLogs);
+ this.tagDefinitionId = tagDefinitionId;
+ this.tagDefinitionName = tagDefinitionName;
+ }
+
+ public TagJson(final TagDefinition tagDefintion, @Nullable final List<AuditLog> auditLogs) {
+ this(tagDefintion.getId().toString(), tagDefintion.getName(), toAuditLogJson(auditLogs));
+ }
+
+ public String getTagDefinitionId() {
+ return tagDefinitionId;
+ }
+
+ public String getTagDefinitionName() {
+ return tagDefinitionName;
+ }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/PaymentApiExceptionMapper.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/PaymentApiExceptionMapper.java
index 551f0d2..44e26ff 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/PaymentApiExceptionMapper.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/PaymentApiExceptionMapper.java
@@ -57,7 +57,7 @@ public class PaymentApiExceptionMapper extends ExceptionMapperBase implements Ex
} else if (exception.getCode() == ErrorCode.PAYMENT_CREATE_REFUND.getCode()) {
return buildInternalErrorResponse(exception, uriInfo);
} else if (exception.getCode() == ErrorCode.PAYMENT_DEL_DEFAULT_PAYMENT_METHOD.getCode()) {
- return buildInternalErrorResponse(exception, uriInfo);
+ return buildBadRequestResponse(exception, uriInfo);
} else if (exception.getCode() == ErrorCode.PAYMENT_DEL_PAYMENT_METHOD.getCode()) {
return buildInternalErrorResponse(exception, uriInfo);
} else if (exception.getCode() == ErrorCode.PAYMENT_GET_PAYMENT_METHODS.getCode()) {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/TagApiExceptionMapper.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/TagApiExceptionMapper.java
index bcd1220..87010d3 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/TagApiExceptionMapper.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/TagApiExceptionMapper.java
@@ -40,6 +40,8 @@ public class TagApiExceptionMapper extends ExceptionMapperBase implements Except
public Response toResponse(final TagApiException exception) {
if (exception.getCode() == ErrorCode.TAG_DOES_NOT_EXIST.getCode()) {
return buildNotFoundResponse(exception, uriInfo);
+ } else if (exception.getCode() == ErrorCode.TAG_CANNOT_BE_REMOVED.getCode()) {
+ return buildBadRequestResponse(exception, uriInfo);
} else {
return buildBadRequestResponse(exception, uriInfo);
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index 47e8e64..a8093d6 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -39,6 +39,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
+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.AccountData;
@@ -79,6 +80,7 @@ import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.dao.ObjectType;
+import com.ning.billing.util.tag.ControlTagType;
import com.google.common.base.Function;
import com.google.common.collect.ArrayListMultimap;
@@ -217,7 +219,7 @@ public class AccountResource extends JaxRsResourceBase {
@Path("/{accountId:" + UUID_PATTERN + "}/" + TIMELINE)
@Produces(APPLICATION_JSON)
public Response getAccountTimeline(@PathParam("accountId") final String accountIdString,
- @QueryParam("audit") @DefaultValue("false") final Boolean withAudit) throws AccountApiException, PaymentApiException, EntitlementRepairException {
+ @QueryParam(QUERY_AUDIT) @DefaultValue("false") final Boolean withAudit) throws AccountApiException, PaymentApiException, EntitlementRepairException {
final UUID accountId = UUID.fromString(accountIdString);
final Account account = accountApi.getAccountById(accountId);
@@ -449,8 +451,8 @@ public class AccountResource extends JaxRsResourceBase {
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id));
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String id, @QueryParam(QUERY_AUDIT) @DefaultValue("false") final Boolean withAudit) throws TagDefinitionApiException {
+ return super.getTags(UUID.fromString(id), withAudit);
}
@POST
@@ -474,7 +476,26 @@ public class AccountResource extends JaxRsResourceBase {
@QueryParam(QUERY_TAGS) final String tagList,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
- @HeaderParam(HDR_COMMENT) final String comment) throws TagApiException {
+ @HeaderParam(HDR_COMMENT) final String comment) throws TagApiException, AccountApiException {
+
+ // Look if there is an AUTO_PAY_OFF for that account and check if the account has a default paymentMethod
+ // If not we can't remove the AUTO_PAY_OFF tag
+ final Collection<UUID> tagDefinitionUUIDs = getTagDefinitionUUIDs(tagList);
+ boolean isTagAutoPayOff = false;
+ for (UUID cur : tagDefinitionUUIDs) {
+ if (cur.equals(ControlTagType.AUTO_PAY_OFF.getId())) {
+ isTagAutoPayOff = true;
+ break;
+ }
+ }
+ final UUID accountId = UUID.fromString(id);
+ if (isTagAutoPayOff) {
+ final Account account = accountApi.getAccountById(accountId);
+ if (account.getPaymentMethodId() == null) {
+ throw new TagApiException(ErrorCode.TAG_CANNOT_BE_REMOVED, ControlTagType.AUTO_PAY_OFF, " the account does not have a default payment method");
+ }
+ }
+
return super.deleteTags(UUID.fromString(id), tagList,
context.createContext(createdBy, reason, comment));
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
index 3863737..889795d 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
@@ -164,8 +164,8 @@ public class BundleResource extends JaxRsResourceBase {
@GET
@Path("/{bundleId:" + UUID_PATTERN + "}/" + TAG_URI)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id));
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String id, @QueryParam(QUERY_AUDIT) @DefaultValue("false") final Boolean withAudit) throws TagDefinitionApiException {
+ return super.getTags(UUID.fromString(id), withAudit);
}
@PUT
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
index e89e850..816eaf3 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
@@ -394,8 +394,8 @@ public class InvoiceResource extends JaxRsResourceBase {
@GET
@Path(TAG_URI)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id));
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String id, @QueryParam(QUERY_AUDIT) @DefaultValue("false") final Boolean withAudit) throws TagDefinitionApiException {
+ return super.getTags(UUID.fromString(id), withAudit);
}
@POST
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
index 790ade4..e52d1c2 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
@@ -67,6 +67,10 @@ public interface JaxrsResource {
public static final String QUERY_BUNDLE_TRANSFER_ADDON = "transferAddOn";
public static final String QUERY_BUNDLE_TRANSFER_CANCEL_IMM = "cancelImmediately";
+ public static final String QUERY_DELETE_DEFAULT_PM_WITH_AUTO_PAY_OFF = "deleteDefaultPmWithAutoPayOff";
+
+ public static final String QUERY_AUDIT = "audit";
+
public static final String ACCOUNTS = "accounts";
public static final String ACCOUNTS_PATH = PREFIX + "/" + ACCOUNTS;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
index 6f2d2f1..7066e05 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -22,6 +22,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -31,7 +32,9 @@ import org.joda.time.format.ISODateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.ning.billing.ErrorCode;
import com.ning.billing.jaxrs.json.CustomFieldJson;
+import com.ning.billing.jaxrs.json.TagJson;
import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
import com.ning.billing.util.api.AuditUserApi;
import com.ning.billing.util.api.CustomFieldUserApi;
@@ -78,7 +81,7 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
this(uriBuilder, tagUserApi, customFieldUserApi, null);
}
- protected Response getTags(final UUID id) throws TagDefinitionApiException {
+ protected Response getTags(final UUID id, final boolean withAudit) throws TagDefinitionApiException {
final Map<String, Tag> tags = tagUserApi.getTags(id, getObjectType());
final Collection<UUID> tagIdList = (tags.size() == 0) ?
Collections.<UUID>emptyList() :
@@ -89,8 +92,35 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
}
});
+ final AtomicReference<TagDefinitionApiException> theException = new AtomicReference<TagDefinitionApiException>();
final List<TagDefinition> tagDefinitionList = tagUserApi.getTagDefinitions(tagIdList);
- return Response.status(Response.Status.OK).entity(tagDefinitionList).build();
+ final List<TagJson> result = ImmutableList.<TagJson>copyOf(Collections2.transform(tagIdList, new Function<UUID, TagJson>() {
+ @Override
+ public TagJson apply(UUID input) {
+ try {
+ final TagDefinition tagDefinition = findTagDefinitionFromId(tagDefinitionList, input);
+ return new TagJson(input.toString(), tagDefinition.getName(), null);
+ } catch (TagDefinitionApiException e) {
+ theException.set(e);
+ return null;
+ }
+ }
+ }));
+ // Yackk..
+ if (theException.get() != null) {
+ throw theException.get();
+ }
+
+ return Response.status(Response.Status.OK).entity(result).build();
+ }
+
+ private TagDefinition findTagDefinitionFromId(final List<TagDefinition> tagDefinitionList, final UUID tagDefinitionId) throws TagDefinitionApiException {
+ for (TagDefinition cur : tagDefinitionList) {
+ if (cur.getId().equals(tagDefinitionId)) {
+ return cur;
+ }
+ }
+ throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, tagDefinitionId);
}
protected Response createTags(final UUID id,
@@ -102,7 +132,7 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
return uriBuilder.buildResponse(this.getClass(), "getTags", id, uriInfo.getBaseUri().toString());
}
- private Collection<UUID> getTagDefinitionUUIDs(final String tagList) {
+ protected Collection<UUID> getTagDefinitionUUIDs(final String tagList) {
final String[] tagParts = tagList.split(",\\s*");
return Collections2.transform(ImmutableList.copyOf(tagParts), new Function<String, UUID>() {
@Override
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
index 91012ee..15d014b 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
@@ -104,13 +104,14 @@ public class PaymentMethodResource extends JaxRsResourceBase {
@Produces(APPLICATION_JSON)
@Path("/{paymentMethodId:" + UUID_PATTERN + "}")
public Response deletePaymentMethod(@PathParam("paymentMethodId") final String paymentMethodId,
+ @QueryParam(QUERY_DELETE_DEFAULT_PM_WITH_AUTO_PAY_OFF) @DefaultValue("false") final Boolean deleteDefaultPaymentMethodWithAutoPayOff,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment) throws PaymentApiException, AccountApiException {
final PaymentMethod paymentMethod = paymentApi.getPaymentMethodById(UUID.fromString(paymentMethodId));
final Account account = accountApi.getAccountById(paymentMethod.getAccountId());
- paymentApi.deletedPaymentMethod(account, UUID.fromString(paymentMethodId), context.createContext(createdBy, reason, comment));
+ paymentApi.deletedPaymentMethod(account, UUID.fromString(paymentMethodId), deleteDefaultPaymentMethodWithAutoPayOff, context.createContext(createdBy, reason, comment));
return Response.status(Status.OK).build();
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
index 3f49504..e2ce6f4 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
@@ -25,6 +25,7 @@ import java.util.UUID;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
@@ -170,8 +171,8 @@ public class PaymentResource extends JaxRsResourceBase {
@GET
@Path(TAG_URI)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id));
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String id, @QueryParam(QUERY_AUDIT) @DefaultValue("false") final Boolean withAudit) throws TagDefinitionApiException {
+ return super.getTags(UUID.fromString(id), withAudit);
}
@POST
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
index 03c30d2..69ebb23 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
@@ -374,8 +374,8 @@ public class SubscriptionResource extends JaxRsResourceBase {
@GET
@Path(TAG_URI)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id));
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String id, @QueryParam(QUERY_AUDIT) @DefaultValue("false") final Boolean withAudit) throws TagDefinitionApiException {
+ return super.getTags(UUID.fromString(id), withAudit);
}
@POST
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
index e568b61..fd7b8eb 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
@@ -105,4 +105,16 @@ public class BlockingAccountUserApi implements AccountUserApi {
public void removeEmail(final UUID accountId, final AccountEmail email, final CallContext context) {
userApi.removeEmail(accountId, email, context);
}
+
+ @Override
+ public void updatePaymentMethod(UUID accountId, UUID paymentMethodId,
+ CallContext context) throws AccountApiException {
+ userApi.updatePaymentMethod(accountId, paymentMethodId, context);
+ }
+
+ @Override
+ public void removePaymentMethod(UUID accountId, CallContext context)
+ throws AccountApiException {
+ userApi.removePaymentMethod(accountId, context);
+ }
}
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
index a2c1f11..2b10f8a 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
@@ -177,9 +177,9 @@ public class DefaultPaymentApi implements PaymentApi {
}
@Override
- public void deletedPaymentMethod(final Account account, final UUID paymentMethodId, final CallContext context)
+ public void deletedPaymentMethod(final Account account, final UUID paymentMethodId, final boolean deleteDefaultPaymentMethodWithAutoPayOff, final CallContext context)
throws PaymentApiException {
- methodProcessor.deletedPaymentMethod(account, paymentMethodId);
+ methodProcessor.deletedPaymentMethod(account, paymentMethodId, deleteDefaultPaymentMethodWithAutoPayOff);
}
@Override
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
index 83e4146..d1ca916 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
@@ -17,14 +17,13 @@ package com.ning.billing.payment.core;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
-import javax.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
@@ -50,22 +49,34 @@ import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
import com.ning.billing.payment.provider.DefaultNoOpPaymentMethodPlugin;
import com.ning.billing.payment.provider.ExternalPaymentProviderPlugin;
import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
+import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContext;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.globallocker.GlobalLocker;
import static com.ning.billing.payment.glue.PaymentModule.PLUGIN_EXECUTOR_NAMED;
public class PaymentMethodProcessor extends ProcessorBase {
+ private static final Logger log = LoggerFactory.getLogger(PaymentMethodProcessor.class);
+
+ private final Clock clock;
+
@Inject
public PaymentMethodProcessor(final PaymentProviderPluginRegistry pluginRegistry,
final AccountUserApi accountUserApi,
final Bus eventBus,
final PaymentDao paymentDao,
+ final TagUserApi tagUserApi,
+ final Clock clock,
final GlobalLocker locker,
@Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
- super(pluginRegistry, accountUserApi, eventBus, paymentDao, locker, executor);
+ super(pluginRegistry, accountUserApi, eventBus, paymentDao, tagUserApi, locker, executor);
+ this.clock = clock;
}
public Set<String> getAvailablePlugins() {
@@ -111,9 +122,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
paymentDao.insertPaymentMethod(pmModel, context);
if (setDefault) {
- final MutableAccountData updateAccountData = new DefaultMutableAccountData(account);
- updateAccountData.setPaymentMethodId(pm.getId());
- accountUserApi.updateAccount(account.getId(), updateAccountData, context);
+ accountUserApi.updatePaymentMethod(account.getId(), pm.getId(), context);
}
} catch (PaymentPluginApiException e) {
// STEPH all errors should also take a pluginName
@@ -276,7 +285,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
}
- public void deletedPaymentMethod(final Account account, final UUID paymentMethodId)
+ public void deletedPaymentMethod(final Account account, final UUID paymentMethodId, final boolean deleteDefaultPaymentMethodWithAutoPayOff)
throws PaymentApiException {
new WithAccountLock<Void>().processAccountWithLock(locker, account.getExternalKey(), new WithAccountLockCallback<Void>() {
@@ -290,7 +299,17 @@ public class PaymentMethodProcessor extends ProcessorBase {
try {
if (account.getPaymentMethodId().equals(paymentMethodId)) {
- throw new PaymentApiException(ErrorCode.PAYMENT_DEL_DEFAULT_PAYMENT_METHOD, account.getId());
+ if (!deleteDefaultPaymentMethodWithAutoPayOff) {
+ throw new PaymentApiException(ErrorCode.PAYMENT_DEL_DEFAULT_PAYMENT_METHOD, account.getId());
+ } else {
+ final CallContext context = new DefaultCallContext("PaymentMethodProcessor", CallOrigin.INTERNAL, UserType.SYSTEM, null, clock);
+ final boolean isAccountAutoPayOoff = isAccountAutoPayOff(account.getId());
+ if (!isAccountAutoPayOoff) {
+ log.info("Setting account {} to AUTO_PAY_OFF because of default payment method deletion");
+ setAccountAutoPayOff(account.getId(), context);
+ }
+ accountUserApi.removePaymentMethod(account.getId(), context);
+ }
}
final PaymentPluginApi pluginApi = getPluginApi(paymentMethodId, account.getId());
pluginApi.deletePaymentMethod(account.getExternalKey(), paymentMethodModel.getExternalId());
@@ -298,6 +317,8 @@ public class PaymentMethodProcessor extends ProcessorBase {
return null;
} catch (PaymentPluginApiException e) {
throw new PaymentApiException(ErrorCode.PAYMENT_DEL_PAYMENT_METHOD, account.getId(), e.getErrorMessage());
+ } catch (AccountApiException e) {
+ throw new PaymentApiException(e);
}
}
});
@@ -317,10 +338,9 @@ public class PaymentMethodProcessor extends ProcessorBase {
try {
final PaymentPluginApi pluginApi = getPluginApi(paymentMethodId, account.getId());
+
pluginApi.setDefaultPaymentMethod(account.getExternalKey(), paymentMethodModel.getExternalId());
- final MutableAccountData updateAccountData = new DefaultMutableAccountData(account);
- updateAccountData.setPaymentMethodId(paymentMethodId);
- accountUserApi.updateAccount(account.getId(), updateAccountData, context);
+ accountUserApi.updatePaymentMethod(account.getId(), paymentMethodId, context);
return null;
} catch (PaymentPluginApiException e) {
throw new PaymentApiException(ErrorCode.PAYMENT_UPD_PAYMENT_METHOD, account.getId(), e.getErrorMessage());
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
index 02b6cb4..7509404 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
@@ -81,7 +81,6 @@ public class PaymentProcessor extends ProcessorBase {
private final PaymentMethodProcessor paymentMethodProcessor;
private final InvoicePaymentApi invoicePaymentApi;
- private final TagUserApi tagUserApi;
private final FailedPaymentRetryServiceScheduler failedPaymentRetryService;
private final PluginFailureRetryServiceScheduler pluginFailureRetryService;
private final AutoPayRetryServiceScheduler autoPayoffRetryService;
@@ -109,10 +108,9 @@ public class PaymentProcessor extends ProcessorBase {
final GlobalLocker locker,
@Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor,
final CallContextFactory factory) {
- super(pluginRegistry, accountUserApi, eventBus, paymentDao, locker, executor);
+ super(pluginRegistry, accountUserApi, eventBus, paymentDao, tagUserApi, locker, executor);
this.paymentMethodProcessor = paymentMethodProcessor;
this.invoicePaymentApi = invoicePaymentApi;
- this.tagUserApi = tagUserApi;
this.failedPaymentRetryService = failedPaymentRetryService;
this.pluginFailureRetryService = pluginFailureRetryService;
this.autoPayoffRetryService = autoPayoffRetryService;
@@ -272,12 +270,7 @@ public class PaymentProcessor extends ProcessorBase {
!isInstantPayment &&
!isAccountAutoPayOff) {
log.warn(String.format("Setting account %s into AUTO_PAY_OFF because of bad payment %s", accountId, lastPaymentForPaymentMethod.getId()));
- try {
- tagUserApi.addTag(accountId, ObjectType.ACCOUNT, ControlTagType.AUTO_PAY_OFF.getId(), context);
- } catch (TagApiException e) {
- log.error("Failed to add AUTO_PAY_OFF on account " + accountId, e);
- throw new PaymentApiException(ErrorCode.PAYMENT_INTERNAL_ERROR, "Failed to add AUTO_PAY_OFF on account " + accountId);
- }
+ setAccountAutoPayOff(accountId, context);
}
}
@@ -312,16 +305,6 @@ public class PaymentProcessor extends ProcessorBase {
retryFailedPaymentInternal(paymentId, PaymentStatus.PAYMENT_FAILURE);
}
- private boolean isAccountAutoPayOff(final UUID accountId) {
- final Map<String, Tag> accountTags = tagUserApi.getTags(accountId, ObjectType.ACCOUNT);
- for (final Tag cur : accountTags.values()) {
- if (ControlTagType.AUTO_PAY_OFF.getId().equals(cur.getTagDefinitionId())) {
- return true;
- }
- }
- return false;
- }
-
private void retryFailedPaymentInternal(final UUID paymentId, final PaymentStatus... expectedPaymentStates) {
diff --git a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
index 33c1431..7d542e9 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
@@ -15,6 +15,7 @@
*/
package com.ning.billing.payment.core;
+import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -31,13 +32,19 @@ import com.ning.billing.payment.dao.PaymentDao;
import com.ning.billing.payment.dao.PaymentMethodModelDao;
import com.ning.billing.payment.plugin.api.PaymentPluginApi;
import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
+import com.ning.billing.util.api.TagApiException;
+import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
import com.ning.billing.util.bus.BusEvent;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.dao.ObjectType;
import com.ning.billing.util.globallocker.GlobalLock;
import com.ning.billing.util.globallocker.GlobalLocker;
import com.ning.billing.util.globallocker.GlobalLocker.LockerType;
import com.ning.billing.util.globallocker.LockFailedException;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
public abstract class ProcessorBase {
@@ -49,6 +56,7 @@ public abstract class ProcessorBase {
protected final GlobalLocker locker;
protected final ExecutorService executor;
protected final PaymentDao paymentDao;
+ protected final TagUserApi tagUserApi;
private static final Logger log = LoggerFactory.getLogger(ProcessorBase.class);
@@ -56,6 +64,7 @@ public abstract class ProcessorBase {
final AccountUserApi accountUserApi,
final Bus eventBus,
final PaymentDao paymentDao,
+ final TagUserApi tagUserApi,
final GlobalLocker locker,
final ExecutorService executor) {
this.pluginRegistry = pluginRegistry;
@@ -64,6 +73,27 @@ public abstract class ProcessorBase {
this.paymentDao = paymentDao;
this.locker = locker;
this.executor = executor;
+ this.tagUserApi = tagUserApi;
+ }
+
+ protected boolean isAccountAutoPayOff(final UUID accountId) {
+ final Map<String, Tag> accountTags = tagUserApi.getTags(accountId, ObjectType.ACCOUNT);
+ for (final Tag cur : accountTags.values()) {
+ if (ControlTagType.AUTO_PAY_OFF.getId().equals(cur.getTagDefinitionId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ protected void setAccountAutoPayOff(UUID accountId, CallContext context) throws PaymentApiException {
+ try {
+ tagUserApi.addTag(accountId, ObjectType.ACCOUNT, ControlTagType.AUTO_PAY_OFF.getId(), context);
+ } catch (TagApiException e) {
+ log.error("Failed to add AUTO_PAY_OFF on account " + accountId, e);
+ throw new PaymentApiException(ErrorCode.PAYMENT_INTERNAL_ERROR, "Failed to add AUTO_PAY_OFF on account " + accountId);
+ }
}
protected PaymentPluginApi getPaymentProviderPlugin(final UUID paymentMethodId) throws PaymentApiException {
diff --git a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
index 63706ba..a254ff2 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
@@ -48,6 +48,7 @@ import com.ning.billing.payment.dao.RefundModelDao.RefundStatus;
import com.ning.billing.payment.plugin.api.PaymentPluginApi;
import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
+import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallContextFactory;
@@ -77,10 +78,11 @@ public class RefundProcessor extends ProcessorBase {
final InvoicePaymentApi invoicePaymentApi,
final Bus eventBus,
final CallContextFactory factory,
+ final TagUserApi tagUserApi,
final PaymentDao paymentDao,
final GlobalLocker locker,
@Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
- super(pluginRegistry, accountUserApi, eventBus, paymentDao, locker, executor);
+ super(pluginRegistry, accountUserApi, eventBus, paymentDao, tagUserApi, locker, executor);
this.invoicePaymentApi = invoicePaymentApi;
this.factory = factory;
}
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
index 88369bf..f3a57e3 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
@@ -90,11 +90,13 @@ public class TestPaymentApi extends PaymentTestSuite {
@BeforeClass(groups = "fast")
public void setupClass() throws Exception {
- account = testHelper.createTestAccount("yoyo.yahoo.com");
+ account = testHelper.createTestAccount("yoyo.yahoo.com", false);
}
@BeforeMethod(groups = "fast")
- public void setUp() throws EventBusException {
+ public void setUp() throws Exception {
+ final PaymentMethodPlugin paymentMethodInfo = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), true, null);
+ testHelper.addTestPaymentMethod(account, paymentMethodInfo);
eventBus.start();
}
@@ -201,14 +203,24 @@ public class TestPaymentApi extends PaymentTestSuite {
boolean failed = false;
try {
- paymentApi.deletedPaymentMethod(account, newPaymentMethodId, context);
+ paymentApi.deletedPaymentMethod(account, newPaymentMethodId, false, context);
} catch (PaymentApiException e) {
failed = true;
}
assertTrue(failed);
- paymentApi.deletedPaymentMethod(account, initDefaultMethod.getId(), context);
+ paymentApi.deletedPaymentMethod(account, initDefaultMethod.getId(), true, context);
methods = paymentApi.getPaymentMethods(account, false);
assertEquals(methods.size(), 1);
+
+ // NOW retry with default payment method with special flag
+ paymentApi.deletedPaymentMethod(account, newPaymentMethodId, true, context);
+
+ methods = paymentApi.getPaymentMethods(account, false);
+ assertEquals(methods.size(), 0);
+
+
+
}
+
}
diff --git a/payment/src/test/java/com/ning/billing/payment/core/TestPaymentMethodProcessor.java b/payment/src/test/java/com/ning/billing/payment/core/TestPaymentMethodProcessor.java
index a349629..68f95b9 100644
--- a/payment/src/test/java/com/ning/billing/payment/core/TestPaymentMethodProcessor.java
+++ b/payment/src/test/java/com/ning/billing/payment/core/TestPaymentMethodProcessor.java
@@ -33,9 +33,12 @@ import com.ning.billing.payment.api.PaymentMethod;
import com.ning.billing.payment.dao.MockPaymentDao;
import com.ning.billing.payment.provider.DefaultPaymentProviderPluginRegistry;
import com.ning.billing.payment.provider.ExternalPaymentProviderPlugin;
+import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.clock.DefaultClock;
import com.ning.billing.util.globallocker.GlobalLocker;
public class TestPaymentMethodProcessor extends PaymentTestSuite {
@@ -47,12 +50,14 @@ public class TestPaymentMethodProcessor extends PaymentTestSuite {
final DefaultPaymentProviderPluginRegistry pluginRegistry = new DefaultPaymentProviderPluginRegistry(Mockito.mock(PaymentConfig.class));
pluginRegistry.register(new ExternalPaymentProviderPlugin(new ClockMock()), ExternalPaymentProviderPlugin.PLUGIN_NAME);
+ final Clock clock = new DefaultClock();
final AccountUserApi accountUserApi = Mockito.mock(AccountUserApi.class);
final Bus bus = Mockito.mock(Bus.class);
final MockPaymentDao paymentDao = new MockPaymentDao();
final GlobalLocker globalLocker = Mockito.mock(GlobalLocker.class);
final ExecutorService executorService = Mockito.mock(ExecutorService.class);
- processor = new PaymentMethodProcessor(pluginRegistry, accountUserApi, bus, paymentDao, globalLocker, executorService);
+ final TagUserApi tagUserApi = Mockito.mock(TagUserApi.class);
+ processor = new PaymentMethodProcessor(pluginRegistry, accountUserApi, bus, paymentDao, tagUserApi, clock, globalLocker, executorService);
}
@Test(groups = "fast")
diff --git a/payment/src/test/java/com/ning/billing/payment/TestHelper.java b/payment/src/test/java/com/ning/billing/payment/TestHelper.java
index af509ab..ed4c905 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestHelper.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestHelper.java
@@ -95,7 +95,7 @@ public class TestHelper {
return invoice;
}
- public Account createTestAccount(final String email) throws Exception {
+ public Account createTestAccount(final String email, final boolean addPaymentMethod) throws Exception {
final String name = "First" + UUID.randomUUID().toString() + " " + "Last" + UUID.randomUUID().toString();
final String externalKey = UUID.randomUUID().toString();
@@ -114,12 +114,14 @@ public class TestHelper {
Mockito.when(accountUserApi.getAccountById(Mockito.<UUID>any())).thenReturn(account);
Mockito.when(accountUserApi.getAccountByKey(Mockito.anyString())).thenReturn(account);
- final PaymentMethodPlugin pm = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), true, null);
- addTestPaymentMethod(account, pm);
+ if (addPaymentMethod) {
+ final PaymentMethodPlugin pm = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), true, null);
+ addTestPaymentMethod(account, pm);
+ }
return account;
}
- private void addTestPaymentMethod(final Account account, final PaymentMethodPlugin paymentMethodInfo) throws Exception {
+ public void addTestPaymentMethod(final Account account, final PaymentMethodPlugin paymentMethodInfo) throws Exception {
final UUID paymentMethodId = paymentApi.addPaymentMethod(PaymentTestModuleWithMocks.PLUGIN_TEST_NAME, account, true, paymentMethodInfo, context);
Mockito.when(account.getPaymentMethodId()).thenReturn(paymentMethodId);
}
diff --git a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
index 0c021a6..9deb279 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
@@ -151,7 +151,7 @@ public class TestRetryService extends PaymentTestSuite {
private void testSchedulesRetryInternal(final int maxTries, final FailureType failureType) throws Exception {
- final Account account = testHelper.createTestAccount("yiyi.gmail.com");
+ final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
final BigDecimal amount = new BigDecimal("10.00");
final UUID subscriptionId = UUID.randomUUID();
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
index 9d88abb..fab5627 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -42,6 +42,7 @@ import com.ning.billing.jaxrs.json.PaymentMethodJson;
import com.ning.billing.jaxrs.json.RefundJson;
import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
import com.ning.billing.jaxrs.json.TagDefinitionJson;
+import com.ning.billing.jaxrs.json.TagJson;
import com.ning.billing.jaxrs.resources.JaxrsResource;
import com.ning.http.client.Response;
@@ -226,6 +227,55 @@ public class TestAccount extends TestJaxrsBase {
baseJson = response.getResponseBody();
paymentMethods = mapper.readValue(baseJson, new TypeReference<List<PaymentMethodJson>>() {});
assertEquals(paymentMethods.size(), 1);
+
+
+ //
+ // DELETE DEFAULT PAYMENT METHOD (without special flag first)
+ //
+ uri = JaxrsResource.PAYMENT_METHODS_PATH + "/" + paymentMethodPP.getPaymentMethodId() ;
+ response = doDelete(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.BAD_REQUEST.getStatusCode());
+
+ //
+ // RETRY TO DELETE DEFAULT PAYMENT METHOD (with special flag this time)
+ //
+ uri = JaxrsResource.PAYMENT_METHODS_PATH + "/" + paymentMethodPP.getPaymentMethodId() ;
+ queryParams = new HashMap<String, String>();
+ queryParams.put(JaxrsResource.QUERY_DELETE_DEFAULT_PM_WITH_AUTO_PAY_OFF, "true");
+
+ response = doDelete(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+ // CHECK ACCOUNT IS NOW AUTO_PAY_OFF
+
+ uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + JaxrsResource.TAGS;
+ response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+ baseJson = response.getResponseBody();
+ List<TagJson> tagsJson = mapper.readValue(baseJson, new TypeReference<List<TagJson>>() {});
+ Assert.assertEquals(tagsJson.size(), 1);
+ TagJson tagJson = tagsJson.get(0);
+ Assert.assertEquals(tagJson.getTagDefinitionName(), "AUTO_PAY_OFF");
+ Assert.assertEquals(tagJson.getTagDefinitionId(), new UUID(0, 1).toString());
+
+ // FETCH ACCOUNT AGAIN AND CHECK THERE IS NO DEFAULT PAYMENT METHOD SET
+ uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId();
+ response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+
+ AccountJson updatedAccountJson = mapper.readValue(response.getResponseBody(), AccountJson.class);
+ Assert.assertEquals(updatedAccountJson.getAccountId(), accountJson.getAccountId());
+ Assert.assertNull(updatedAccountJson.getPaymentMethodId());
+
+ //
+ // FINALLY TRY TO REMOVE AUTO_PAY_OFF WITH NO DEFAULT PAYMENT METHOD ON ACCOUNT
+ //
+ uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + JaxrsResource.TAGS;
+ queryParams = new HashMap<String, String>();
+ queryParams.put(JaxrsResource.QUERY_TAGS, new UUID(0, 1).toString());
+ response = doDelete(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.BAD_REQUEST.getStatusCode());
+
}
@Test(groups = "slow")
diff --git a/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java b/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
index 53d0596..d0210c2 100644
--- a/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
+++ b/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
@@ -165,4 +165,17 @@ public class MockAccountUserApi implements AccountUserApi {
throws AccountApiException {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void updatePaymentMethod(UUID accountId, UUID paymentMethodId,
+ CallContext context) throws AccountApiException {
+ throw new UnsupportedOperationException();
+
+ }
+
+ @Override
+ public void removePaymentMethod(UUID accountId, CallContext context)
+ throws AccountApiException {
+ throw new UnsupportedOperationException();
+ }
}