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) {