killbill-uncached

Details

diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 0cda076..39dc17f 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -184,7 +184,7 @@ public enum ErrorCode {
     INVOICE_TARGET_DATE_TOO_FAR_IN_THE_FUTURE(4005, "The target date was too far in the future. Target Date: %s"),
     INVOICE_NOT_FOUND(4006, "No invoice could be found for id %s."),
     INVOICE_NOTHING_TO_DO(4007, "No invoice to generate for account %s and date %s"),
-    
+
     /*
      *
      * Range 4900: Invoice payment
@@ -193,21 +193,25 @@ public enum ErrorCode {
     INVOICE_PAYMENT_NOT_FOUND(4900, "No invoice payment could be found for id %s."),
     CHARGE_BACK_AMOUNT_TOO_HIGH(4901, "Tried to charge back %s of a %s payment."),
     CHARGE_BACK_AMOUNT_IS_NEGATIVE(4902, "Charge backs for negative amounts are not permitted"),
-    CHARGE_BACK_COULD_NOT_FIND_ACCOUNT_ID(4093, "Could not find chargeback for id %s."),
-    CHARGE_BACK_DOES_NOT_EXIST(4093, "Could not find chargeback for id %s."),
+    CHARGE_BACK_COULD_NOT_FIND_ACCOUNT_ID(4003, "Could not find chargeback for id %s."),
+    CHARGE_BACK_DOES_NOT_EXIST(4004, "Could not find chargeback for id %s."),
+    INVOICE_PAYMENT_BY_ATTEMPT_NOT_FOUND(4905, "No invoice payment could be found for paymentAttempt id %s."),
+    REFUND_AMOUNT_TOO_HIGH(4906, "Tried to refund %s of a %s payment."),
+    REFUND_AMOUNT_IS_NEGATIVE(4907, "Refund for negative amounts are not permitted"),
+
     /*
-     * 
+     *
      * Range 5000: Overdue system
-     * 
+     *
      */
     OVERDUE_CAT_ERROR_ENCOUNTERED(5001, "Catalog error encountered on Overdueable: id='%s', type='%s'"),
     OVERDUE_TYPE_NOT_SUPPORTED(5002, "Overdue of this type is not supported: id='%s', type='%s'"),
     OVERDUE_NO_REEVALUATION_INTERVAL(5003, "No valid reevaluation interval for state (name: %s)"),
     OVERDUE_NOT_CONFIGURED(5004, "No configuration was found for the overdue system"),
     /*
-     * 
+     *
      * Range 6000: Blocking system
-     * 
+     *
      */
     BLOCK_BLOCKED_ACTION(6000, "The action %s is block on this %s with id=%s"),
     BLOCK_TYPE_NOT_SUPPORTED(6001, "The Blockable type '%s' is not supported"),
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java b/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java
index 9c6eb69..9bf4cc5 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java
@@ -44,9 +44,11 @@ public interface InvoicePaymentApi {
 
     public void notifyOfPaymentAttempt(UUID invoiceId, UUID paymentAttemptId, DateTime paymentAttemptDate, CallContext context);
 
-    public InvoicePayment processChargeback(UUID invoicePaymentId, BigDecimal amount, CallContext context) throws InvoiceApiException;
+    public InvoicePayment createRefund(UUID paymentAttemptId, BigDecimal amount, boolean isInvoiceAdjusted, CallContext context) throws InvoiceApiException;
 
-    public InvoicePayment processChargeback(UUID invoicePaymentId, CallContext context) throws InvoiceApiException;
+    public InvoicePayment createChargeback(UUID invoicePaymentId, BigDecimal amount, CallContext context) throws InvoiceApiException;
+
+    public InvoicePayment createChargeback(UUID invoicePaymentId, CallContext context) throws InvoiceApiException;
 
     public BigDecimal getRemainingAmountPaid(UUID invoicePaymentId);
 
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 eeb8c85..125e195 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
@@ -81,13 +81,13 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
     }
 
     @Override
-    public InvoicePayment processChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
+    public InvoicePayment createChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
         return dao.postChargeback(invoicePaymentId, amount, context);
     }
 
     @Override
-    public InvoicePayment processChargeback(final UUID invoicePaymentId, final CallContext context) throws InvoiceApiException {
-        return processChargeback(invoicePaymentId, null, context);
+    public InvoicePayment createChargeback(final UUID invoicePaymentId, final CallContext context) throws InvoiceApiException {
+        return createChargeback(invoicePaymentId, null, context);
     }
 
     @Override
@@ -114,4 +114,11 @@ public class DefaultInvoicePaymentApi implements InvoicePaymentApi {
     public UUID getAccountIdFromInvoicePaymentId(final UUID invoicePaymentId) throws InvoiceApiException {
         return dao.getAccountIdFromInvoicePaymentId(invoicePaymentId);
     }
+
+    @Override
+    public InvoicePayment createRefund(UUID paymentAttemptId,
+            BigDecimal amount, boolean isInvoiceAdjusted, CallContext context)
+            throws InvoiceApiException {
+        return dao.createRefund(paymentAttemptId, amount, isInvoiceAdjusted, 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 246ba16..4b10980 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
@@ -48,6 +48,7 @@ import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.DefaultInvoicePayment;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.invoice.model.RefundAdjInvoiceItem;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
 import com.ning.billing.util.ChangeType;
 import com.ning.billing.util.api.TagApiException;
@@ -297,6 +298,53 @@ public class DefaultInvoiceDao implements InvoiceDao {
         tagUserApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.toTagDefinition(), context);
     }
 
+
+    @Override
+    public InvoicePayment createRefund(final UUID paymentAttemptId,
+            final BigDecimal amount, final boolean isInvoiceAdjusted, final CallContext context)
+            throws InvoiceApiException {
+
+        return invoicePaymentSqlDao.inTransaction(new Transaction<InvoicePayment, InvoicePaymentSqlDao>() {
+            @Override
+            public InvoicePayment inTransaction(final InvoicePaymentSqlDao transactional, final TransactionStatus status) throws Exception {
+                final InvoicePayment payment = transactional.getByPaymentAttemptId(paymentAttemptId.toString());
+                if (payment == null) {
+                    throw new InvoiceApiException(ErrorCode.INVOICE_PAYMENT_BY_ATTEMPT_NOT_FOUND, paymentAttemptId);
+                }
+                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_NEGATIVE);
+                }
+                if (requestedAmount.compareTo(maxRefundAmount) > 0) {
+                    throw new InvoiceApiException(ErrorCode.REFUND_AMOUNT_TOO_HIGH, requestedAmount, maxRefundAmount);
+                }
+
+                final InvoicePayment refund = new DefaultInvoicePayment(UUID.randomUUID(), InvoicePaymentType.REFUND, paymentAttemptId,
+                        payment.getInvoiceId(), context.getCreatedDate(), requestedAmount, payment.getCurrency(), payment.getId());
+                transactional.create(refund, context);
+
+                if (isInvoiceAdjusted) {
+                    InvoiceSqlDao transInvoiceDao = transactional.become(InvoiceSqlDao.class);
+                    Invoice invoice = transInvoiceDao.getById(payment.getInvoiceId().toString());
+                    if (invoice != null) {
+                        populateChildren(invoice, transInvoiceDao);
+                    }
+
+                    BigDecimal maxBalanceToAdjust = (invoice.getBalance().compareTo(BigDecimal.ZERO) <= 0) ? BigDecimal.ZERO : invoice.getBalance();
+                    BigDecimal requestedAmountToAdjust = requestedAmount.compareTo(maxBalanceToAdjust)  > 0 ? maxBalanceToAdjust : requestedAmount;
+                    if (requestedAmountToAdjust.compareTo(BigDecimal.ZERO) > 0) {
+                        final InvoiceItem adjItem = new RefundAdjInvoiceItem(invoice.getId(), invoice.getAccountId(), context.getCreatedDate(), requestedAmountToAdjust, invoice.getCurrency());
+                        InvoiceItemSqlDao transInvoiceItemDao = transInvoiceDao.become(InvoiceItemSqlDao.class);
+                        transInvoiceItemDao.create(adjItem, context);
+                    }
+                }
+                return refund;
+            }
+        });
+    }
+
+
     @Override
     public InvoicePayment postChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
 
@@ -306,7 +354,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
 
                 final BigDecimal maxChargedBackAmount = getRemainingAmountPaidFromTransaction(invoicePaymentId, transactional);
                 final BigDecimal requestedChargedBackAmout = (amount == null) ? maxChargedBackAmount : amount;
-                if (requestedChargedBackAmout.compareTo(BigDecimal.ZERO) < 0) {
+                if (requestedChargedBackAmout.compareTo(BigDecimal.ZERO) <= 0) {
                     throw new InvoiceApiException(ErrorCode.CHARGE_BACK_AMOUNT_IS_NEGATIVE);
                 }
                 if (requestedChargedBackAmout.compareTo(maxChargedBackAmount) > 0) {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index 8d3c1a8..209285b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -66,6 +66,9 @@ public interface InvoiceDao {
 
     InvoicePayment postChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException;
 
+    InvoicePayment createRefund(UUID paymentAttemptId,
+            BigDecimal amount, boolean isInvoiceAdjusted, CallContext context) throws InvoiceApiException;
+
     BigDecimal getRemainingAmountPaid(final UUID invoicePaymentId);
 
     UUID getAccountIdFromInvoicePaymentId(final UUID invoicePaymentId) throws InvoiceApiException;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
index 7087cd3..fa5d431 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
@@ -103,7 +103,7 @@ public class MockInvoicePaymentApi implements InvoicePaymentApi {
     }
 
     @Override
-    public InvoicePayment processChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
+    public InvoicePayment createChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException {
         InvoicePayment existingPayment = null;
         for (final InvoicePayment payment : invoicePayments) {
             if (payment.getId() == invoicePaymentId) {
@@ -121,7 +121,7 @@ public class MockInvoicePaymentApi implements InvoicePaymentApi {
     }
 
     @Override
-    public InvoicePayment processChargeback(final UUID invoicePaymentId, final CallContext context) throws InvoiceApiException {
+    public InvoicePayment createChargeback(final UUID invoicePaymentId, final CallContext context) throws InvoiceApiException {
         InvoicePayment existingPayment = null;
         for (final InvoicePayment payment : invoicePayments) {
             if (payment.getId() == invoicePaymentId) {
@@ -130,7 +130,7 @@ public class MockInvoicePaymentApi implements InvoicePaymentApi {
         }
 
         if (existingPayment != null) {
-            this.processChargeback(invoicePaymentId, existingPayment.getAmount(), context);
+            this.createChargeback(invoicePaymentId, existingPayment.getAmount(), context);
         }
 
         return existingPayment;
@@ -171,4 +171,12 @@ public class MockInvoicePaymentApi implements InvoicePaymentApi {
     public InvoicePayment getChargebackById(final UUID chargebackId) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public InvoicePayment createRefund(UUID paymentAttemptId,
+            BigDecimal amount, boolean isInvoiceAdjusted, CallContext context)
+            throws InvoiceApiException {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index 984d819..a2e8a34 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -258,4 +258,12 @@ public class MockInvoiceDao implements InvoiceDao {
         return null;
     }
 
+    @Override
+    public InvoicePayment createRefund(UUID paymentAttemptId,
+            BigDecimal amount, boolean isInvoiceAdjusted, CallContext context)
+            throws InvoiceApiException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/ChargeBackTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/ChargeBackTests.java
index 699b12b..322e92d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/ChargeBackTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/ChargeBackTests.java
@@ -90,7 +90,7 @@ public class ChargeBackTests {
         final InvoicePayment payment = createAndPersistPayment(invoice.getId(), THIRTY);
 
         // create a full charge back
-        invoicePaymentApi.processChargeback(payment.getId(), THIRTY, context);
+        invoicePaymentApi.createChargeback(payment.getId(), THIRTY, context);
 
         // check amount owed
         final BigDecimal amount = invoicePaymentApi.getRemainingAmountPaid(payment.getId());
@@ -103,7 +103,7 @@ public class ChargeBackTests {
         final InvoicePayment payment = createAndPersistPayment(invoice.getId(), THIRTY);
 
         // create a partial charge back
-        invoicePaymentApi.processChargeback(payment.getId(), FIFTEEN, context);
+        invoicePaymentApi.createChargeback(payment.getId(), FIFTEEN, context);
 
         // check amount owed
         final BigDecimal amount = invoicePaymentApi.getRemainingAmountPaid(payment.getId());
@@ -116,7 +116,7 @@ public class ChargeBackTests {
         final InvoicePayment payment = createAndPersistPayment(invoice.getId(), THIRTY);
 
         // create a large charge back
-        invoicePaymentApi.processChargeback(payment.getId(), ONE_MILLION, context);
+        invoicePaymentApi.createChargeback(payment.getId(), ONE_MILLION, context);
     }
 
     @Test(expectedExceptions = InvoiceApiException.class)
@@ -125,7 +125,7 @@ public class ChargeBackTests {
         final InvoicePayment payment = createAndPersistPayment(invoice.getId(), THIRTY);
 
         // create a partial charge back
-        invoicePaymentApi.processChargeback(payment.getId(), BigDecimal.ONE.negate(), context);
+        invoicePaymentApi.createChargeback(payment.getId(), BigDecimal.ONE.negate(), context);
     }
 
     @Test
@@ -154,7 +154,7 @@ public class ChargeBackTests {
         final InvoicePayment payment = createAndPersistPayment(invoice.getId(), THIRTY);
 
         // create a partial charge back
-        invoicePaymentApi.processChargeback(payment.getId(), FIFTEEN, context);
+        invoicePaymentApi.createChargeback(payment.getId(), FIFTEEN, context);
 
         final List<InvoicePayment> chargebacks = invoicePaymentApi.getChargebacksByAccountId(invoice.getAccountId());
         assertNotNull(chargebacks);
@@ -175,7 +175,7 @@ public class ChargeBackTests {
         final InvoicePayment payment = createAndPersistPayment(invoice.getId(), THIRTY);
 
         // create a partial charge back
-        invoicePaymentApi.processChargeback(payment.getId(), FIFTEEN, context);
+        invoicePaymentApi.createChargeback(payment.getId(), FIFTEEN, context);
 
         final List<InvoicePayment> chargebacks = invoicePaymentApi.getChargebacksByPaymentAttemptId(payment.getPaymentAttemptId());
         assertNotNull(chargebacks);
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 8823018..2ce2493 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
@@ -166,7 +166,7 @@ public class ChargebackResource implements JaxrsResource {
                 return Response.status(Response.Status.NO_CONTENT).entity(error).build();
             }
 
-            final InvoicePayment chargeBack = invoicePaymentApi.processChargeback(invoicePayment.getId(), json.getChargebackAmount(),
+            final InvoicePayment chargeBack = invoicePaymentApi.createChargeback(invoicePayment.getId(), json.getChargebackAmount(),
                                                                                   context.createContext(createdBy, reason, comment));
             return uriBuilder.buildResponse(ChargebackResource.class, "getChargeback", chargeBack.getId());
         } catch (InvoiceApiException e) {