Details
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 e82b61c..d906f1c 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
@@ -230,7 +230,7 @@ public class TestAnalyticsService extends TestWithEmbeddedDB {
invoiceCreationNotification = new DefaultInvoiceCreationEvent(invoice.getId(), account.getId(),
INVOICE_AMOUNT, ACCOUNT_CURRENCY, clock.getUTCNow(), null);
- paymentInfoNotification = new DefaultPaymentInfoEvent(account.getId(), invoices.get(0).getId(), null, invoices.get(0).getBalance(), -1, PaymentStatus.UNKNOWN, null, new DateTime());
+ paymentInfoNotification = new DefaultPaymentInfoEvent(account.getId(), invoices.get(0).getId(), null, invoices.get(0).getBalance(), -1, PaymentStatus.UNKNOWN, null, null, new DateTime());
//STEPH talk to Pierre
/*
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java b/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java
index 8c5a1ef..8bbae11 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -38,4 +38,6 @@ public interface PaymentInfoEvent extends Entity, BusEvent {
public Integer getPaymentNumber();
public PaymentStatus getStatus();
+
+ public String getExtPaymentRefId();
}
diff --git a/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java b/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java
index 3e8b563..eeb356a 100644
--- a/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java
+++ b/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -38,4 +38,6 @@ public interface PaymentInfoPlugin {
public String getGatewayError();
public String getGatewayErrorCode();
+
+ public String getExternalReferenceId();
}
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 b09e347..7c344fe 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
@@ -315,12 +315,17 @@ public class DefaultInvoiceDao implements InvoiceDao {
throw new InvoiceApiException(ErrorCode.REFUND_AMOUNT_IS_POSITIVE);
}
- // No that we check signs, let's work with positive numbers, this makes things simpler
+ // Now that we checked signs, let's work with positive numbers, this makes things simpler
final BigDecimal requestedPositiveAmount = requestedAmount.negate();
if (requestedPositiveAmount.compareTo(maxRefundAmount) > 0) {
throw new InvoiceApiException(ErrorCode.REFUND_AMOUNT_TOO_HIGH, requestedPositiveAmount, maxRefundAmount);
}
+ // Before we go further, check if that refund already got inserted
+ final InvoicePayment existingRefund = transactional.getPaymentsForCookieId(paymentCookieId.toString());
+ if (existingRefund != null) {
+ return existingRefund;
+ }
final InvoicePayment refund = new DefaultInvoicePayment(UUID.randomUUID(), InvoicePaymentType.REFUND, paymentAttemptId,
payment.getInvoiceId(), context.getCreatedDate(), requestedPositiveAmount.negate(), payment.getCurrency(), paymentCookieId, payment.getId());
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java
index 6ca968d..6bf0d10 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.java
@@ -83,6 +83,10 @@ public interface InvoicePaymentSqlDao extends EntitySqlDao<InvoicePayment>, Tran
@SqlQuery
InvoicePayment getInvoicePayment(@Bind("paymentAttemptId") final String paymentAttemptId);
+ @SqlQuery
+ InvoicePayment getPaymentsForCookieId(@Bind("paymentCookieId") final String paymentCookieId);
+
+
@SqlUpdate
void notifyOfPaymentAttempt(@InvoicePaymentBinder final InvoicePayment invoicePayment,
@CallContextBinder final CallContext context);
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg
index a028cf6..02dffc5 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoicePaymentSqlDao.sql.stg
@@ -43,6 +43,12 @@ getById() ::= <<
WHERE id = :id;
>>
+getPaymentsForCookieId() ::= <<
+ SELECT <invoicePaymentFields()>
+ FROM invoice_payments
+ WHERE payment_cookie_id = :paymentCookieId;
+>>
+
getPaymentsForInvoice() ::= <<
SELECT <invoicePaymentFields()>
FROM invoice_payments
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
index bf8c4a4..ebeb7d0 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
@@ -584,7 +584,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
balance = invoiceDao.getAccountBalance(accountId);
assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
- invoiceDao.createRefund(paymentAttemptId, refund1, withAdjustment, null, context);
+ invoiceDao.createRefund(paymentAttemptId, refund1, withAdjustment, UUID.randomUUID(), context);
balance = invoiceDao.getAccountBalance(accountId);
if (withAdjustment) {
assertEquals(balance.compareTo(BigDecimal.ZERO), 0);
@@ -678,7 +678,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
assertEquals(cba.compareTo(new BigDecimal("10.00")), 0);
// PARTIAL REFUND on the payment
- invoiceDao.createRefund(paymentAttemptId, refundAmount, withAdjustment, null, context);
+ invoiceDao.createRefund(paymentAttemptId, refundAmount, withAdjustment, UUID.randomUUID(), context);
balance = invoiceDao.getAccountBalance(accountId);
assertEquals(balance.compareTo(expectedFinalBalance), 0);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/RefundJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/RefundJson.java
index 8c4b812..f65f6d7 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/RefundJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/RefundJson.java
@@ -25,26 +25,32 @@ import com.ning.billing.payment.api.Refund;
public class RefundJson {
+ private final String refundId;
private final String paymentId;
private final BigDecimal refundAmount;
private final Boolean isAdjusted;
public RefundJson(Refund input) {
- this(input.getPaymentId().toString(), input.getRefundAmount(), input.isAdjusted());
+ this(input.getId().toString(), input.getPaymentId().toString(), input.getRefundAmount(), input.isAdjusted());
}
@JsonCreator
- public RefundJson(@JsonProperty("paymentId") String paymentId,
+ public RefundJson(@JsonProperty("refund_id") final String refundId,
+ @JsonProperty("paymentId") String paymentId,
@JsonProperty("refundAmount") BigDecimal refundAmount,
- @JsonProperty("isAdjusted") final Boolean isAdjusted) {
- super();
+ @JsonProperty("adjusted") final Boolean isAdjusted) {
+ this.refundId = refundId;
this.paymentId = paymentId;
this.refundAmount = refundAmount;
this.isAdjusted = isAdjusted;
}
public RefundJson() {
- this(null, null, null);
+ this(null, null, null, null);
+ }
+
+ public String getRefundId() {
+ return refundId;
}
public String getPaymentId() {
@@ -58,4 +64,62 @@ public class RefundJson {
public boolean isAdjusted() {
return isAdjusted;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((isAdjusted == null) ? 0 : isAdjusted.hashCode());
+ result = prime * result
+ + ((paymentId == null) ? 0 : paymentId.hashCode());
+ result = prime * result
+ + ((refundAmount == null) ? 0 : refundAmount.hashCode());
+ result = prime * result
+ + ((refundId == null) ? 0 : refundId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (! this.equalsNoId(obj)) {
+ return false;
+ } else {
+ RefundJson other = (RefundJson) obj;
+ if (getRefundId() == null) {
+ return other.getRefundId() == null;
+ } else {
+ return getRefundId().equals(other.getRefundId());
+ }
+ }
+ }
+
+ public boolean equalsNoId(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RefundJson other = (RefundJson) obj;
+ if (isAdjusted == null) {
+ if (other.isAdjusted != null)
+ return false;
+ } else if (!isAdjusted.equals(other.isAdjusted))
+ return false;
+ if (paymentId == null) {
+ if (other.paymentId != null)
+ return false;
+ } else if (!paymentId.equals(other.paymentId))
+ return false;
+ if (refundAmount == null) {
+ if (other.refundAmount != null)
+ return false;
+ } else if (!refundAmount.equals(other.refundAmount)) {
+ return false;
+ }
+ return true;
+ }
+
+
}
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 264c620..faaccb5 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
@@ -26,6 +26,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.Status;
import java.util.ArrayList;
@@ -109,7 +110,8 @@ public class PaymentResource extends JaxRsResourceBase {
@PathParam("paymentId") final String paymentId,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
- @HeaderParam(HDR_COMMENT) final String comment) {
+ @HeaderParam(HDR_COMMENT) final String comment,
+ @javax.ws.rs.core.Context final UriInfo uriInfo) {
try {
final UUID paymentUuid = UUID.fromString(paymentId);
@@ -118,7 +120,7 @@ public class PaymentResource extends JaxRsResourceBase {
final Account account = accountApi.getAccountById(payment.getAccountId());
Refund result = paymentApi.createRefund(account, paymentUuid, json.getRefundAmount(), json.isAdjusted(), context.createContext(createdBy, reason, comment));
- return uriBuilder.buildResponse(RefundResource.class, "getRefund", result.getId());
+ return uriBuilder.buildResponse(RefundResource.class, "getRefund", result.getId(), uriInfo.getBaseUri().toString());
} catch (AccountApiException e) {
if (e.getCode() == ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID.getCode()) {
return Response.status(Status.NO_CONTENT).build();
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java
index 63e72c0..6a5a729 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java
@@ -33,6 +33,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
import com.ning.billing.jaxrs.json.RefundJson;
import com.ning.billing.jaxrs.util.Context;
import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
@@ -71,8 +72,11 @@ public class RefundResource extends JaxRsResourceBase {
Refund refund = paymentApi.getRefund(UUID.fromString(refundId));
return Response.status(Status.OK).entity(new RefundJson(refund)).build();
} catch (PaymentApiException e) {
- // STEPH NO_CONTENT if oes not exist
- return Response.status(Status.BAD_REQUEST).build();
+ if (e.getCode() == ErrorCode.PAYMENT_NO_SUCH_REFUND.getCode()) {
+ return Response.status(Status.NO_CONTENT).build();
+ } else {
+ return Response.status(Status.BAD_REQUEST).build();
+ }
}
}
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 a43b1b5..4968a24 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
@@ -81,8 +81,7 @@ public class DefaultPaymentApi implements PaymentApi {
@Override
public Refund getRefund(UUID refundId) throws PaymentApiException {
- // TODO Auto-generated method stub
- return null;
+ return refundProcessor.getRefund(refundId);
}
@Override
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java
index a34f71e..e284d6a 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java
@@ -36,6 +36,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
private final PaymentStatus status;
private final UUID userToken;
private final DateTime effectiveDate;
+ private final String extPaymentRefId;
@JsonCreator
public DefaultPaymentInfoEvent(@JsonProperty("id") final UUID id,
@@ -45,6 +46,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
@JsonProperty("amount") final BigDecimal amount,
@JsonProperty("paymentNumber") final Integer paymentNumber,
@JsonProperty("status") final PaymentStatus status,
+ @JsonProperty("extPaymentRefId") final String extPaymentRefId,
@JsonProperty("userToken") final UUID userToken,
@JsonProperty("effectiveDate") final DateTime effectiveDate) {
super(id);
@@ -54,6 +56,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
this.amount = amount;
this.paymentNumber = paymentNumber;
this.status = status;
+ this.extPaymentRefId = extPaymentRefId;
this.userToken = userToken;
this.effectiveDate = effectiveDate;
}
@@ -61,8 +64,8 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
public DefaultPaymentInfoEvent(final UUID accountId, final UUID invoiceId,
final UUID paymentId, final BigDecimal amount, final Integer paymentNumber,
- final PaymentStatus status, final UUID userToken, final DateTime effectiveDate) {
- this(UUID.randomUUID(), accountId, invoiceId, paymentId, amount, paymentNumber, status, userToken, effectiveDate);
+ final PaymentStatus status, final String extPaymentRefId, final UUID userToken, final DateTime effectiveDate) {
+ this(UUID.randomUUID(), accountId, invoiceId, paymentId, amount, paymentNumber, status, extPaymentRefId, userToken, effectiveDate);
}
public DefaultPaymentInfoEvent(final DefaultPaymentInfoEvent src) {
@@ -73,6 +76,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
src.amount,
src.paymentNumber,
src.status,
+ src.extPaymentRefId,
src.userToken,
src.effectiveDate);
}
@@ -132,6 +136,11 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
return status;
}
+ @Override
+ public String getExtPaymentRefId() {
+ return extPaymentRefId;
+ }
+
@Override
public int hashCode() {
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 03c38ef..f22bb8e 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
@@ -223,7 +223,7 @@ public class PaymentProcessor extends ProcessorBase {
@Override
public Void doOperation() throws PaymentApiException {
- // Fetch gain with account lock this time
+ // Fetch again with account lock this time
final PaymentModelDao payment = paymentDao.getPayment(paymentId);
boolean foundExpectedState = false;
for (final PaymentStatus cur : expectedPaymentStates) {
@@ -295,7 +295,7 @@ public class PaymentProcessor extends ProcessorBase {
case PROCESSED:
// Update Payment/PaymentAttempt status
paymentStatus = PaymentStatus.SUCCESS;
- paymentDao.updateStatusForPaymentWithAttempt(paymentInput.getId(), paymentStatus, null, attemptInput.getId(), context);
+ paymentDao.updateStatusForPaymentWithAttempt(paymentInput.getId(), paymentStatus, null, paymentPluginInfo.getExternalReferenceId(), attemptInput.getId(), context);
// Fetch latest objects
allAttempts = paymentDao.getAttemptsForPayment(paymentInput.getId());
@@ -311,7 +311,8 @@ public class PaymentProcessor extends ProcessorBase {
// Create Bus event
event = new DefaultPaymentInfoEvent(account.getId(),
- invoice.getId(), payment.getId(), payment.getAmount(), payment.getPaymentNumber(), paymentStatus, context.getUserToken(), payment.getEffectiveDate());
+ invoice.getId(), payment.getId(), payment.getAmount(), payment.getPaymentNumber(), paymentStatus,
+ paymentPluginInfo.getExternalReferenceId(), context.getUserToken(), payment.getEffectiveDate());
break;
case ERROR:
@@ -326,7 +327,7 @@ public class PaymentProcessor extends ProcessorBase {
paymentStatus = PaymentStatus.PAYMENT_FAILURE_ABORTED;
}
- paymentDao.updateStatusForPaymentWithAttempt(paymentInput.getId(), paymentStatus, paymentPluginInfo.getGatewayError(), attemptInput.getId(), context);
+ paymentDao.updateStatusForPaymentWithAttempt(paymentInput.getId(), paymentStatus, paymentPluginInfo.getGatewayError(), null, attemptInput.getId(), context);
log.info(String.format("Could not process payment for account %s, invoice %s, error = %s",
account.getId(), invoice.getId(), paymentPluginInfo.getGatewayError()));
@@ -347,7 +348,7 @@ public class PaymentProcessor extends ProcessorBase {
paymentStatus = isInstantPayment ? PaymentStatus.PAYMENT_FAILURE_ABORTED : scheduleRetryOnPluginFailure(paymentInput.getId());
// STEPH message might need truncation to fit??
- paymentDao.updateStatusForPaymentWithAttempt(paymentInput.getId(), paymentStatus, e.getMessage(), attemptInput.getId(), context);
+ paymentDao.updateStatusForPaymentWithAttempt(paymentInput.getId(), paymentStatus, e.getMessage(), null, attemptInput.getId(), context);
throw new PaymentApiException(ErrorCode.PAYMENT_CREATE_PAYMENT, account.getId(), e.getMessage());
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 54fbeb9..92c4544 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
@@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
@@ -33,6 +34,7 @@ import com.google.common.collect.Collections2;
import com.google.inject.name.Named;
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.AccountUserApi;
import com.ning.billing.invoice.api.InvoiceApiException;
import com.ning.billing.invoice.api.InvoicePaymentApi;
@@ -123,7 +125,7 @@ public class RefundProcessor extends ProcessorBase {
if (nbExistingRefunds > foundPluginCompletedRefunds) {
log.info("Found existing plugin refund for paymentId {}, skip plugin", paymentId);
} else {
- // If there is no such exitng refund we create it
+ // If there is no such existng refund we create it
plugin.processRefund(account, paymentId, refundAmount);
}
paymentDao.updateRefundStatus(refundInfo.getId(), RefundStatus.PLUGIN_COMPLETED, context);
@@ -153,6 +155,7 @@ public class RefundProcessor extends ProcessorBase {
if (filteredInput.size() == 0) {
throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_REFUND, refundId);
}
+
if (completePluginCompletedRefund(filteredInput)) {
result = paymentDao.getRefund(refundId);
}
@@ -200,23 +203,42 @@ public class RefundProcessor extends ProcessorBase {
private boolean completePluginCompletedRefund(final List<RefundModelDao> refunds) throws PaymentApiException {
- boolean fixedTheWorld = false;
+
+ final Collection<RefundModelDao> refundsToBeFixed = Collections2.filter(refunds, new Predicate<RefundModelDao>() {
+ @Override
+ public boolean apply(RefundModelDao in) {
+ return in.getRefundStatus() == RefundStatus.PLUGIN_COMPLETED;
+ }
+ });
+ if (refundsToBeFixed.size() == 0) {
+ return false;
+ }
+
try {
- final CallContext context = factory.createCallContext("RefundProcessor", CallOrigin.INTERNAL, UserType.SYSTEM);
- for (RefundModelDao cur : refunds) {
- if (cur.getRefundStatus() == RefundStatus.PLUGIN_COMPLETED) {
- final PaymentAttemptModelDao successfulAttempt = getPaymentAttempt(cur.getPaymentId());
- if (successfulAttempt != null) {
- invoicePaymentApi.createRefund(successfulAttempt.getId(), cur.getAmount(), cur.isAdjsuted(), cur.getId(), context);
- paymentDao.updateRefundStatus(cur.getId(), RefundStatus.COMPLETED, context);
- fixedTheWorld = true;
+ Account account = accountUserApi.getAccountById(refundsToBeFixed.iterator().next().getAccountId());
+ new WithAccountLock<Void>().processAccountWithLock(locker, account.getExternalKey(), new WithAccountLockCallback<Void>() {
+
+ @Override
+ public Void doOperation() throws PaymentApiException {
+ try {
+ final CallContext context = factory.createCallContext("RefundProcessor", CallOrigin.INTERNAL, UserType.SYSTEM);
+ for (RefundModelDao cur : refundsToBeFixed) {
+ final PaymentAttemptModelDao successfulAttempt = getPaymentAttempt(cur.getPaymentId());
+ if (successfulAttempt != null) {
+ invoicePaymentApi.createRefund(successfulAttempt.getId(), cur.getAmount(), cur.isAdjsuted(), cur.getId(), context);
+ paymentDao.updateRefundStatus(cur.getId(), RefundStatus.COMPLETED, context);
+ }
+ }
+ } catch (InvoiceApiException e) {
+ throw new PaymentApiException(e);
}
+ return null;
}
- }
- } catch (InvoiceApiException e) {
+ });
+ return true;
+ } catch (AccountApiException e) {
throw new PaymentApiException(e);
}
- return fixedTheWorld;
}
private PaymentAttemptModelDao getPaymentAttempt(final UUID paymentId) {
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java b/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java
index 3c39f60..4ecbe1f 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/AuditedPaymentDao.java
@@ -143,31 +143,16 @@ public class AuditedPaymentDao implements PaymentDao {
});
}
-
- @Override
- public void updateStatusForPayment(final UUID paymentId,
- final PaymentStatus paymentStatus, final CallContext context) {
- paymentSqlDao.inTransaction(new Transaction<Void, PaymentSqlDao>() {
-
- @Override
- public Void inTransaction(final PaymentSqlDao transactional,
- final TransactionStatus status) throws Exception {
- updatePaymentStatusFromTransaction(paymentId, paymentStatus, context, transactional);
- return null;
- }
- });
- }
-
@Override
public void updateStatusForPaymentWithAttempt(final UUID paymentId,
- final PaymentStatus paymentStatus, final String paymentError, final UUID attemptId,
+ final PaymentStatus paymentStatus, final String paymentError, final String extPaymentRefId, final UUID attemptId,
final CallContext context) {
paymentSqlDao.inTransaction(new Transaction<Void, PaymentSqlDao>() {
@Override
public Void inTransaction(final PaymentSqlDao transactional,
final TransactionStatus status) throws Exception {
- updatePaymentStatusFromTransaction(paymentId, paymentStatus, context, transactional);
+ updatePaymentStatusFromTransaction(paymentId, paymentStatus, extPaymentRefId, context, transactional);
final PaymentAttemptSqlDao transPaymentAttemptSqlDao = transactional.become(PaymentAttemptSqlDao.class);
updatePaymentAttemptStatusFromTransaction(attemptId, paymentStatus, paymentError, context, transPaymentAttemptSqlDao);
return null;
@@ -186,8 +171,8 @@ public class AuditedPaymentDao implements PaymentDao {
transactional.insertAuditFromTransaction(audit, context);
}
- private void updatePaymentStatusFromTransaction(final UUID paymentId, final PaymentStatus paymentStatus, final CallContext context, final PaymentSqlDao transactional) {
- transactional.updatePaymentStatus(paymentId.toString(), paymentStatus.toString(), context);
+ private void updatePaymentStatusFromTransaction(final UUID paymentId, final PaymentStatus paymentStatus, final String extPaymentRefId, final CallContext context, final PaymentSqlDao transactional) {
+ transactional.updatePaymentStatusAndExtRef(paymentId.toString(), paymentStatus.toString(), extPaymentRefId, context);
final PaymentModelDao savedPayment = transactional.getPayment(paymentId.toString());
final Long recordId = transactional.getRecordId(savedPayment.getId().toString());
final EntityHistory<PaymentModelDao> history = new EntityHistory<PaymentModelDao>(savedPayment.getId(), recordId, savedPayment, ChangeType.UPDATE);
@@ -235,8 +220,16 @@ public class AuditedPaymentDao implements PaymentDao {
@Override
public RefundModelDao inTransaction(RefundSqlDao transactional,
TransactionStatus status) throws Exception {
+
transactional.insertRefund(refundInfo, context);
- return refundInfo;
+ final RefundModelDao savedRefund = transactional.getRefund(refundInfo.getId().toString());
+ final Long recordId = transactional.getRecordId(savedRefund.getId().toString());
+ final EntityHistory<RefundModelDao> history = new EntityHistory<RefundModelDao>(savedRefund.getId(), recordId, savedRefund, ChangeType.INSERT);
+ transactional.insertHistoryFromTransaction(history, context);
+ final Long historyRecordId = transactional.getHistoryRecordId(recordId);
+ final EntityAudit audit = new EntityAudit(TableName.REFUNDS, historyRecordId, ChangeType.INSERT);
+ transactional.insertAuditFromTransaction(audit, context);
+ return savedRefund;
}
});
}
@@ -244,13 +237,21 @@ public class AuditedPaymentDao implements PaymentDao {
@Override
public void updateRefundStatus(final UUID refundId,
- final RefundStatus status, final CallContext context) {
+ final RefundStatus refundStatus, final CallContext context) {
refundSqlDao.inTransaction(new Transaction<Void, RefundSqlDao>() {
@Override
public Void inTransaction(RefundSqlDao transactional,
TransactionStatus status) throws Exception {
- transactional.updateStatus(refundId.toString(), status.toString());
+ transactional.updateStatus(refundId.toString(), refundStatus.toString());
+
+ final RefundModelDao savedRefund = transactional.getRefund(refundId.toString());
+ final Long recordId = transactional.getRecordId(savedRefund.getId().toString());
+ final EntityHistory<RefundModelDao> history = new EntityHistory<RefundModelDao>(savedRefund.getId(), recordId, savedRefund, ChangeType.UPDATE);
+ transactional.insertHistoryFromTransaction(history, context);
+ final Long historyRecordId = transactional.getHistoryRecordId(recordId);
+ final EntityAudit audit = new EntityAudit(TableName.REFUNDS, historyRecordId, ChangeType.UPDATE);
+ transactional.insertAuditFromTransaction(audit, context);
return null;
}
});
@@ -263,7 +264,7 @@ public class AuditedPaymentDao implements PaymentDao {
@Override
public RefundModelDao inTransaction(RefundSqlDao transactional,
TransactionStatus status) throws Exception {
- return transactional.getById(refundId.toString());
+ return transactional.getRefund(refundId.toString());
}
});
}
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java
index 65254fb..711ae93 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java
@@ -18,14 +18,9 @@ package com.ning.billing.payment.dao;
import java.util.List;
import java.util.UUID;
-import org.skife.jdbi.v2.sqlobject.Bind;
-import org.skife.jdbi.v2.sqlobject.SqlQuery;
-
import com.ning.billing.payment.api.PaymentStatus;
import com.ning.billing.payment.dao.RefundModelDao.RefundStatus;
-import com.ning.billing.payment.dao.RefundSqlDao.RefundModelDaoBinder;
import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallContextBinder;
public interface PaymentDao {
@@ -34,10 +29,7 @@ public interface PaymentDao {
public PaymentAttemptModelDao insertNewAttemptForPayment(final UUID paymentId, final PaymentAttemptModelDao attempt, final boolean scheduleTimeoutRetry, final CallContext context);
-
- public void updateStatusForPayment(final UUID paymentId, final PaymentStatus paymentStatus, final CallContext context);
-
- public void updateStatusForPaymentWithAttempt(final UUID paymentId, final PaymentStatus paymentStatus, final String paymentError, final UUID attemptId, final CallContext context);
+ public void updateStatusForPaymentWithAttempt(final UUID paymentId, final PaymentStatus paymentStatus, final String paymentError, final String extPaymentRefId, final UUID attemptId, final CallContext context);
public PaymentAttemptModelDao getPaymentAttempt(final UUID attemptId);
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java
index a68de8c..d47cf05 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -49,6 +49,7 @@ public @interface PaymentHistoryBinder {
q.bind("amount", payment.getAmount());
q.bind("currency", payment.getCurrency().toString());
q.bind("paymentStatus", payment.getPaymentStatus().toString());
+ q.bind("externalPaymentRefId", payment.getExtPaymentRefId());
q.bind("effectiveDate", getDate(payment.getEffectiveDate()));
}
};
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentModelDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentModelDao.java
index ab1fecc..bf19311 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentModelDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentModelDao.java
@@ -36,11 +36,12 @@ public class PaymentModelDao extends EntityBase {
private final DateTime effectiveDate;
private final Integer paymentNumber;
private final PaymentStatus paymentStatus;
+ private final String extPaymentRefId;
public PaymentModelDao(final UUID id, final UUID accountId, final UUID invoiceId, final UUID paymentMethodId,
final Integer paymentNumber, final BigDecimal amount, final Currency currency,
- final PaymentStatus paymentStatus, final DateTime effectiveDate) {
+ final PaymentStatus paymentStatus, final DateTime effectiveDate, final String extPaymentRefId) {
super(id);
this.accountId = accountId;
this.invoiceId = invoiceId;
@@ -50,16 +51,16 @@ public class PaymentModelDao extends EntityBase {
this.currency = currency;
this.paymentStatus = paymentStatus;
this.effectiveDate = effectiveDate;
+ this.extPaymentRefId = extPaymentRefId;
}
public PaymentModelDao(final UUID accountId, final UUID invoiceId,
final BigDecimal amount, final Currency currency, final DateTime effectiveDate) {
- this(UUID.randomUUID(), accountId, invoiceId, null, INVALID_PAYMENT_NUMBER, amount, currency, PaymentStatus.UNKNOWN, effectiveDate);
+ this(UUID.randomUUID(), accountId, invoiceId, null, INVALID_PAYMENT_NUMBER, amount, currency, PaymentStatus.UNKNOWN, effectiveDate, null);
}
public PaymentModelDao(final PaymentModelDao src, final PaymentStatus newPaymentStatus) {
- this(src.getId(), src.getAccountId(), src.getInvoiceId(), null, src.getPaymentNumber(), src.getAmount(), src.getCurrency(), newPaymentStatus, src.getEffectiveDate())
- ;
+ this(src.getId(), src.getAccountId(), src.getInvoiceId(), null, src.getPaymentNumber(), src.getAmount(), src.getCurrency(), newPaymentStatus, src.getEffectiveDate(), null);
}
public UUID getAccountId() {
@@ -93,4 +94,8 @@ public class PaymentModelDao extends EntityBase {
public DateTime getEffectiveDate() {
return effectiveDate;
}
+
+ public String getExtPaymentRefId() {
+ return extPaymentRefId;
+ }
}
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
index f637976..9d88b8f 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
@@ -53,8 +53,8 @@ public interface PaymentSqlDao extends Transactional<PaymentSqlDao>, UpdatableEn
@CallContextBinder final CallContext context);
@SqlUpdate
- void updatePaymentStatus(@Bind("id") final String paymentId, @Bind("paymentStatus") final String paymentStatus,
- @CallContextBinder final CallContext context);
+ void updatePaymentStatusAndExtRef(@Bind("id") final String paymentId, @Bind("paymentStatus") final String paymentStatus,
+ @Bind("externalPaymentRefId") final String externalPaymentRefId, @CallContextBinder final CallContext context);
@SqlUpdate
void updatePaymentAmount(@Bind("id") final String paymentId, @Bind("amount") final BigDecimal amount,
@@ -87,6 +87,7 @@ public interface PaymentSqlDao extends Transactional<PaymentSqlDao>, UpdatableEn
stmt.bind("currency", payment.getCurrency().toString());
stmt.bind("effectiveDate", getDate(payment.getEffectiveDate()));
stmt.bind("paymentStatus", payment.getPaymentStatus().toString());
+ stmt.bind("externalPaymentRefId", payment.getExtPaymentRefId());
}
}
@@ -104,8 +105,9 @@ public interface PaymentSqlDao extends Transactional<PaymentSqlDao>, UpdatableEn
final DateTime effectiveDate = getDate(rs, "effective_date");
final Currency currency = Currency.valueOf(rs.getString("currency"));
final PaymentStatus paymentStatus = PaymentStatus.valueOf(rs.getString("payment_status"));
+ final String extPaymentRefId = rs.getString("external_payment_ref_id");
- return new PaymentModelDao(id, accountId, invoiceId, paymentMethodId, paymentNumber, amount, currency, paymentStatus, effectiveDate);
+ return new PaymentModelDao(id, accountId, invoiceId, paymentMethodId, paymentNumber, amount, currency, paymentStatus, effectiveDate, extPaymentRefId);
}
}
}
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/RefundHistoryBinder.java b/payment/src/main/java/com/ning/billing/payment/dao/RefundHistoryBinder.java
new file mode 100644
index 0000000..3110b2f
--- /dev/null
+++ b/payment/src/main/java/com/ning/billing/payment/dao/RefundHistoryBinder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.payment.dao;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+import com.ning.billing.util.dao.BinderBase;
+import com.ning.billing.util.dao.EntityHistory;
+
+
+@BindingAnnotation(RefundHistoryBinder.RefundHistoryBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface RefundHistoryBinder {
+
+
+ public static class RefundHistoryBinderFactory extends BinderBase implements BinderFactory {
+ @Override
+ public Binder<RefundHistoryBinder, EntityHistory<RefundModelDao>> build(final Annotation annotation) {
+ return new Binder<RefundHistoryBinder, EntityHistory<RefundModelDao>>() {
+ @Override
+ public void bind(final SQLStatement<?> q, final RefundHistoryBinder bind, final EntityHistory<RefundModelDao> history) {
+ q.bind("recordId", history.getValue());
+ q.bind("changeType", history.getChangeType().toString());
+ final RefundModelDao refund = history.getEntity();
+ q.bind("id", refund.getId().toString());
+ q.bind("accountId", refund.getAccountId().toString());
+ q.bind("paymentId", refund.getPaymentId().toString());
+ q.bind("amount", refund.getAmount());
+ q.bind("currency", refund.getCurrency().toString());
+ q.bind("isAdjusted", refund.isAdjsuted());
+ q.bind("refundStatus", refund.getRefundStatus().toString());
+ }
+ };
+ }
+ }
+}
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/RefundSqlDao.java b/payment/src/main/java/com/ning/billing/payment/dao/RefundSqlDao.java
index c29c6ed..e6bea41 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/RefundSqlDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/RefundSqlDao.java
@@ -39,6 +39,7 @@ import com.ning.billing.payment.dao.RefundModelDao.RefundStatus;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallContextBinder;
import com.ning.billing.util.dao.BinderBase;
+import com.ning.billing.util.dao.EntityHistory;
import com.ning.billing.util.dao.MapperBase;
import com.ning.billing.util.entity.dao.UpdatableEntitySqlDao;
@@ -53,7 +54,7 @@ public interface RefundSqlDao extends Transactional<RefundSqlDao>, UpdatableEnti
@CallContextBinder final CallContext context);
@SqlUpdate
- void updateStatus(@Bind("id") final String refundId, @Bind("refund_status") final String status);
+ void updateStatus(@Bind("id") final String refundId, @Bind("refundStatus") final String status);
@SqlQuery
RefundModelDao getRefund(@Bind("id") final String refundId);
@@ -64,6 +65,11 @@ public interface RefundSqlDao extends Transactional<RefundSqlDao>, UpdatableEnti
@SqlQuery
List<RefundModelDao> getRefundsForAccount(@Bind("accountId") final String accountId);
+ @Override
+ @SqlUpdate
+ public void insertHistoryFromTransaction(@RefundHistoryBinder final EntityHistory<RefundModelDao> payment,
+ @CallContextBinder final CallContext context);
+
public static final class RefundModelDaoBinder extends BinderBase implements Binder<Bind, RefundModelDao> {
@Override
@@ -73,8 +79,8 @@ public interface RefundSqlDao extends Transactional<RefundSqlDao>, UpdatableEnti
stmt.bind("paymentId", refund.getPaymentId().toString());
stmt.bind("amount", refund.getAmount());
stmt.bind("currency", refund.getCurrency().toString());
- stmt.bind("is_adjusted", refund.isAdjsuted());
- stmt.bind("refund_status", refund.getRefundStatus().toString());
+ stmt.bind("isAdjusted", refund.isAdjsuted());
+ stmt.bind("refundStatus", refund.getRefundStatus().toString());
}
}
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
index 325d03d..e4c20f3 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -70,4 +70,10 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentInfoPlugin {
public String getGatewayErrorCode() {
return null;
}
+
+
+ @Override
+ public String getExternalReferenceId() {
+ return null;
+ }
}
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
index cf23c59..c43b64b 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
@@ -199,7 +199,6 @@ public class DefaultNoOpPaymentProviderPlugin implements NoOpPaymentPluginApi {
@Override
public int getNbRefundForPaymentAmount(Account account, UUID paymentId,
BigDecimal refundAmount) throws PaymentPluginApiException {
- // TODO Auto-generated method stub
return 0;
}
diff --git a/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg b/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg
index 2dc34b6..742d9f7 100644
--- a/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg
+++ b/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg
@@ -9,6 +9,7 @@ paymentFields(prefix) ::= <<
<prefix>effective_date,
<prefix>currency,
<prefix>payment_status,
+ <prefix>external_payment_ref_id,
<prefix>created_by,
<prefix>created_date,
<prefix>updated_by,
@@ -17,7 +18,7 @@ paymentFields(prefix) ::= <<
insertPayment() ::= <<
INSERT INTO payments (<paymentFields()>)
- VALUES (:id, :accountId, :invoiceId, :paymentMethodId, :amount, :effectiveDate, :currency, :paymentStatus, :userName, :createdDate, :userName, :createdDate);
+ VALUES (:id, :accountId, :invoiceId, :paymentMethodId, :amount, :effectiveDate, :currency, :paymentStatus, :externalPaymentRefId, :userName, :createdDate, :userName, :createdDate);
>>
getPayment() ::= <<
@@ -42,9 +43,9 @@ getPaymentsForAccount() ::= <<
>>
-updatePaymentStatus() ::= <<
+updatePaymentStatusAndExtRef() ::= <<
UPDATE payments
- SET payment_status = :paymentStatus
+ SET payment_status = :paymentStatus, external_payment_ref_id = :externalPaymentRefId
WHERE id = :id;
>>
@@ -71,6 +72,7 @@ historyFields(prefix) ::= <<
<prefix>effective_date,
<prefix>currency,
<prefix>payment_status,
+ <prefix>external_payment_ref_id,
<prefix>created_by,
<prefix>created_date,
<prefix>updated_by,
@@ -79,7 +81,7 @@ historyFields(prefix) ::= <<
insertHistoryFromTransaction() ::= <<
INSERT INTO payment_history (<historyFields()>)
- VALUES (:recordId, :id, :accountId, :invoiceId, :paymentMethodId, :amount, :effectiveDate, :currency, :paymentStatus, :userName, :createdDate, :userName, :updatedDate);
+ VALUES (:recordId, :id, :accountId, :invoiceId, :paymentMethodId, :amount, :effectiveDate, :currency, :paymentStatus, :externalPaymentRefId, :userName, :createdDate, :userName, :updatedDate);
>>
diff --git a/payment/src/main/resources/com/ning/billing/payment/dao/RefundSqlDao.sql.stg b/payment/src/main/resources/com/ning/billing/payment/dao/RefundSqlDao.sql.stg
new file mode 100644
index 0000000..d1e8719
--- /dev/null
+++ b/payment/src/main/resources/com/ning/billing/payment/dao/RefundSqlDao.sql.stg
@@ -0,0 +1,92 @@
+group RefundSqlDao;
+
+refundFields(prefix) ::= <<
+<prefix>id,
+<prefix>account_id,
+<prefix>payment_id,
+<prefix>amount,
+<prefix>currency,
+<prefix>is_adjusted,
+<prefix>refund_status,
+<prefix>created_by,
+<prefix>created_date,
+<prefix>updated_by,
+<prefix>updated_date
+>>
+
+insertRefund() ::= <<
+ INSERT INTO refunds (<refundFields()>)
+ VALUES (:id, :accountId, :paymentId, :amount, :currency, :isAdjusted, :refundStatus, :userName, :createdDate, :userName, :createdDate);
+>>
+
+updateStatus() ::= <<
+ UPDATE refunds
+ SET refund_status = :refundStatus
+ WHERE id = :id;
+>>
+
+getRefund() ::= <<
+ SELECT <refundFields()>
+ FROM refunds
+ WHERE id = :id;
+>>
+
+getRefundsForPayment() ::= <<
+ SELECT <refundFields()>
+ FROM refunds
+ WHERE payment_id = :paymentId;
+>>
+
+getRefundsForAccount() ::= <<
+ SELECT <refundFields()>
+ FROM refunds
+ WHERE account_id = :accountId;
+>>
+
+getRecordId() ::= <<
+ SELECT record_id
+ FROM refunds
+ WHERE id = :id;
+>>
+
+historyFields(prefix) ::= <<
+ <prefix>record_id,
+ <prefix>id,
+ <prefix>account_id,
+ <prefix>payment_id,
+ <prefix>amount,
+ <prefix>currency,
+ <prefix>is_adjusted,
+ <prefix>refund_status,
+ <prefix>created_by,
+ <prefix>created_date,
+ <prefix>updated_by,
+ <prefix>updated_date
+>>
+
+insertHistoryFromTransaction() ::= <<
+ INSERT INTO refund_history (<historyFields()>)
+ VALUES (:recordId, :id, :accountId, :paymentId, :amount, :currency, :isAdjusted, :refundStatus, :userName, :createdDate, :userName, :createdDate);
+>>
+
+getHistoryRecordId() ::= <<
+ SELECT MAX(history_record_id)
+ FROM payment_method_history
+ WHERE record_id = :recordId;
+>>
+
+auditFields(prefix) ::= <<
+ <prefix>table_name,
+ <prefix>record_id,
+ <prefix>change_type,
+ <prefix>change_date,
+ <prefix>changed_by,
+ <prefix>reason_code,
+ <prefix>comments,
+ <prefix>user_token
+>>
+
+insertAuditFromTransaction() ::= <<
+ INSERT INTO audit_log(<auditFields()>)
+ VALUES(:tableName, :recordId, :changeType, :createdDate, :userName, :reasonCode, :comment, :userToken);
+>>
diff --git a/payment/src/main/resources/com/ning/billing/payment/ddl.sql b/payment/src/main/resources/com/ning/billing/payment/ddl.sql
index 69db6a2..a652b58 100644
--- a/payment/src/main/resources/com/ning/billing/payment/ddl.sql
+++ b/payment/src/main/resources/com/ning/billing/payment/ddl.sql
@@ -1,23 +1,4 @@
-DROP TABLE IF EXISTS refunds;
-CREATE TABLE refunds (
- record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
- id char(36) NOT NULL,
- account_id char(36) COLLATE utf8_bin NOT NULL,
- payment_id char(36) COLLATE utf8_bin NOT NULL,
- amount decimal(8,2),
- currency char(3),
- is_adjusted tinyint(1),
- refund_status varchar(50),
- created_by varchar(50) NOT NULL,
- created_date datetime NOT NULL,
- updated_by varchar(50) NOT NULL,
- updated_date datetime NOT NULL,
- PRIMARY KEY (record_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-CREATE UNIQUE INDEX refunds_id ON refunds(id);
-CREATE INDEX refunds_pay ON refunds(payment_id);
-CREATE INDEX refunds_accnt ON refunds(account_id);
DROP TABLE IF EXISTS payments;
CREATE TABLE payments (
@@ -29,7 +10,8 @@ CREATE TABLE payments (
amount decimal(8,2),
currency char(3),
effective_date datetime,
- payment_status varchar(50),
+ payment_status varchar(50),
+ external_payment_ref_id varchar(64),
created_by varchar(50) NOT NULL,
created_date datetime NOT NULL,
updated_by varchar(50) NOT NULL,
@@ -51,7 +33,8 @@ CREATE TABLE payment_history (
amount decimal(8,2),
currency char(3),
effective_date datetime,
- payment_status varchar(50),
+ payment_status varchar(50),
+ external_payment_ref_id varchar(64),
created_by varchar(50) NOT NULL,
created_date datetime NOT NULL,
updated_by varchar(50) NOT NULL,
@@ -132,6 +115,46 @@ CREATE TABLE payment_method_history (
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE UNIQUE INDEX payment_method_history_record_id ON payment_method_history(record_id);
+DROP TABLE IF EXISTS refunds;
+CREATE TABLE refunds (
+ record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
+ id char(36) NOT NULL,
+ account_id char(36) COLLATE utf8_bin NOT NULL,
+ payment_id char(36) COLLATE utf8_bin NOT NULL,
+ amount decimal(8,2),
+ currency char(3),
+ is_adjusted tinyint(1),
+ refund_status varchar(50),
+ created_by varchar(50) NOT NULL,
+ created_date datetime NOT NULL,
+ updated_by varchar(50) NOT NULL,
+ updated_date datetime NOT NULL,
+ PRIMARY KEY (record_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+CREATE UNIQUE INDEX refunds_id ON refunds(id);
+CREATE INDEX refunds_pay ON refunds(payment_id);
+CREATE INDEX refunds_accnt ON refunds(account_id);
+
+DROP TABLE IF EXISTS refund_history;
+CREATE TABLE refund_history (
+ history_record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
+ record_id int(11) unsigned NOT NULL,
+ id char(36) NOT NULL,
+ account_id char(36) COLLATE utf8_bin NOT NULL,
+ payment_id char(36) COLLATE utf8_bin NOT NULL,
+ amount decimal(8,2),
+ currency char(3),
+ is_adjusted tinyint(1),
+ refund_status varchar(50),
+ created_by varchar(50) NOT NULL,
+ created_date datetime NOT NULL,
+ updated_by varchar(50) NOT NULL,
+ updated_date datetime NOT NULL,
+ PRIMARY KEY (history_record_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+CREATE INDEX refund_history_record_id ON refund_history(record_id);
+
+
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java b/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java
index 371f7b1..d634792 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -39,7 +39,7 @@ public class TestEventJson {
@Test(groups = {"fast"})
public void testPaymentInfoEvent() throws Exception {
- final PaymentInfoEvent e = new DefaultPaymentInfoEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), new BigDecimal(12.9), new Integer(13), PaymentStatus.SUCCESS, UUID.randomUUID(), new DateTime());
+ final PaymentInfoEvent e = new DefaultPaymentInfoEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), new BigDecimal(12.9), new Integer(13), PaymentStatus.SUCCESS, "ext-ref-12345", UUID.randomUUID(), new DateTime());
final String json = mapper.writeValueAsString(e);
final Class<?> clazz = Class.forName(DefaultPaymentInfoEvent.class.getName());
diff --git a/payment/src/test/java/com/ning/billing/payment/dao/MockPaymentDao.java b/payment/src/test/java/com/ning/billing/payment/dao/MockPaymentDao.java
index ce1a17c..80b75f4 100644
--- a/payment/src/test/java/com/ning/billing/payment/dao/MockPaymentDao.java
+++ b/payment/src/test/java/com/ning/billing/payment/dao/MockPaymentDao.java
@@ -53,7 +53,7 @@ public class MockPaymentDao implements PaymentDao {
@Override
public void updateStatusForPaymentWithAttempt(final UUID paymentId,
- final PaymentStatus paymentStatus, final String paymentError, final UUID attemptId,
+ final PaymentStatus paymentStatus, final String paymentError, final String extpaymentRefId, final UUID attemptId,
final CallContext context) {
synchronized (this) {
final PaymentModelDao entry = payments.remove(paymentId);
@@ -68,18 +68,6 @@ public class MockPaymentDao implements PaymentDao {
}
@Override
- public void updateStatusForPayment(final UUID paymentId,
- final PaymentStatus paymentStatus, final CallContext context) {
- synchronized (this) {
- final PaymentModelDao entry = payments.remove(paymentId);
- if (entry != null) {
- payments.put(paymentId, new PaymentModelDao(entry, paymentStatus));
- }
- }
- }
-
-
- @Override
public PaymentAttemptModelDao getPaymentAttempt(final UUID attemptId) {
return attempts.get(attemptId);
}
diff --git a/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java b/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
index 10c2ac5..cbe952a 100644
--- a/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
+++ b/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -24,6 +24,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.skife.config.ConfigurationObjectFactory;
import org.skife.jdbi.v2.IDBI;
+import org.testng.Assert;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
@@ -34,6 +35,7 @@ import com.ning.billing.dbi.DBIProvider;
import com.ning.billing.dbi.DbiConfig;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.payment.api.PaymentStatus;
+import com.ning.billing.payment.dao.RefundModelDao.RefundStatus;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TestCallContext;
import com.ning.billing.util.clock.Clock;
@@ -42,6 +44,8 @@ import com.ning.billing.util.io.IOUtils;
import static junit.framework.Assert.assertNull;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
public class TestPaymentDao {
private static final CallContext context = new TestCallContext("PaymentTests");
@@ -89,6 +93,57 @@ public class TestPaymentDao {
}
+
+
+ @Test(groups = {"slow"})
+ public void testRefund() {
+
+ final UUID accountId = UUID.randomUUID();
+ final UUID paymentId1 = UUID.randomUUID();
+ final BigDecimal amount1 = new BigDecimal(13);
+ final Currency currency = Currency.USD;
+
+ RefundModelDao refund1 = new RefundModelDao(accountId, paymentId1, amount1, currency, true);
+
+ paymentDao.insertRefund(refund1, context);
+ RefundModelDao refundCheck = paymentDao.getRefund(refund1.getId());
+ assertNotNull(refundCheck);
+ assertEquals(refundCheck.getAccountId(), accountId);
+ assertEquals(refundCheck.getPaymentId(), paymentId1);
+ assertEquals(refundCheck.getAmount().compareTo(amount1), 0);
+ assertEquals(refundCheck.getCurrency(), currency);
+ assertEquals(refundCheck.isAdjsuted(), true);
+ assertEquals(refundCheck.getRefundStatus(), RefundStatus.CREATED);
+
+ final BigDecimal amount2 = new BigDecimal(7.00);
+ final UUID paymentId2 = UUID.randomUUID();
+
+ RefundModelDao refund2 = new RefundModelDao(accountId, paymentId2, amount2, currency, true);
+ paymentDao.insertRefund(refund2, context);
+ paymentDao.updateRefundStatus(refund2.getId(), RefundStatus.COMPLETED, context);
+
+ List<RefundModelDao> refundChecks = paymentDao.getRefundsForPayment(paymentId1);
+ assertEquals(refundChecks.size(), 1);
+
+ refundChecks = paymentDao.getRefundsForPayment(paymentId2);
+ assertEquals(refundChecks.size(), 1);
+
+ refundChecks = paymentDao.getRefundsForAccount(accountId);
+ assertEquals(refundChecks.size(), 2);
+ for (RefundModelDao cur : refundChecks) {
+ if (cur.getPaymentId().equals(paymentId1)) {
+ assertEquals(cur.getAmount().compareTo(amount1), 0);
+ assertEquals(cur.getRefundStatus(), RefundStatus.CREATED);
+ } else if (cur.getPaymentId().equals(paymentId2)) {
+ assertEquals(cur.getAmount().compareTo(amount2), 0);
+ assertEquals(cur.getRefundStatus(), RefundStatus.COMPLETED);
+ } else {
+ fail("Unexpected refund");
+ }
+ }
+ }
+
+
@Test(groups = {"slow"})
public void testUpdateStatus() {
@@ -105,7 +160,7 @@ public class TestPaymentDao {
final PaymentStatus paymentStatus = PaymentStatus.SUCCESS;
final String paymentError = "No error";
- paymentDao.updateStatusForPaymentWithAttempt(payment.getId(), paymentStatus, paymentError, attempt.getId(), context);
+ paymentDao.updateStatusForPaymentWithAttempt(payment.getId(), paymentStatus, paymentError, null, attempt.getId(), context);
final List<PaymentModelDao> payments = paymentDao.getPaymentsForInvoice(invoiceId);
assertEquals(payments.size(), 1);
diff --git a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
index 74ef8c3..96c8668 100644
--- a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
+++ b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
@@ -33,6 +33,7 @@ import com.ning.billing.jaxrs.resources.CatalogResource;
import com.ning.billing.jaxrs.resources.InvoiceResource;
import com.ning.billing.jaxrs.resources.PaymentMethodResource;
import com.ning.billing.jaxrs.resources.PaymentResource;
+import com.ning.billing.jaxrs.resources.RefundResource;
import com.ning.billing.jaxrs.resources.SubscriptionResource;
import com.ning.billing.jaxrs.resources.TagResource;
import com.ning.billing.jaxrs.util.KillbillEventHandler;
@@ -58,7 +59,7 @@ public class KillbillServerModule extends AbstractModule {
installKillbillModules();
}
-
+
protected void configureDao() {
// Load mysql driver if needed
try {
@@ -79,6 +80,7 @@ public class KillbillServerModule extends AbstractModule {
bind(CatalogResource.class).asEagerSingleton();
bind(PaymentMethodResource.class).asEagerSingleton();
bind(PaymentResource.class).asEagerSingleton();
+ bind(RefundResource.class).asEagerSingleton();
bind(KillbillEventHandler.class).asEagerSingleton();
}
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 60aa56a..54ecd11 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -44,6 +44,7 @@ import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
import com.ning.billing.jaxrs.json.CustomFieldJson;
import com.ning.billing.jaxrs.json.PaymentJsonSimple;
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.resources.JaxrsResource;
@@ -233,7 +234,7 @@ public class TestAccount extends TestJaxrsBase {
}
@Test(groups = "slow", enabled = true)
- public void testAccountPayments() throws Exception {
+ public void testAccountPaymentsWithRefund() throws Exception {
//clock.setTime(new DateTime(2012, 4, 25, 0, 3, 42, 0));
@@ -250,13 +251,21 @@ public class TestAccount extends TestJaxrsBase {
crappyWaitForLackOfProperSynchonization();
- final String uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + JaxrsResource.PAYMENTS;
+ String uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + JaxrsResource.PAYMENTS;
- final Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
- final String baseJson = response.getResponseBody();
- final List<PaymentJsonSimple> objFromJson = mapper.readValue(baseJson, new TypeReference<List<PaymentJsonSimple>>() {});
+ String baseJson = response.getResponseBody();
+ List<PaymentJsonSimple> objFromJson = mapper.readValue(baseJson, new TypeReference<List<PaymentJsonSimple>>() {});
Assert.assertEquals(objFromJson.size(), 1);
+
+ uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + JaxrsResource.REFUNDS;
+ response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ baseJson = response.getResponseBody();
+ List<RefundJson> objRefundFromJson = mapper.readValue(baseJson, new TypeReference<List<RefundJson>>() {});
+ Assert.assertEquals(objRefundFromJson.size(), 0);
+
}
@Test(groups = "slow", enabled = true)
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestPayment.java b/server/src/test/java/com/ning/billing/jaxrs/TestPayment.java
new file mode 100644
index 0000000..be1ec0d
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestPayment.java
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
+import com.ning.billing.jaxrs.json.PaymentJsonSimple;
+
+import com.ning.billing.jaxrs.json.RefundJson;
+import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
+import com.ning.billing.jaxrs.resources.JaxrsResource;
+import com.ning.http.client.Response;
+
+public class TestPayment extends TestJaxrsBase {
+
+ private static final Logger log = LoggerFactory.getLogger(TestPayment.class);
+
+ @Test(groups = "slow", enabled = true)
+ public void testPaymentWithRefund() throws Exception {
+ final AccountJson accountJson = createAccountWithDefaultPaymentMethod("eraahahildo", "sheqrgfhwe", "eraahahildo@yahoo.com");
+ assertNotNull(accountJson);
+
+ final BundleJsonNoSubscriptions bundleJson = createBundle(accountJson.getAccountId(), "317199");
+ assertNotNull(bundleJson);
+
+ final SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), "Shotgun", ProductCategory.BASE.toString(), BillingPeriod.MONTHLY.toString(), true);
+ assertNotNull(subscriptionJson);
+
+ clock.addMonths(1);
+ crappyWaitForLackOfProperSynchonization();
+
+
+ String uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + JaxrsResource.PAYMENTS;
+
+ Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ String baseJson = response.getResponseBody();
+ List<PaymentJsonSimple> objFromJson = mapper.readValue(baseJson, new TypeReference<List<PaymentJsonSimple>>() {});
+ Assert.assertEquals(objFromJson.size(), 1);
+
+ final String paymentId = objFromJson.get(0).getPaymentId();
+ final BigDecimal paymentAmount = objFromJson.get(0).getAmount();
+
+ uri = JaxrsResource.PAYMENTS_PATH + "/" + paymentId + "/" + JaxrsResource.REFUNDS;
+ response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ baseJson = response.getResponseBody();
+ List<RefundJson> objRefundFromJson = mapper.readValue(baseJson, new TypeReference<List<RefundJson>>() {});
+ Assert.assertEquals(objRefundFromJson.size(), 0);
+
+ // Issue the refund
+
+ RefundJson refundJson = new RefundJson(null, paymentId, paymentAmount.negate(), false);
+ baseJson = mapper.writeValueAsString(refundJson);
+ response = doPost(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+
+ final String locationCC = response.getHeader("Location");
+ Assert.assertNotNull(locationCC);
+
+ // Retrieves by Id based on Location returned
+ response = doGetWithUrl(locationCC, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ baseJson = response.getResponseBody();
+ final RefundJson refundJsonCheck = mapper.readValue(baseJson, RefundJson.class);
+ Assert.assertTrue(refundJsonCheck.equalsNoId(refundJson));
+
+ uri = JaxrsResource.PAYMENTS_PATH + "/" + paymentId + "/" + JaxrsResource.REFUNDS;
+ response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ baseJson = response.getResponseBody();
+ objRefundFromJson = mapper.readValue(baseJson, new TypeReference<List<RefundJson>>() {});
+ Assert.assertEquals(objRefundFromJson.size(), 1);
+
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/dao/TableName.java b/util/src/main/java/com/ning/billing/util/dao/TableName.java
index 4008f2e..a5038d5 100644
--- a/util/src/main/java/com/ning/billing/util/dao/TableName.java
+++ b/util/src/main/java/com/ning/billing/util/dao/TableName.java
@@ -31,6 +31,7 @@ public enum TableName {
PAYMENT_METHODS("payment_methods"),
SUBSCRIPTIONS("subscriptions"),
SUBSCRIPTION_EVENTS("subscription_events"),
+ REFUNDS("refunds"),
TAG_HISTORY("tag_history");
private final String tableName;