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 5920cc2..62d03e4 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
@@ -139,9 +139,7 @@ public class ChargebackResource implements JaxrsResource {
context.createContext(createdBy, reason, comment));
return uriBuilder.buildResponse(ChargebackResource.class, "getChargeback", chargeBack.getId());
} catch (InvoiceApiException e) {
- final String error = String.format("Failed to create chargeback %s", json);
- log.info(error, e);
- return Response.status(Response.Status.BAD_REQUEST).entity(error).build();
+ return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
}
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 34cf968..386c3b2 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestChargeback.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestChargeback.java
@@ -45,6 +45,7 @@ import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
public class TestChargeback extends TestJaxrsBase {
+
@Test(groups = "slow")
public void testAddChargeback() throws Exception {
final PaymentJsonSimple payment = createAccountWithInvoiceAndPayment();
@@ -61,6 +62,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);
@@ -70,11 +72,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(), javax.ws.rs.core.Response.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 {