Details
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java
index 2729faa..effca13 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/invoice/DefaultInvoicePaymentApi.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.UUID;
import org.joda.time.DateTime;
+import org.skife.jdbi.v2.exceptions.TransactionFailedException;
import com.ning.billing.ErrorCode;
import com.ning.billing.catalog.api.Currency;
@@ -38,6 +39,8 @@ import com.google.inject.Inject;
public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
+ private static final WithInvoiceApiException<InvoicePayment> invoicePaymentWithException = new WithInvoiceApiException<InvoicePayment>();
+
private final InvoiceDao dao;
@Inject
@@ -77,15 +80,6 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
dao.notifyOfPayment(invoicePayment, context);
}
- @Override
- public InvoicePayment createChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
- return dao.postChargeback(invoicePaymentId, amount, context);
- }
-
- @Override
- public InvoicePayment createChargeback(final UUID invoicePaymentId, final CallContext context) throws InvoiceApiException {
- return createChargeback(invoicePaymentId, null, context);
- }
@Override
public BigDecimal getRemainingAmountPaid(final UUID invoicePaymentId) {
@@ -115,9 +109,59 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
@Override
public InvoicePayment createRefund(final UUID paymentId, final BigDecimal amount, final boolean isInvoiceAdjusted,
final UUID paymentCookieId, final CallContext context) throws InvoiceApiException {
- if (amount.compareTo(BigDecimal.ZERO) <= 0) {
- throw new InvoiceApiException(ErrorCode.PAYMENT_REFUND_AMOUNT_NEGATIVE_OR_NULL);
+
+ return invoicePaymentWithException.executeAndThrow(new WithInvoiceApiExceptionCallback<InvoicePayment>() {
+
+ @Override
+ public InvoicePayment doHandle() throws InvoiceApiException {
+ if (amount.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new InvoiceApiException(ErrorCode.PAYMENT_REFUND_AMOUNT_NEGATIVE_OR_NULL);
+ }
+ return dao.createRefund(paymentId, amount, isInvoiceAdjusted, paymentCookieId, context);
+ }
+ });
+ }
+
+ @Override
+ public InvoicePayment createChargeback(final UUID invoicePaymentId, final CallContext context) throws InvoiceApiException {
+ return createChargeback(invoicePaymentId, null, context);
+ }
+
+
+ @Override
+ public InvoicePayment createChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
+
+ return invoicePaymentWithException.executeAndThrow(new WithInvoiceApiExceptionCallback<InvoicePayment>() {
+
+ @Override
+ public InvoicePayment doHandle() throws InvoiceApiException {
+ return dao.postChargeback(invoicePaymentId, amount, context);
+ }
+
+ });
+
+ }
+
+ //
+ // Allow to safely catch TransactionFailedException exceptions and rethrow the correct InvoiceApiException exception
+ //
+ private interface WithInvoiceApiExceptionCallback<T> {
+ public T doHandle() throws InvoiceApiException;
+ }
+
+ private static final class WithInvoiceApiException<T> {
+ public T executeAndThrow(WithInvoiceApiExceptionCallback<T> callback) throws InvoiceApiException {
+
+ try {
+ return callback.doHandle();
+ } catch (TransactionFailedException e) {
+ if (e.getCause() instanceof InvoiceApiException) {
+ InvoiceApiException realException = (InvoiceApiException) e.getCause();
+ throw realException;
+ } else {
+ throw e;
+ }
+ }
}
- return dao.createRefund(paymentId, amount, isInvoiceAdjusted, paymentCookieId, context);
}
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index 3f94759..68cf45c 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -385,7 +385,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
if (payment == null) {
throw new InvoiceApiException(ErrorCode.INVOICE_PAYMENT_NOT_FOUND, invoicePaymentId.toString());
} else {
- final InvoicePayment chargeBack = new DefaultInvoicePayment(UUID.randomUUID(), InvoicePaymentType.CHARGED_BACK, null,
+ final InvoicePayment chargeBack = new DefaultInvoicePayment(UUID.randomUUID(), InvoicePaymentType.CHARGED_BACK, payment.getPaymentId(),
payment.getInvoiceId(), context.getCreatedDate(), requestedChargedBackAmout.negate(), payment.getCurrency(), null, payment.getId());
invoicePaymentSqlDao.create(chargeBack, context);
return chargeBack;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/ChargebackJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/ChargebackJson.java
index 2cb35fc..9eba9a9 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/ChargebackJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/ChargebackJson.java
@@ -49,7 +49,7 @@ public class ChargebackJson {
this.requestedDate = null;
this.effectiveDate = chargeback.getPaymentDate();
this.chargebackAmount = chargeback.getAmount().negate();
- this.paymentId = chargeback.getLinkedInvoicePaymentId().toString();
+ this.paymentId = chargeback.getPaymentId().toString();
this.reason = null;
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/ChargebackResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/ChargebackResource.java
index c45836b..4fac93c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/ChargebackResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/ChargebackResource.java
@@ -28,7 +28,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
import com.ning.billing.ErrorCode;
import com.ning.billing.invoice.api.InvoiceApiException;
@@ -109,8 +108,7 @@ public class ChargebackResource extends JaxRsResourceBase {
public Response createChargeback(final ChargebackJson json,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
- @HeaderParam(HDR_COMMENT) final String comment,
- @javax.ws.rs.core.Context final UriInfo uriInfo) throws InvoiceApiException {
+ @HeaderParam(HDR_COMMENT) final String comment) throws InvoiceApiException {
final InvoicePayment invoicePayment = invoicePaymentApi.getInvoicePayment(UUID.fromString(json.getPaymentId()));
if (invoicePayment == null) {
throw new InvoiceApiException(ErrorCode.INVOICE_PAYMENT_NOT_FOUND, json.getPaymentId());
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestChargeback.java b/server/src/test/java/com/ning/billing/jaxrs/TestChargeback.java
index 0a7dcb2..c20e0fe 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestChargeback.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestChargeback.java
@@ -65,6 +65,7 @@ public class TestChargeback extends TestJaxrsBase {
response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
verifySingleChargebackResponse(response, input);
+
// Find the chargeback by account
response = doGet(JaxrsResource.CHARGEBACKS_PATH + "/accounts/" + payment.getAccountId(), DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
verifyCollectionChargebackResponse(response, input);
@@ -74,11 +75,55 @@ public class TestChargeback extends TestJaxrsBase {
verifyCollectionChargebackResponse(response, input);
}
+
+ @Test(groups = "slow")
+ public void testMultipleChargeback() throws Exception {
+ final PaymentJsonSimple payment = createAccountWithInvoiceAndPayment();
+
+ // We get a 249.95 payment so we do 4 chargeback and then the fifth should fail
+ final ChargebackJson input = new ChargebackJson(null, null, new BigDecimal("50.00"), payment.getPaymentId(), null);
+ final String jsonInput = mapper.writeValueAsString(input);
+
+ //
+ int count = 4;
+ Response response = null;
+ while (count-- > 0) {
+ response = doPost(JaxrsResource.CHARGEBACKS_PATH, jsonInput, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ assertEquals(response.getStatusCode(), javax.ws.rs.core.Response.Status.CREATED.getStatusCode(), response.getResponseBody());
+ }
+
+ // Last attempt should fail because this is more than the Payment
+ response = doPost(JaxrsResource.CHARGEBACKS_PATH, jsonInput, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ assertEquals(response.getStatusCode(), javax.ws.rs.core.Response.Status.BAD_REQUEST.getStatusCode(), response.getResponseBody());
+
+
+ // Find the chargeback by account
+ response = doGet(JaxrsResource.CHARGEBACKS_PATH + "/accounts/" + payment.getAccountId(), DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ assertEquals(response.getStatusCode(), javax.ws.rs.core.Response.Status.OK.getStatusCode());
+ ChargebackCollectionJson objFromJson = mapper.readValue(response.getResponseBody(), ChargebackCollectionJson.class);
+ assertEquals(objFromJson.getChargebacks().size(), 4);
+ for (int i = 0; i < objFromJson.getChargebacks().size(); i++) {
+ ChargebackJson chargeBack = objFromJson.getChargebacks().get(i);
+ assertTrue(chargeBack.getChargebackAmount().compareTo(input.getChargebackAmount()) == 0);
+ assertEquals(chargeBack.getPaymentId(), input.getPaymentId());
+ }
+
+ // Find the chargeback by payment
+ response = doGet(JaxrsResource.CHARGEBACKS_PATH + "/payments/" + payment.getPaymentId(), DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ assertEquals(response.getStatusCode(), javax.ws.rs.core.Response.Status.OK.getStatusCode());
+ objFromJson = mapper.readValue(response.getResponseBody(), ChargebackCollectionJson.class);
+ assertEquals(objFromJson.getChargebacks().size(), 4);
+
+ }
+
+
private void verifyCollectionChargebackResponse(final Response response, final ChargebackJson input) throws IOException {
assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
final ChargebackCollectionJson objFromJson = mapper.readValue(response.getResponseBody(), ChargebackCollectionJson.class);
assertEquals(objFromJson.getChargebacks().size(), 1);
- assertTrue(objFromJson.getChargebacks().get(0).getChargebackAmount().compareTo(input.getChargebackAmount()) == 0);
+ ChargebackJson chargeBack = objFromJson.getChargebacks().get(0);
+ assertTrue(chargeBack.getChargebackAmount().compareTo(input.getChargebackAmount()) == 0);
+ assertEquals(chargeBack.getPaymentId(), input.getPaymentId());
}
private void verifySingleChargebackResponse(final Response response, final ChargebackJson input) throws IOException {
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
index 582a384..fc0ddf2 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
@@ -101,13 +101,15 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
}
}
}
+ if (definitionIds.size() > 0) {
+ result.addAll(tagDefinitionSqlDao.getByIds(Collections2.transform(definitionIds, new Function<UUID, String>() {
+ @Override
+ public String apply(UUID input) {
+ return input.toString();
+ }
- result.addAll(tagDefinitionSqlDao.getByIds(Collections2.transform(definitionIds, new Function<UUID, String>() {
- @Override
- public String apply(UUID input) {
- return input.toString();
- }
- })));
+ })));
+ }
return result;
}
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java
index cd0e544..e1f4105 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java
@@ -95,6 +95,10 @@ public class TestAuditedTagDao extends UtilTestSuiteWithEmbeddedDB {
final List<UUID> uuids = new ArrayList<UUID>();
+ // Check with a empty Collecion first
+ List<TagDefinition> result = tagDefinitionDao.getByIds(uuids);
+ assertEquals(result.size(), 0);
+
TagDefinition defYo = tagDefinitionDao.create("yo", "defintion yo", context);
uuids.add(defYo.getId());
TagDefinition defBah = tagDefinitionDao.create("bah", "defintion bah", context);
@@ -102,7 +106,7 @@ public class TestAuditedTagDao extends UtilTestSuiteWithEmbeddedDB {
TagDefinition defZoo = tagDefinitionDao.create("zoo", "defintion zoo", context);
uuids.add(defZoo.getId());
- List<TagDefinition> result = tagDefinitionDao.getByIds(uuids);
+ result = tagDefinitionDao.getByIds(uuids);
assertEquals(result.size(), 3);
// Add control tag and retry