use of org.killbill.billing.invoice.api.InvoicePayment in project killbill by killbill.
the class PaymentChecker method checkPayment.
private void checkPayment(final UUID accountId, final Payment payment, final CallContext context, final ExpectedPaymentCheck expected) {
Assert.assertEquals(payment.getAccountId(), accountId);
Assert.assertEquals(payment.getCurrency(), expected.getCurrency());
if (expected.getInvoiceId() != null) {
for (final InvoicePayment invoicePayment : invoicePaymentApi.getInvoicePayments(payment.getId(), context)) {
Assert.assertEquals(invoicePayment.getInvoiceId(), expected.getInvoiceId());
}
}
final PaymentTransaction transaction = getPurchaseTransaction(payment);
Assert.assertTrue(transaction.getAmount().compareTo(expected.getAmount()) == 0, "Actual amount " + transaction.getAmount() + ", expected amount " + expected.getAmount());
Assert.assertEquals(transaction.getTransactionStatus(), expected.getStatus());
Assert.assertEquals(transaction.getEffectiveDate().toLocalDate().compareTo(expected.getPaymentDate()), 0);
auditChecker.checkPaymentCreated(payment, context);
}
use of org.killbill.billing.invoice.api.InvoicePayment in project killbill by killbill.
the class TestInvoiceDao method testRefundWithRepairAndInvoiceItemAdjustmentInternal.
private void testRefundWithRepairAndInvoiceItemAdjustmentInternal(final BigDecimal refundAmount) throws InvoiceApiException, EntityPersistenceException {
final UUID accountId = account.getId();
final UUID bundleId = UUID.randomUUID();
final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
final Invoice invoice = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
invoiceUtil.createInvoice(invoice, context);
final LocalDate startDate = new LocalDate(2011, 3, 1);
final LocalDate endDate = startDate.plusMonths(1);
final BigDecimal amount = new BigDecimal("20.0");
// Recurring item
final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate, amount, amount, Currency.USD);
invoiceUtil.createInvoiceItem(item2, context);
BigDecimal balancePriorRefund = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balancePriorRefund.compareTo(new BigDecimal("20.00")), 0);
// Pay the whole thing
final UUID paymentId = UUID.randomUUID();
final BigDecimal payment1 = amount;
final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoice.getId(), new DateTime(), payment1, Currency.USD, Currency.USD, null, true);
invoiceUtil.createPayment(payment, context);
balancePriorRefund = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balancePriorRefund.compareTo(new BigDecimal("0.00")), 0);
// Repair the item (And add CBA item that should be generated)
final InvoiceItem repairItem = new RepairAdjInvoiceItem(invoice.getId(), accountId, startDate, endDate, amount.negate(), Currency.USD, item2.getId());
invoiceUtil.createInvoiceItem(repairItem, context);
final InvoiceItem cbaItem = new CreditBalanceAdjInvoiceItem(invoice.getId(), accountId, startDate, amount, Currency.USD);
invoiceUtil.createInvoiceItem(cbaItem, context);
final Map<UUID, BigDecimal> itemAdjustment = new HashMap<UUID, BigDecimal>();
// PAss a null value to let invoice calculate the amount to adjust
itemAdjustment.put(item2.getId(), null);
invoiceDao.createRefund(paymentId, refundAmount, true, itemAdjustment, UUID.randomUUID().toString(), context);
balancePriorRefund = invoiceDao.getAccountBalance(accountId, context);
final boolean partialRefund = refundAmount.compareTo(amount) < 0;
final BigDecimal cba = invoiceDao.getAccountCBA(accountId, context);
final InvoiceModelDao savedInvoice = invoiceDao.getById(invoice.getId(), context);
final BigDecimal expectedCba = balancePriorRefund.compareTo(BigDecimal.ZERO) < 0 ? balancePriorRefund.negate() : BigDecimal.ZERO;
assertEquals(cba.compareTo(expectedCba), 0);
// Let's re-calculate them from invoice
final BigDecimal balanceAfterRefund = invoiceDao.getAccountBalance(accountId, context);
final BigDecimal cbaAfterRefund = invoiceDao.getAccountCBA(accountId, context);
if (partialRefund) {
// IB = 20 (rec) - 20 (repair) + 20 (cba) - (20 -7) = 7; AB = IB - CBA = 7 - 20 = -13
assertEquals(balancePriorRefund.compareTo(new BigDecimal("-13.0")), 0);
assertEquals(savedInvoice.getInvoiceItems().size(), 4);
assertEquals(balanceAfterRefund.compareTo(new BigDecimal("-13.0")), 0);
assertEquals(cbaAfterRefund.compareTo(expectedCba), 0);
} else {
assertEquals(balancePriorRefund.compareTo(new BigDecimal("0.0")), 0);
assertEquals(savedInvoice.getInvoiceItems().size(), 4);
assertEquals(balanceAfterRefund.compareTo(BigDecimal.ZERO), 0);
assertEquals(cbaAfterRefund.compareTo(expectedCba), 0);
}
}
use of org.killbill.billing.invoice.api.InvoicePayment in project killbill by killbill.
the class TestInvoiceDao method testAccountBalanceWithRefundAndCBAInternal.
private void testAccountBalanceWithRefundAndCBAInternal(final boolean withAdjustment, final BigDecimal refundAmount, final BigDecimal expectedFinalBalance) throws InvoiceApiException, EntityPersistenceException {
final UUID accountId = account.getId();
final UUID bundleId = UUID.randomUUID();
final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
invoiceUtil.createInvoice(invoice1, context);
final LocalDate startDate = new LocalDate(2011, 3, 1);
final LocalDate endDate = startDate.plusMonths(1);
final BigDecimal amount1 = new BigDecimal("5.0");
final BigDecimal rate1 = new BigDecimal("20.0");
final BigDecimal rate2 = new BigDecimal("10.0");
// Fixed Item
final FixedPriceInvoiceItem item1 = new FixedPriceInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase A", startDate, amount1, Currency.USD);
invoiceUtil.createInvoiceItem(item1, context);
BigDecimal balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(new BigDecimal("5.00")), 0);
// Recurring item
final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate, rate1, rate1, Currency.USD);
invoiceUtil.createInvoiceItem(item2, context);
balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(new BigDecimal("25.00")), 0);
// Pay the whole thing
final UUID paymentId = UUID.randomUUID();
final BigDecimal payment1 = amount1.add(rate1);
final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoice1.getId(), new DateTime(), payment1, Currency.USD, Currency.USD, null, true);
invoiceUtil.createPayment(payment, context);
balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
// Repair previous item with rate 2
final RepairAdjInvoiceItem item2Repair = new RepairAdjInvoiceItem(invoice1.getId(), accountId, startDate, endDate, rate1.negate(), Currency.USD, item2.getId());
final RecurringInvoiceItem item2Replace = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate, rate2, rate2, Currency.USD);
invoiceUtil.createInvoiceItem(item2Repair, context);
invoiceUtil.createInvoiceItem(item2Replace, context);
balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(new BigDecimal("-10.00")), 0);
// CBA
final CreditBalanceAdjInvoiceItem cbaItem = new CreditBalanceAdjInvoiceItem(invoice1.getId(), accountId, new LocalDate(), balance.negate(), Currency.USD);
invoiceUtil.createInvoiceItem(cbaItem, context);
balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(new BigDecimal("-10.00")), 0);
BigDecimal cba = invoiceDao.getAccountCBA(accountId, context);
assertEquals(cba.compareTo(new BigDecimal("10.00")), 0);
// PARTIAL REFUND on the payment
final Map<UUID, BigDecimal> invoiceItemIdsWithAmounts = new HashMap<UUID, BigDecimal>();
if (withAdjustment) {
invoiceItemIdsWithAmounts.put(item2Replace.getId(), refundAmount);
}
invoiceDao.createRefund(paymentId, refundAmount, withAdjustment, invoiceItemIdsWithAmounts, UUID.randomUUID().toString(), context);
balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(expectedFinalBalance), 0);
cba = invoiceDao.getAccountCBA(accountId, context);
final BigDecimal expectedCba = balance.compareTo(BigDecimal.ZERO) < 0 ? balance.negate() : BigDecimal.ZERO;
assertEquals(cba.compareTo(expectedCba), 0);
}
use of org.killbill.billing.invoice.api.InvoicePayment in project killbill by killbill.
the class TestInvoiceDao method testAccountBalanceWithRefundInternal.
private void testAccountBalanceWithRefundInternal(final boolean withAdjustment) throws InvoiceApiException, EntityPersistenceException {
final UUID accountId = account.getId();
final UUID bundleId = UUID.randomUUID();
final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
invoiceUtil.createInvoice(invoice1, context);
final LocalDate startDate = new LocalDate(2011, 3, 1);
final LocalDate endDate = startDate.plusMonths(1);
final BigDecimal rate1 = new BigDecimal("20.0");
final BigDecimal refund1 = new BigDecimal("7.00");
// Recurring item
final RecurringInvoiceItem item2 = new RecurringInvoiceItem(invoice1.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test phase B", startDate, endDate, rate1, rate1, Currency.USD);
invoiceUtil.createInvoiceItem(item2, context);
BigDecimal balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(new BigDecimal("20.00")), 0);
// Pay the whole thing
final UUID paymentId = UUID.randomUUID();
final BigDecimal payment1 = rate1;
final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, paymentId, invoice1.getId(), new DateTime(), payment1, Currency.USD, Currency.USD, null, true);
invoiceUtil.createPayment(payment, context);
balance = invoiceDao.getAccountBalance(accountId, context);
assertEquals(balance.compareTo(new BigDecimal("0.00")), 0);
invoiceDao.createRefund(paymentId, refund1, withAdjustment, ImmutableMap.<UUID, BigDecimal>of(), UUID.randomUUID().toString(), context);
balance = invoiceDao.getAccountBalance(accountId, context);
if (withAdjustment) {
assertEquals(balance.compareTo(BigDecimal.ZERO), 0);
} else {
assertEquals(balance.compareTo(new BigDecimal("7.00")), 0);
}
}
use of org.killbill.billing.invoice.api.InvoicePayment in project killbill by killbill.
the class InvoicePaymentControlPluginApi method checkForIncompleteInvoicePaymentAndRepair.
private boolean checkForIncompleteInvoicePaymentAndRepair(final Invoice invoice, final InternalCallContext internalContext) throws InvoiceApiException {
final List<InvoicePayment> invoicePayments = invoice.getPayments();
// Look for ATTEMPT matching that invoiceId that are not successful and extract matching paymentTransaction
final InvoicePayment incompleteInvoicePayment = Iterables.tryFind(invoicePayments, new Predicate<InvoicePayment>() {
@Override
public boolean apply(final InvoicePayment input) {
return input.getType() == InvoicePaymentType.ATTEMPT && !input.isSuccess();
}
}).orNull();
// If such (incomplete) paymentTransaction exists, verify the state of the payment transaction
if (incompleteInvoicePayment != null) {
final String transactionExternalKey = incompleteInvoicePayment.getPaymentCookieId();
final List<PaymentTransactionModelDao> transactions = paymentDao.getPaymentTransactionsByExternalKey(transactionExternalKey, internalContext);
final PaymentTransactionModelDao successfulTransaction = Iterables.tryFind(transactions, new Predicate<PaymentTransactionModelDao>() {
@Override
public boolean apply(final PaymentTransactionModelDao input) {
//
return input.getTransactionStatus() == TransactionStatus.SUCCESS;
}
}).orNull();
if (successfulTransaction != null) {
log.info(String.format("Detected an incomplete invoicePayment row for invoiceId='%s' and transactionExternalKey='%s', will correct status", invoice.getId(), successfulTransaction.getTransactionExternalKey()));
invoiceApi.recordPaymentAttemptCompletion(invoice.getId(), successfulTransaction.getAmount(), successfulTransaction.getCurrency(), successfulTransaction.getProcessedCurrency(), successfulTransaction.getPaymentId(), successfulTransaction.getTransactionExternalKey(), successfulTransaction.getCreatedDate(), true, internalContext);
return true;
}
}
return false;
}
Aggregations