Details
diff --git a/api/src/main/java/org/killbill/billing/invoice/api/InvoiceInternalApi.java b/api/src/main/java/org/killbill/billing/invoice/api/InvoiceInternalApi.java
index 0403e60..b50879e 100644
--- a/api/src/main/java/org/killbill/billing/invoice/api/InvoiceInternalApi.java
+++ b/api/src/main/java/org/killbill/billing/invoice/api/InvoiceInternalApi.java
@@ -73,4 +73,6 @@ public interface InvoiceInternalApi {
* @param context the callcontext
*/
public void consumeExistingCBAOnAccountWithUnpaidInvoices(final UUID accountId, final InternalCallContext context) throws InvoiceApiException;
+
+ public Map<UUID, BigDecimal> validateInvoiceItemAdjustments(final UUID paymentId, final Map<UUID, BigDecimal> idWithAmount, final InternalTenantContext context) throws InvoiceApiException;
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java b/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
index b6d3059..e47f289 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
@@ -19,8 +19,10 @@ package org.killbill.billing.invoice.api;
import java.math.BigDecimal;
import java.util.Collection;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -52,6 +54,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
public class InvoiceApiHelper {
@@ -119,9 +122,12 @@ public class InvoiceApiHelper {
* @param effectiveDate adjustment effective date, in the account timezone
* @return the adjustment item
*/
- public InvoiceItem createAdjustmentItem(final Invoice invoiceToBeAdjusted, final UUID invoiceItemId,
- @Nullable final BigDecimal positiveAdjAmount, @Nullable final Currency currency,
- final LocalDate effectiveDate, final InternalCallContext context) throws InvoiceApiException {
+ public InvoiceItem createAdjustmentItem(final Invoice invoiceToBeAdjusted,
+ final UUID invoiceItemId,
+ @Nullable final BigDecimal positiveAdjAmount,
+ @Nullable final Currency currency,
+ final LocalDate effectiveDate,
+ final InternalCallContext context) throws InvoiceApiException {
final InvoiceItem invoiceItemToBeAdjusted = Iterables.<InvoiceItem>tryFind(invoiceToBeAdjusted.getInvoiceItems(),
new Predicate<InvoiceItem>() {
@Override
@@ -133,14 +139,20 @@ public class InvoiceApiHelper {
throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, invoiceItemId);
}
- // Retrieve the amount and currency if needed
- final BigDecimal amountToAdjust = Objects.firstNonNull(positiveAdjAmount, invoiceItemToBeAdjusted.getAmount());
// Check the specified currency matches the one of the existing invoice
final Currency currencyForAdjustment = Objects.firstNonNull(currency, invoiceItemToBeAdjusted.getCurrency());
if (invoiceItemToBeAdjusted.getCurrency() != currencyForAdjustment) {
throw new InvoiceApiException(ErrorCode.CURRENCY_INVALID, currency, invoiceItemToBeAdjusted.getCurrency());
}
+ // Reuse the same logic we have for the refun with item adjustment
+ final Map<UUID, BigDecimal> input = new HashMap<UUID, BigDecimal>();
+ input.put(invoiceItemId, positiveAdjAmount);
+
+ final Map<UUID, BigDecimal> output = dao.computeItemAdjustments(invoiceToBeAdjusted.getId().toString(), input, context);
+
+ // If we pass that stage, it means the validation succeeded so we just need to extract resulting amount and negate the result.
+ final BigDecimal amountToAdjust = output.get(invoiceItemId).negate();
// Finally, create the adjustment
return new ItemAdjInvoiceItem(UUIDs.randomUUID(),
context.getCreatedDate(),
@@ -148,8 +160,7 @@ public class InvoiceApiHelper {
invoiceItemToBeAdjusted.getAccountId(),
effectiveDate,
null,
- // Note! The amount is negated here!
- amountToAdjust.negate(),
+ amountToAdjust,
currencyForAdjustment,
invoiceItemToBeAdjusted.getId());
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java b/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
index b3da4f0..a4a7621 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
@@ -20,6 +20,7 @@ package org.killbill.billing.invoice.api.svcs;
import java.math.BigDecimal;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -41,6 +42,8 @@ import org.killbill.billing.invoice.api.InvoicePayment;
import org.killbill.billing.invoice.api.InvoicePaymentType;
import org.killbill.billing.invoice.api.WithAccountLock;
import org.killbill.billing.invoice.dao.InvoiceDao;
+import org.killbill.billing.invoice.dao.InvoiceDaoHelper;
+import org.killbill.billing.invoice.dao.InvoiceItemModelDao;
import org.killbill.billing.invoice.dao.InvoiceModelDao;
import org.killbill.billing.invoice.dao.InvoicePaymentModelDao;
import org.killbill.billing.invoice.model.DefaultInvoice;
@@ -158,6 +161,12 @@ public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
dao.consumeExstingCBAOnAccountWithUnpaidInvoices(accountId, context);
}
+ @Override
+ public Map<UUID, BigDecimal> validateInvoiceItemAdjustments(final UUID paymentId, final Map<UUID, BigDecimal> idWithAmount, final InternalTenantContext context) throws InvoiceApiException {
+ final InvoicePayment invoicePayment = getInvoicePayment(paymentId, InvoicePaymentType.ATTEMPT, context);
+ return dao.computeItemAdjustments(invoicePayment.getInvoiceId().toString(), idWithAmount, context);
+ }
+
private InvoicePayment getInvoicePayment(final UUID paymentId, final InvoicePaymentType type, final InternalTenantContext context) throws InvoiceApiException {
final Collection<InvoicePayment> invoicePayments = Collections2.transform(dao.getInvoicePayments(paymentId, context), new Function<InvoicePaymentModelDao, InvoicePayment>() {
@Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 0c2b5b3..d5d3bd6 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -394,7 +394,7 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
amount,
currency,
effectiveDate,
- internalCallContextFactory.createInternalCallContext(context));
+ internalCallContextFactory.createInternalCallContext(accountId, context));
invoice.addInvoiceItem(adjustmentItem);
return ImmutableList.<Invoice>of(invoice);
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
index 0f4cdc0..8f97ea4 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
@@ -575,6 +575,16 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
}
@Override
+ public Map<UUID, BigDecimal> computeItemAdjustments(final String invoiceId, final Map<UUID, BigDecimal> invoiceItemIdsWithNullAmounts, final InternalTenantContext context) throws InvoiceApiException {
+ return transactionalSqlDao.execute(InvoiceApiException.class, new EntitySqlDaoTransactionWrapper<Map<UUID, BigDecimal>>() {
+ @Override
+ public Map<UUID, BigDecimal> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+ return invoiceDaoHelper.computeItemAdjustments(invoiceId, entitySqlDaoWrapperFactory, invoiceItemIdsWithNullAmounts, context);
+ }
+ });
+ }
+
+ @Override
public BigDecimal getRemainingAmountPaid(final UUID invoicePaymentId, final InternalTenantContext context) {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<BigDecimal>() {
@Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
index a5d1590..effce52 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
@@ -75,6 +75,10 @@ public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceA
InvoiceItemModelDao doCBAComplexity(InvoiceModelDao invoice, InternalCallContext context) throws InvoiceApiException;
+ Map<UUID, BigDecimal> computeItemAdjustments(final String invoiceId,
+ final Map<UUID, BigDecimal> invoiceItemIdsWithNullAmounts,
+ final InternalTenantContext context) throws InvoiceApiException;
+
/**
* Create a refund.
*
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDaoHelper.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDaoHelper.java
index 56beb81..407aa6f 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDaoHelper.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDaoHelper.java
@@ -34,7 +34,6 @@ import org.killbill.billing.ErrorCode;
import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.catalog.api.Currency;
-import org.killbill.billing.entity.EntityPersistenceException;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
@@ -43,7 +42,6 @@ import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap.Builder;
public class InvoiceDaoHelper {
@@ -65,9 +63,9 @@ public class InvoiceDaoHelper {
final Map<UUID, BigDecimal> invoiceItemIdsWithNullAmounts,
final InternalTenantContext context) throws InvoiceApiException {
// Populate the missing amounts for individual items, if needed
- final Builder<UUID, BigDecimal> invoiceItemIdsWithAmountsBuilder = new Builder<UUID, BigDecimal>();
+ final Map<UUID, BigDecimal> outputItemIdsWithAmounts = new HashMap<UUID, BigDecimal>();
if (invoiceItemIdsWithNullAmounts.size() == 0) {
- return invoiceItemIdsWithAmountsBuilder.build();
+ return outputItemIdsWithAmounts;
}
// Retrieve invoice before the Refund
@@ -82,53 +80,50 @@ public class InvoiceDaoHelper {
// If we have an item amount, we 'd like to use it, but we need to check first that it is lesser or equal than maximum allowed
//If, not we compute maximum value we can adjust per item
for (final UUID invoiceItemId : invoiceItemIdsWithNullAmounts.keySet()) {
- final BigDecimal originalItemAmount = getInvoiceItemAmountForId(invoice, invoiceItemId);
- final BigDecimal maxAdjAmount = computeItemAdjustmentAmount(invoiceItemId, originalItemAmount, invoice.getInvoiceItems());
+ final List<InvoiceItemModelDao> adjustedOrRepairedItems = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class).getAdjustedOrRepairedInvoiceItemsByLinkedId(invoiceItemId.toString(), context);
+ computeItemAdjustmentsForTargetInvoiceItem(getInvoiceItemForId(invoice, invoiceItemId), adjustedOrRepairedItems, invoiceItemIdsWithNullAmounts, outputItemIdsWithAmounts);
+ }
+ return outputItemIdsWithAmounts;
+ }
- final BigDecimal proposedItemAmount = invoiceItemIdsWithNullAmounts.get(invoiceItemId);
- if (proposedItemAmount != null && proposedItemAmount.compareTo(maxAdjAmount) > 0) {
- throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_ADJUSTMENT_AMOUNT_INVALID, proposedItemAmount, maxAdjAmount);
- }
- final BigDecimal itemAmountToAdjust = Objects.firstNonNull(proposedItemAmount, maxAdjAmount);
- if (itemAmountToAdjust.compareTo(BigDecimal.ZERO) > 0) {
- invoiceItemIdsWithAmountsBuilder.put(invoiceItemId, itemAmountToAdjust);
- }
+ private static void computeItemAdjustmentsForTargetInvoiceItem(final InvoiceItemModelDao targetInvoiceItem, final List<InvoiceItemModelDao> adjustedOrRepairedItems, final Map<UUID, BigDecimal> inputAdjInvoiceItem, final Map<UUID, BigDecimal> outputAdjInvoiceItem) throws InvoiceApiException {
+ final BigDecimal originalItemAmount = targetInvoiceItem.getAmount();
+ final BigDecimal maxAdjLeftAmount = computeItemAdjustmentAmount(originalItemAmount, adjustedOrRepairedItems);
+
+ final BigDecimal proposedItemAmount = inputAdjInvoiceItem.get(targetInvoiceItem.getId());
+ if (proposedItemAmount != null && proposedItemAmount.compareTo(maxAdjLeftAmount) > 0) {
+ throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_ADJUSTMENT_AMOUNT_INVALID, proposedItemAmount, maxAdjLeftAmount);
}
- return invoiceItemIdsWithAmountsBuilder.build();
+ final BigDecimal itemAmountToAdjust = Objects.firstNonNull(proposedItemAmount, maxAdjLeftAmount);
+ if (itemAmountToAdjust.compareTo(BigDecimal.ZERO) > 0) {
+ outputAdjInvoiceItem.put(targetInvoiceItem.getId(), itemAmountToAdjust);
+ }
}
/**
- * @param invoiceItem item we are adjusting
* @param requestedPositiveAmountToAdjust amount we are adjusting for that item
- * @param invoiceItems list of all invoice items on this invoice
+ * @param adjustedOrRepairedItems list of all adjusted or repaired linking to this item
* @return the amount we should really adjust based on whether or not the item got repaired
*/
- private BigDecimal computeItemAdjustmentAmount(final UUID invoiceItem, final BigDecimal requestedPositiveAmountToAdjust, final List<InvoiceItemModelDao> invoiceItems) {
+ private static BigDecimal computeItemAdjustmentAmount(final BigDecimal requestedPositiveAmountToAdjust, final List<InvoiceItemModelDao> adjustedOrRepairedItems) {
- BigDecimal positiveRepairedAmount = BigDecimal.ZERO;
+ BigDecimal positiveAdjustedOrRepairedAmount = BigDecimal.ZERO;
- final Collection<InvoiceItemModelDao> repairedItems = Collections2.filter(invoiceItems, new Predicate<InvoiceItemModelDao>() {
- @Override
- public boolean apply(final InvoiceItemModelDao input) {
- return (input.getType() == InvoiceItemType.REPAIR_ADJ && input.getLinkedItemId().equals(invoiceItem));
- }
- });
- for (final InvoiceItemModelDao cur : repairedItems) {
- // Repair item are negative so we negate to make it positive
- positiveRepairedAmount = positiveRepairedAmount.add(cur.getAmount().negate());
+ for (final InvoiceItemModelDao cur : adjustedOrRepairedItems) {
+ // Adjustment or repair items are negative so we negate to make it positive
+ positiveAdjustedOrRepairedAmount = positiveAdjustedOrRepairedAmount.add(cur.getAmount().negate());
}
- return (positiveRepairedAmount.compareTo(requestedPositiveAmountToAdjust) >= 0) ? BigDecimal.ZERO : requestedPositiveAmountToAdjust.subtract(positiveRepairedAmount);
+ return (positiveAdjustedOrRepairedAmount.compareTo(requestedPositiveAmountToAdjust) >= 0) ? BigDecimal.ZERO : requestedPositiveAmountToAdjust.subtract(positiveAdjustedOrRepairedAmount);
}
- private BigDecimal getInvoiceItemAmountForId(final InvoiceModelDao invoice, final UUID invoiceItemId) throws InvoiceApiException {
+ private InvoiceItemModelDao getInvoiceItemForId(final InvoiceModelDao invoice, final UUID invoiceItemId) throws InvoiceApiException {
for (final InvoiceItemModelDao invoiceItem : invoice.getInvoiceItems()) {
if (invoiceItem.getId().equals(invoiceItemId)) {
- return invoiceItem.getAmount();
+ return invoiceItem;
}
}
-
throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, invoiceItemId);
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java
index e4245c4..4ec1a9f 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java
@@ -37,4 +37,9 @@ public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItemModelDao, Inv
@SqlQuery
List<InvoiceItemModelDao> getInvoiceItemsBySubscription(@Bind("subscriptionId") final String subscriptionId,
@BindBean final InternalTenantContext context);
+
+
+ @SqlQuery
+ List<InvoiceItemModelDao> getAdjustedOrRepairedInvoiceItemsByLinkedId(@Bind("linkedItemId") final String linkedItemId,
+ @BindBean final InternalTenantContext context);
}
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
index d5d3a7f..8470a77 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
@@ -58,3 +58,12 @@ getInvoiceItemsBySubscription() ::= <<
<AND_CHECK_TENANT()>
;
>>
+
+getAdjustedOrRepairedInvoiceItemsByLinkedId() ::= <<
+ SELECT <allTableFields()>
+ FROM <tableName()>
+ WHERE linked_item_id = :linkedItemId
+ AND type IN ('ITEM_ADJ', 'REPAIR_ADJ')
+ <AND_CHECK_TENANT()>
+ ;
+>>
\ No newline at end of file
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql b/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql
index bb1ed4e..1a3907c 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql
@@ -29,6 +29,7 @@ CREATE UNIQUE INDEX invoice_items_id ON invoice_items(id);
CREATE INDEX invoice_items_subscription_id ON invoice_items(subscription_id ASC);
CREATE INDEX invoice_items_invoice_id ON invoice_items(invoice_id ASC);
CREATE INDEX invoice_items_account_id ON invoice_items(account_id ASC);
+CREATE INDEX invoice_items_linked_item_id ON invoice_items(linked_item_id ASC);
CREATE INDEX invoice_items_tenant_account_record_id ON invoice_items(tenant_record_id, account_record_id);
DROP TABLE IF EXISTS invoices;
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
index aabfb60..d6a2133 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
@@ -304,6 +304,11 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
}
@Override
+ public Map<UUID, BigDecimal> computeItemAdjustments(final String invoiceId, final Map<UUID, BigDecimal> invoiceItemIdsWithNullAmounts, final InternalTenantContext context) throws InvoiceApiException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public BigDecimal getRemainingAmountPaid(final UUID invoicePaymentId, final InternalTenantContext context) {
throw new UnsupportedOperationException();
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java b/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
index f3738f5..51c25da 100644
--- a/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
@@ -300,6 +300,19 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
amountToBeRefunded,
paymentControlPluginContext.getAmount())));
}
+
+ final PluginProperty prop = getPluginProperty(pluginProperties, PROP_IPCD_REFUND_WITH_ADJUSTMENTS);
+ final boolean isAdjusted = prop != null ? Boolean.valueOf((String) prop.getValue()) : false;
+ if (isAdjusted) {
+ try {
+ invoiceApi.validateInvoiceItemAdjustments(paymentControlPluginContext.getPaymentId(), idWithAmount, internalContext);
+ } catch (InvoiceApiException e) {
+ throw new PaymentControlApiException(String.format("Refund for payment %s aborted", payment.getId()),
+ new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, e.getMessage()));
+ }
+ }
+
+ return new DefaultPriorPaymentControlResult(isAborted, amountToBeRefunded);
}
private Map<UUID, BigDecimal> extractIdsWithAmountFromProperties(final Iterable<PluginProperty> properties) {
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
index 71ea328..de2d296 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
@@ -415,7 +415,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
createPropertiesForInvoice(invoice), INVOICE_PAYMENT, callContext);
Assert.fail("Unexpected success");
} catch (final PaymentApiException e) {
- assertTrue(e.getCause() instanceof PaymentControlApiException);
}
}