/*
* Copyright 2010-2013 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 java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.ning.billing.jaxrs.json.AccountJson;
import com.ning.billing.jaxrs.json.InvoiceItemJson;
import com.ning.billing.jaxrs.json.InvoiceJson;
import com.ning.billing.jaxrs.json.PaymentJson;
import com.ning.billing.jaxrs.json.PaymentMethodJson;
import com.ning.billing.jaxrs.json.RefundJson;
import com.ning.billing.payment.api.RefundStatus;
public class TestPayment extends TestJaxrsBase {
@Test(groups = "slow")
public void testRetrievePayment() throws Exception {
final PaymentJson paymentJson = setupScenarioWithPayment();
final PaymentJson retrievedPaymentJson = getPayment(paymentJson.getPaymentId());
Assert.assertEquals(retrievedPaymentJson, paymentJson);
}
@Test(groups = "slow")
public void testFullRefundWithNoAdjustment() throws Exception {
final PaymentJson paymentJson = setupScenarioWithPayment();
// Issue a refund for the full amount
final BigDecimal refundAmount = paymentJson.getAmount();
final BigDecimal expectedInvoiceBalance = refundAmount;
// Post and verify the refund
final RefundJson refundJsonCheck = createRefund(paymentJson.getPaymentId(), refundAmount);
verifyRefund(paymentJson, refundJsonCheck, refundAmount);
// Verify the invoice balance
verifyInvoice(paymentJson, expectedInvoiceBalance);
}
@Test(groups = "slow")
public void testPartialRefundWithNoAdjustment() throws Exception {
final PaymentJson paymentJson = setupScenarioWithPayment();
// Issue a refund for a fraction of the amount
final BigDecimal refundAmount = getFractionOfAmount(paymentJson.getAmount());
final BigDecimal expectedInvoiceBalance = refundAmount;
// Post and verify the refund
final RefundJson refundJsonCheck = createRefund(paymentJson.getPaymentId(), refundAmount);
verifyRefund(paymentJson, refundJsonCheck, refundAmount);
// Verify the invoice balance
verifyInvoice(paymentJson, expectedInvoiceBalance);
}
@Test(groups = "slow")
public void testFullRefundWithInvoiceAdjustment() throws Exception {
final PaymentJson paymentJson = setupScenarioWithPayment();
// Issue a refund for the full amount
final BigDecimal refundAmount = paymentJson.getAmount();
final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
// Post and verify the refund
final RefundJson refundJsonCheck = createRefundWithInvoiceAdjustment(paymentJson.getPaymentId(), refundAmount);
verifyRefund(paymentJson, refundJsonCheck, refundAmount);
// Verify the invoice balance
verifyInvoice(paymentJson, expectedInvoiceBalance);
}
@Test(groups = "slow")
public void testPartialRefundWithInvoiceAdjustment() throws Exception {
final PaymentJson paymentJson = setupScenarioWithPayment();
// Issue a refund for a fraction of the amount
final BigDecimal refundAmount = getFractionOfAmount(paymentJson.getAmount());
final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
// Post and verify the refund
final RefundJson refundJsonCheck = createRefundWithInvoiceAdjustment(paymentJson.getPaymentId(), refundAmount);
verifyRefund(paymentJson, refundJsonCheck, refundAmount);
// Verify the invoice balance
verifyInvoice(paymentJson, expectedInvoiceBalance);
}
@Test(groups = "slow")
public void testRefundWithFullInvoiceItemAdjustment() throws Exception {
final PaymentJson paymentJson = setupScenarioWithPayment();
// Get the individual items for the invoice
final InvoiceJson invoice = getInvoiceWithItems(paymentJson.getInvoiceId());
final InvoiceItemJson itemToAdjust = invoice.getItems().get(0);
// Issue a refund for the full amount
final BigDecimal refundAmount = itemToAdjust.getAmount();
final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
// Post and verify the refund
final RefundJson refundJsonCheck = createRefundWithInvoiceItemAdjustment(paymentJson.getPaymentId(),
itemToAdjust.getInvoiceItemId(),
null /* null means full adjustment for that item */);
verifyRefund(paymentJson, refundJsonCheck, refundAmount);
// Verify the invoice balance
verifyInvoice(paymentJson, expectedInvoiceBalance);
}
@Test(groups = "slow")
public void testPartialRefundWithInvoiceItemAdjustment() throws Exception {
final PaymentJson paymentJson = setupScenarioWithPayment();
// Get the individual items for the invoice
final InvoiceJson invoice = getInvoiceWithItems(paymentJson.getInvoiceId());
final InvoiceItemJson itemToAdjust = invoice.getItems().get(0);
// Issue a refund for a fraction of the amount
final BigDecimal refundAmount = getFractionOfAmount(itemToAdjust.getAmount());
final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
// Post and verify the refund
final RefundJson refundJsonCheck = createRefundWithInvoiceItemAdjustment(paymentJson.getPaymentId(),
itemToAdjust.getInvoiceItemId(),
refundAmount);
verifyRefund(paymentJson, refundJsonCheck, refundAmount);
// Verify the invoice balance
verifyInvoice(paymentJson, expectedInvoiceBalance);
}
private BigDecimal getFractionOfAmount(final BigDecimal amount) {
return amount.divide(BigDecimal.TEN).setScale(2, BigDecimal.ROUND_HALF_UP);
}
private PaymentJson setupScenarioWithPayment() throws Exception {
final AccountJson accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
final List<PaymentJson> firstPaymentForAccount = getPaymentsForAccount(accountJson.getAccountId());
Assert.assertEquals(firstPaymentForAccount.size(), 1);
final PaymentJson paymentJson = firstPaymentForAccount.get(0);
// Check the PaymentMethod from paymentMethodId returned in the Payment object
final String paymentMethodId = paymentJson.getPaymentMethodId();
final PaymentMethodJson paymentMethodJson = getPaymentMethodWithPluginInfo(paymentMethodId);
Assert.assertEquals(paymentMethodJson.getPaymentMethodId(), paymentMethodId);
Assert.assertEquals(paymentMethodJson.getAccountId(), accountJson.getAccountId());
// Verify the refunds
final List<RefundJson> objRefundFromJson = getRefundsForPayment(paymentJson.getPaymentId());
Assert.assertEquals(objRefundFromJson.size(), 0);
return paymentJson;
}
private void verifyRefund(final PaymentJson paymentJson, final RefundJson refundJsonCheck, final BigDecimal refundAmount) throws IOException {
Assert.assertEquals(refundJsonCheck.getPaymentId(), paymentJson.getPaymentId());
Assert.assertEquals(refundJsonCheck.getAmount().setScale(2, RoundingMode.HALF_UP), refundAmount.setScale(2, RoundingMode.HALF_UP));
Assert.assertEquals(refundJsonCheck.getCurrency(), DEFAULT_CURRENCY);
Assert.assertEquals(refundJsonCheck.getStatus(), RefundStatus.COMPLETED.toString());
Assert.assertEquals(refundJsonCheck.getEffectiveDate().getYear(), clock.getUTCNow().getYear());
Assert.assertEquals(refundJsonCheck.getEffectiveDate().getMonthOfYear(), clock.getUTCNow().getMonthOfYear());
Assert.assertEquals(refundJsonCheck.getEffectiveDate().getDayOfMonth(), clock.getUTCNow().getDayOfMonth());
Assert.assertEquals(refundJsonCheck.getRequestedDate().getYear(), clock.getUTCNow().getYear());
Assert.assertEquals(refundJsonCheck.getRequestedDate().getMonthOfYear(), clock.getUTCNow().getMonthOfYear());
Assert.assertEquals(refundJsonCheck.getRequestedDate().getDayOfMonth(), clock.getUTCNow().getDayOfMonth());
// Verify the refunds
final List<RefundJson> retrievedRefunds = getRefundsForPayment(paymentJson.getPaymentId());
Assert.assertEquals(retrievedRefunds.size(), 1);
// Verify the refund via the payment API
final PaymentJson retrievedPaymentJson = getPaymentWithRefundsAndChargebacks(paymentJson.getPaymentId());
Assert.assertEquals(retrievedPaymentJson.getPaymentId(), paymentJson.getPaymentId());
Assert.assertEquals(retrievedPaymentJson.getPaidAmount().setScale(2, RoundingMode.HALF_UP), paymentJson.getPaidAmount().add(refundAmount.negate()).setScale(2, RoundingMode.HALF_UP));
Assert.assertEquals(retrievedPaymentJson.getAmount().setScale(2, RoundingMode.HALF_UP), paymentJson.getAmount().setScale(2, RoundingMode.HALF_UP));
Assert.assertEquals(retrievedPaymentJson.getAccountId(), paymentJson.getAccountId());
Assert.assertEquals(retrievedPaymentJson.getInvoiceId(), paymentJson.getInvoiceId());
Assert.assertEquals(retrievedPaymentJson.getRequestedDate(), paymentJson.getRequestedDate());
Assert.assertEquals(retrievedPaymentJson.getEffectiveDate(), paymentJson.getEffectiveDate());
Assert.assertEquals(retrievedPaymentJson.getRetryCount(), paymentJson.getRetryCount());
Assert.assertEquals(retrievedPaymentJson.getCurrency(), paymentJson.getCurrency());
Assert.assertEquals(retrievedPaymentJson.getStatus(), paymentJson.getStatus());
Assert.assertEquals(retrievedPaymentJson.getGatewayErrorCode(), paymentJson.getGatewayErrorCode());
Assert.assertEquals(retrievedPaymentJson.getGatewayErrorMsg(), paymentJson.getGatewayErrorMsg());
Assert.assertEquals(retrievedPaymentJson.getPaymentMethodId(), paymentJson.getPaymentMethodId());
Assert.assertEquals(retrievedPaymentJson.getChargebacks().size(), 0);
Assert.assertEquals(retrievedPaymentJson.getRefunds().size(), 1);
Assert.assertEquals(retrievedPaymentJson.getRefunds().get(0), refundJsonCheck);
}
private void verifyInvoice(final PaymentJson paymentJson, final BigDecimal expectedInvoiceBalance) throws IOException {
final InvoiceJson invoiceJson = getInvoice(paymentJson.getInvoiceId());
Assert.assertEquals(invoiceJson.getBalance().setScale(2, BigDecimal.ROUND_HALF_UP),
expectedInvoiceBalance.setScale(2, BigDecimal.ROUND_HALF_UP));
}
}