killbill-aplcache

Details

diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index dd03756..8ea1ee2 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -248,7 +248,8 @@ public enum ErrorCode {
     PAYMENT_NO_SUCH_REFUND(7023, "Refund %s does not exist"),
     PAYMENT_NO_SUCH_SUCCESS_PAYMENT(7024, "Payment %s did not succeed"),
     PAYMENT_REFUND_AMOUNT_TOO_LARGE(7025, "Refund amount if larger than payment"),
-    PAYMENT_BAD_ACCOUNT(7026, "Account %s has payments left in an unknwon state"),
+    PAYMENT_REFUND_AMOUNT_NEGATIVE_OR_NULL(7026, "Refund amount needs to be strictly positive"),
+    PAYMENT_BAD_ACCOUNT(7027, "Account %s has payments left in an unknwon state"),
 
     PAYMENT_PLUGIN_TIMEOUT(7100, "Plugin timeout for account %s and invoice %s"),
     PAYMENT_PLUGIN_ACCOUNT_INIT(7101, "Account initialization for account %s and plugin % s failed: %s"),
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 dfb40b4..513dae0 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
@@ -24,6 +24,7 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 
 import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
@@ -112,6 +113,9 @@ 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 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 86d7bef..2dec344 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
@@ -305,13 +305,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     throw new InvoiceApiException(ErrorCode.INVOICE_PAYMENT_BY_ATTEMPT_NOT_FOUND, paymentId);
                 }
                 final BigDecimal maxRefundAmount = payment.getAmount() == null ? BigDecimal.ZERO : payment.getAmount();
-                final BigDecimal requestedAmount = amount == null ? maxRefundAmount : amount;
-                if (requestedAmount.compareTo(BigDecimal.ZERO) >= 0) {
-                    throw new InvoiceApiException(ErrorCode.REFUND_AMOUNT_IS_POSITIVE);
-                }
-
-                // Now that we checked signs, let's work with positive numbers, this makes things simpler
-                final BigDecimal requestedPositiveAmount = requestedAmount.negate();
+                final BigDecimal requestedPositiveAmount = amount == null ? maxRefundAmount : amount;
                 if (requestedPositiveAmount.compareTo(maxRefundAmount) > 0) {
                     throw new InvoiceApiException(ErrorCode.REFUND_AMOUNT_TOO_HIGH, requestedPositiveAmount, maxRefundAmount);
                 }
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 fb7bf9c..6f3594c 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
@@ -561,7 +561,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final DateTime endDate = startDate.plusMonths(1);
 
         final BigDecimal rate1 = new BigDecimal("20.0");
-        final BigDecimal refund1 = new BigDecimal("-7.00");
+        final BigDecimal refund1 = new BigDecimal("7.00");
         final BigDecimal rate2 = new BigDecimal("10.0");
 
         // Recurring item
@@ -590,28 +590,28 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
     @Test(groups = "slow")
     public void testAccountBalanceWithSmallRefundAndCBANoAdj() throws InvoiceApiException {
-        BigDecimal refundAmount = new BigDecimal("-7.00");
+        BigDecimal refundAmount = new BigDecimal("7.00");
         BigDecimal expectedBalance = new BigDecimal("-3.00");
         testAccountBalanceWithRefundAndCBAInternal(false, refundAmount, expectedBalance);
     }
 
     @Test(groups = "slow")
     public void testAccountBalanceWithSmallRefundAndCBAWithAdj() throws InvoiceApiException {
-        BigDecimal refundAmount = new BigDecimal("-7.00");
+        BigDecimal refundAmount = new BigDecimal("7.00");
         BigDecimal expectedBalance = new BigDecimal("-3.00");
         testAccountBalanceWithRefundAndCBAInternal(true, refundAmount, expectedBalance);
     }
 
     @Test(groups = "slow")
     public void testAccountBalanceWithLargeRefundAndCBANoAdj() throws InvoiceApiException {
-        BigDecimal refundAmount = new BigDecimal("-20.00");
+        BigDecimal refundAmount = new BigDecimal("20.00");
         BigDecimal expectedBalance = new BigDecimal("10.00");
         testAccountBalanceWithRefundAndCBAInternal(false, refundAmount, expectedBalance);
     }
 
     @Test(groups = "slow")
     public void testAccountBalanceWithLargeRefundAndCBAWithAdj() throws InvoiceApiException {
-        BigDecimal refundAmount = new BigDecimal("-20.00");
+        BigDecimal refundAmount = new BigDecimal("20.00");
         BigDecimal expectedBalance = BigDecimal.ZERO;
         testAccountBalanceWithRefundAndCBAInternal(true, refundAmount, expectedBalance);
     }
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 4968a24..1bcedf9 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
@@ -88,6 +88,9 @@ public class DefaultPaymentApi implements PaymentApi {
     public Refund createRefund(Account account, UUID paymentId,
             BigDecimal refundAmount, boolean isAdjusted, CallContext context)
             throws PaymentApiException {
+        if (refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_REFUND_AMOUNT_NEGATIVE_OR_NULL);
+        }
         return refundProcessor.createRefund(account, paymentId, refundAmount, isAdjusted, context);
 
     }
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 9d31f67..33c1431 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
@@ -66,6 +66,15 @@ public abstract class ProcessorBase {
         this.executor = executor;
     }
 
+    protected PaymentPluginApi getPaymentProviderPlugin(final UUID paymentMethodId) throws PaymentApiException {
+        final PaymentMethodModelDao methodDao = paymentDao.getPaymentMethod(paymentMethodId);
+        if (methodDao == null) {
+            log.error("PaymentMethod dpes not exist", paymentMethodId);
+            throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, paymentMethodId);
+        }
+        return pluginRegistry.getPlugin(methodDao.getPluginName());
+    }
+
 
     protected PaymentPluginApi getPaymentProviderPlugin(final String accountKey)
             throws AccountApiException, PaymentApiException {
@@ -79,20 +88,11 @@ public abstract class ProcessorBase {
     }
 
     protected PaymentPluginApi getPaymentProviderPlugin(final Account account) throws PaymentApiException {
-        String paymentProviderName = null;
-        if (account != null) {
-            final UUID paymentMethodId = account.getPaymentMethodId();
-            if (paymentMethodId == null) {
-                throw new PaymentApiException(ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD, account.getId());
-            }
-            final PaymentMethodModelDao methodDao = paymentDao.getPaymentMethod(paymentMethodId);
-            if (methodDao == null) {
-                log.error("Account {} has a non existent default payment method {}!!!", account.getId(), paymentMethodId);
-                throw new PaymentApiException(ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD, account.getId());
-            }
-            paymentProviderName = methodDao.getPluginName();
+        final UUID paymentMethodId = account.getPaymentMethodId();
+        if (paymentMethodId == null) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD, account.getId());
         }
-        return pluginRegistry.getPlugin(paymentProviderName);
+        return getPaymentProviderPlugin(paymentMethodId);
     }
 
     protected void postPaymentEvent(final BusEvent ev, final UUID accountId) {
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 a7768c2..6640ddb 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
@@ -44,6 +44,7 @@ import com.ning.billing.payment.api.PaymentStatus;
 import com.ning.billing.payment.api.Refund;
 import com.ning.billing.payment.dao.PaymentAttemptModelDao;
 import com.ning.billing.payment.dao.PaymentDao;
+import com.ning.billing.payment.dao.PaymentModelDao;
 import com.ning.billing.payment.dao.RefundModelDao;
 import com.ning.billing.payment.dao.RefundModelDao.RefundStatus;
 import com.ning.billing.payment.plugin.api.PaymentPluginApi;
@@ -89,11 +90,11 @@ public class RefundProcessor extends ProcessorBase {
             public Refund doOperation() throws PaymentApiException {
                 try {
 
-                    final PaymentAttemptModelDao successfulAttempt = getPaymentAttempt(paymentId);
-                    if (successfulAttempt == null) {
+                    final PaymentModelDao payment = paymentDao.getPayment(paymentId);
+                    if (payment == null) {
                         throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_SUCCESS_PAYMENT, paymentId);
                     }
-                    if (successfulAttempt.getRequestedAmount().compareTo(refundAmount) < 0) {
+                    if (payment.getAmount().compareTo(refundAmount) < 0) {
                         throw new PaymentApiException(ErrorCode.PAYMENT_REFUND_AMOUNT_TOO_LARGE);
                     }
 
@@ -102,7 +103,9 @@ public class RefundProcessor extends ProcessorBase {
                     RefundModelDao refundInfo = null;
                     List<RefundModelDao> existingRefunds = paymentDao.getRefundsForPayment(paymentId);
                     for (RefundModelDao cur : existingRefunds) {
-                        if (cur.getAmount().compareTo(refundAmount) == 0) {
+
+                        final BigDecimal existingPositiveAmount = cur.getAmount().negate();
+                        if (existingPositiveAmount.compareTo(refundAmount) == 0) {
                             if (cur.getRefundStatus() == RefundStatus.CREATED) {
                                 if (refundInfo == null) {
                                     refundInfo = cur;
@@ -117,12 +120,14 @@ public class RefundProcessor extends ProcessorBase {
                         paymentDao.insertRefund(refundInfo, context);
                     }
 
-                    final PaymentPluginApi plugin = getPaymentProviderPlugin(account);
+                    final PaymentPluginApi plugin = getPaymentProviderPlugin(payment.getPaymentMethodId());
                     int nbExistingRefunds = plugin.getNbRefundForPaymentAmount(account, paymentId, refundAmount);
+                    log.info(String.format("STEPH debug : found %d pluginRefunds for paymentId %s and amount %s", nbExistingRefunds, paymentId, refundAmount));
+
                     if (nbExistingRefunds > foundPluginCompletedRefunds) {
                         log.info("Found existing plugin refund for paymentId {}, skip plugin", paymentId);
                     } else {
-                        // If there is no such existng refund we create it
+                        // If there is no such existing refund we create it
                         plugin.processRefund(account, paymentId, refundAmount);
                     }
                     paymentDao.updateRefundStatus(refundInfo.getId(), RefundStatus.PLUGIN_COMPLETED, context);
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestPayment.java b/server/src/test/java/com/ning/billing/jaxrs/TestPayment.java
index be1ec0d..090b700 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestPayment.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestPayment.java
@@ -79,7 +79,7 @@ public class TestPayment extends TestJaxrsBase {
 
         // Issue the refund
 
-        RefundJson refundJson = new RefundJson(null, paymentId, paymentAmount.negate(), false);
+        RefundJson refundJson = new RefundJson(null, paymentId, paymentAmount, false);
         baseJson = mapper.writeValueAsString(refundJson);
         response = doPost(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());