killbill-memoizeit

Fixes #96

10/8/2013 3:19:03 PM

Details

diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index eb26739..1b6e286 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -433,6 +433,7 @@ public class AccountResource extends JaxRsResourceBase {
     public Response createPaymentMethod(final PaymentMethodJson json,
                                         @PathParam("accountId") final String accountId,
                                         @QueryParam(QUERY_PAYMENT_METHOD_IS_DEFAULT) @DefaultValue("false") final Boolean isDefault,
+                                        @QueryParam(QUERY_PAY_ALL_UNPAID_INVOICES) @DefaultValue("false") final Boolean payAllUnpaidInvoices,
                                         @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                         @HeaderParam(HDR_REASON) final String reason,
                                         @HeaderParam(HDR_COMMENT) final String comment,
@@ -443,7 +444,18 @@ public class AccountResource extends JaxRsResourceBase {
         final PaymentMethod data = json.toPaymentMethod(accountId);
         final Account account = accountUserApi.getAccountById(data.getAccountId(), callContext);
 
+        final boolean hasDefaultPaymentMethod = account.getPaymentMethodId() != null || isDefault;
+        final Collection<Invoice> unpaidInvoices = invoiceApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext);
+        if (payAllUnpaidInvoices && unpaidInvoices.size() > 0 && !hasDefaultPaymentMethod) {
+            return Response.status(Status.BAD_REQUEST).build();
+        }
+
         final UUID paymentMethodId = paymentApi.addPaymentMethod(data.getPluginName(), account, isDefault, data.getPluginDetail(), callContext);
+        if (payAllUnpaidInvoices && unpaidInvoices.size() > 0) {
+            for (final Invoice invoice : unpaidInvoices) {
+                paymentApi.createPayment(account, invoice.getId(), invoice.getBalance(), callContext);
+            }
+        }
         return uriBuilder.buildResponse(PaymentMethodResource.class, "getPaymentMethod", paymentMethodId, uriInfo.getBaseUri().toString());
     }
 
@@ -473,6 +485,7 @@ public class AccountResource extends JaxRsResourceBase {
     @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENT_METHODS + "/{paymentMethodId:" + UUID_PATTERN + "}/" + PAYMENT_METHODS_DEFAULT_PATH_POSTFIX)
     public Response setDefaultPaymentMethod(@PathParam("accountId") final String accountId,
                                             @PathParam("paymentMethodId") final String paymentMethodId,
+                                            @QueryParam(QUERY_PAY_ALL_UNPAID_INVOICES) @DefaultValue("false") final Boolean payAllUnpaidInvoices,
                                             @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                             @HeaderParam(HDR_REASON) final String reason,
                                             @HeaderParam(HDR_COMMENT) final String comment,
@@ -481,6 +494,13 @@ public class AccountResource extends JaxRsResourceBase {
 
         final Account account = accountUserApi.getAccountById(UUID.fromString(accountId), callContext);
         paymentApi.setDefaultPaymentMethod(account, UUID.fromString(paymentMethodId), callContext);
+
+        if (payAllUnpaidInvoices) {
+            final Collection<Invoice> unpaidInvoices = invoiceApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext);
+            for (final Invoice invoice : unpaidInvoices) {
+                paymentApi.createPayment(account, invoice.getId(), invoice.getBalance(), callContext);
+            }
+        }
         return Response.status(Status.OK).build();
     }
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
index bf2915a..fbdda77 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
@@ -80,6 +80,8 @@ public interface JaxrsResource {
     public static final String QUERY_PAYMENT_METHOD_PLUGIN_INFO = "withPluginInfo";
     public static final String QUERY_PAYMENT_METHOD_IS_DEFAULT = "isDefault";
 
+    public static final String QUERY_PAY_ALL_UNPAID_INVOICES = "payAllUnpaidInvoices";
+
     public static final String QUERY_BUNDLE_TRANSFER_ADDON = "transferAddOn";
     public static final String QUERY_BUNDLE_TRANSFER_CANCEL_IMM = "cancelImmediately";
 
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
index b7d1296..bfc5550 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
@@ -75,6 +75,8 @@ import static com.ning.billing.payment.glue.PaymentModule.PLUGIN_EXECUTOR_NAMED;
 
 public class PaymentProcessor extends ProcessorBase {
 
+    private static final UUID MISSING_PAYMENT_METHOD_ID = UUID.fromString("99999999-dead-beef-babe-999999999999");
+
     private final PaymentMethodProcessor paymentMethodProcessor;
     private final FailedPaymentRetryServiceScheduler failedPaymentRetryService;
     private final PluginFailureRetryServiceScheduler pluginFailureRetryService;
@@ -258,6 +260,10 @@ public class PaymentProcessor extends ProcessorBase {
                                         paymentMethodId = account.getPaymentMethodId();
                                     }
                                 } catch (PaymentApiException e) {
+
+                                    // Insert a payment entry with one attempt in a terminal state to keep a record of the failure
+                                    processNewPaymentForMissingDefaultPaymentMethodWithAccountLocked(account, invoice, requestedAmount, context);
+
                                     // This event will be caught by overdue to refresh the overdue state, if needed.
                                     // Note that at this point, we don't know the exact invoice balance (see getAndValidatePaymentAmount() below).
                                     // This means that events will be posted for null and zero dollar invoices (e.g. trials).
@@ -438,6 +444,20 @@ public class PaymentProcessor extends ProcessorBase {
         return fromPaymentModelDao(paymentInfo, null, context);
     }
 
+
+    private Payment processNewPaymentForMissingDefaultPaymentMethodWithAccountLocked(final Account account, final Invoice invoice,
+                                                                                     final BigDecimal requestedAmount, final InternalCallContext context)
+            throws PaymentApiException {
+        final PaymentStatus paymentStatus = PaymentStatus.PAYMENT_FAILURE_ABORTED ;
+
+        final PaymentModelDao paymentInfo = new PaymentModelDao(account.getId(), invoice.getId(), MISSING_PAYMENT_METHOD_ID, requestedAmount, invoice.getCurrency(), clock.getUTCNow(), paymentStatus);
+        final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), invoice.getId(), paymentInfo.getId(), MISSING_PAYMENT_METHOD_ID, paymentStatus, clock.getUTCNow(), requestedAmount);
+
+        paymentDao.insertPaymentWithFirstAttempt(paymentInfo, attempt, context);
+        return fromPaymentModelDao(paymentInfo, null, context);
+    }
+
+
     private Payment processNewPaymentWithAccountLocked(final UUID paymentMethodId, final PaymentPluginApi plugin, final Account account, final Invoice invoice,
                                                        final BigDecimal requestedAmount, final boolean isInstantPayment, final InternalCallContext context) throws PaymentApiException {
         final PaymentModelDao payment = new PaymentModelDao(account.getId(), invoice.getId(), paymentMethodId, requestedAmount.setScale(2, RoundingMode.HALF_UP), invoice.getCurrency(), clock.getUTCNow());
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
index 7193cb9..1587ee6 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
@@ -17,93 +17,45 @@
 package com.ning.billing.payment.api;
 
 import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.util.List;
 import java.util.UUID;
 
 import org.joda.time.LocalDate;
-import org.mockito.Mockito;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.ning.billing.ErrorCode;
 import com.ning.billing.account.api.Account;
+import com.ning.billing.bus.api.PersistentBus.EventBusException;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.payment.MockRecurringInvoiceItem;
-import com.ning.billing.payment.PaymentTestSuiteNoDB;
-import com.ning.billing.payment.provider.DefaultNoOpPaymentMethodPlugin;
-import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
+import com.ning.billing.payment.PaymentTestSuiteWithEmbeddedDB;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
+public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
 
-public class TestPaymentApi extends PaymentTestSuiteNoDB {
-
-    private static final Logger log = LoggerFactory.getLogger(TestPaymentApi.class);
 
     private Account account;
 
-    @BeforeClass(groups = "fast")
+    @BeforeClass(groups = "slow")
     public void beforeClass() throws Exception {
         super.beforeClass();
-        account = testHelper.createTestAccount("yoyo.yahoo.com", false);
-    }
-
-    @BeforeMethod(groups = "fast")
-    public void beforeMethod() throws Exception {
-        super.beforeMethod();
-        final PaymentMethodPlugin paymentMethodInfo = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), true, null);
-        testHelper.addTestPaymentMethod(account, paymentMethodInfo);
-    }
-
-    @Test(groups = "fast")
-    public void testSimplePaymentWithNoAmount() throws Exception {
-        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
-        final BigDecimal requestedAmount = null;
-        final BigDecimal expectedAmount = invoiceAmount;
-
-        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
+        account = testHelper.createTestAccount("bobo@gmail.com", false);
     }
 
-    @Test(groups = "fast")
-    public void testSimplePaymentWithInvoiceAmount() throws Exception {
-        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
-        final BigDecimal requestedAmount = invoiceAmount;
-        final BigDecimal expectedAmount = invoiceAmount;
 
-        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
-    }
-
-    @Test(groups = "fast")
-    public void testSimplePaymentWithLowerAmount() throws Exception {
-        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
-        final BigDecimal requestedAmount = new BigDecimal("8.0091");
-        final BigDecimal expectedAmount = requestedAmount;
-
-        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
-    }
-
-    @Test(groups = "fast")
-    public void testSimplePaymentWithInvalidAmount() throws Exception {
-        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
-        final BigDecimal requestedAmount = new BigDecimal("80.0091");
-        final BigDecimal expectedAmount = null;
+    @Test(groups = "slow")
+    public void testCreatePaymentWithNoDefaultPaymentMethod() throws InvoiceApiException, EventBusException, PaymentApiException {
 
-        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
-    }
 
-    private void testSimplePayment(final BigDecimal invoiceAmount, final BigDecimal requestedAmount, final BigDecimal expectedAmount) throws Exception {
         final LocalDate now = clock.getUTCToday();
         final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD, callContext);
 
         final UUID subscriptionId = UUID.randomUUID();
         final UUID bundleId = UUID.randomUUID();
+        final BigDecimal requestedAmount = BigDecimal.TEN;
 
         invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(), account.getId(),
                                                             subscriptionId,
@@ -111,69 +63,20 @@ public class TestPaymentApi extends PaymentTestSuiteNoDB {
                                                             "test plan", "test phase",
                                                             now,
                                                             now.plusMonths(1),
-                                                            invoiceAmount,
+                                                            requestedAmount,
                                                             new BigDecimal("1.0"),
                                                             Currency.USD));
 
         try {
-            final Payment paymentInfo = paymentApi.createPayment(account, invoice.getId(), requestedAmount, callContext);
-            if (expectedAmount == null) {
-                fail("Expected to fail because requested amount > invoice amount");
-            }
-            assertNotNull(paymentInfo.getId());
-            assertTrue(paymentInfo.getAmount().compareTo(expectedAmount.setScale(2, RoundingMode.HALF_EVEN)) == 0);
-            assertNotNull(paymentInfo.getPaymentNumber());
-            assertEquals(paymentInfo.getPaymentStatus(), PaymentStatus.SUCCESS);
-            assertEquals(paymentInfo.getAttempts().size(), 1);
-            assertEquals(paymentInfo.getInvoiceId(), invoice.getId());
-            assertEquals(paymentInfo.getCurrency(), Currency.USD);
-
-            final PaymentAttempt paymentAttempt = paymentInfo.getAttempts().get(0);
-            assertNotNull(paymentAttempt);
-            assertNotNull(paymentAttempt.getId());
+            paymentApi.createPayment(account, invoice.getId(), requestedAmount, callContext);
         } catch (PaymentApiException e) {
-            if (expectedAmount != null) {
-                fail("Failed to create payment", e);
-            } else {
-                log.info(e.getMessage());
-                assertEquals(e.getCode(), ErrorCode.PAYMENT_AMOUNT_DENIED.getCode());
-            }
+            Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD.getCode());
         }
-    }
-
-    @Test(groups = "fast")
-    public void testPaymentMethods() throws Exception {
-        List<PaymentMethod> methods = paymentApi.getPaymentMethods(account, false, callContext);
-        assertEquals(methods.size(), 1);
-
-        final PaymentMethod initDefaultMethod = methods.get(0);
-        assertEquals(initDefaultMethod.getId(), account.getPaymentMethodId());
-
-        final PaymentMethodPlugin newPaymenrMethod = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), true, null);
-        final UUID newPaymentMethodId = paymentApi.addPaymentMethod(MockPaymentProviderPlugin.PLUGIN_NAME, account, true, newPaymenrMethod, callContext);
-        Mockito.when(account.getPaymentMethodId()).thenReturn(newPaymentMethodId);
-
-        methods = paymentApi.getPaymentMethods(account, false, callContext);
-        assertEquals(methods.size(), 2);
-
-        assertEquals(newPaymentMethodId, account.getPaymentMethodId());
-
-        boolean failed = false;
-        try {
-            paymentApi.deletedPaymentMethod(account, newPaymentMethodId, false, callContext);
-        } catch (PaymentApiException e) {
-            failed = true;
-        }
-        assertTrue(failed);
-
-        paymentApi.deletedPaymentMethod(account, initDefaultMethod.getId(), true,  callContext);
-        methods = paymentApi.getPaymentMethods(account, false, callContext);
-        assertEquals(methods.size(), 1);
 
-        // NOW retry with default payment method with special flag
-        paymentApi.deletedPaymentMethod(account, newPaymentMethodId, true, callContext);
+        final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), callContext);
+        Assert.assertEquals(payments.size(), 1);
 
-        methods = paymentApi.getPaymentMethods(account, false, callContext);
-        assertEquals(methods.size(), 0);
+        final Payment payment = payments.get(0);
+        Assert.assertEquals(payment.getPaymentStatus(), PaymentStatus.PAYMENT_FAILURE_ABORTED);
     }
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApiNoDB.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApiNoDB.java
new file mode 100644
index 0000000..32938da
--- /dev/null
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApiNoDB.java
@@ -0,0 +1,179 @@
+/*
+ * 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.payment.api;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.LocalDate;
+import org.mockito.Mockito;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.ning.billing.ErrorCode;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.payment.MockRecurringInvoiceItem;
+import com.ning.billing.payment.PaymentTestSuiteNoDB;
+import com.ning.billing.payment.provider.DefaultNoOpPaymentMethodPlugin;
+import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+public class TestPaymentApiNoDB extends PaymentTestSuiteNoDB {
+
+    private static final Logger log = LoggerFactory.getLogger(TestPaymentApiNoDB.class);
+
+    private Account account;
+
+    @BeforeClass(groups = "fast")
+    public void beforeClass() throws Exception {
+        super.beforeClass();
+        account = testHelper.createTestAccount("yoyo.yahoo.com", false);
+    }
+
+    @BeforeMethod(groups = "fast")
+    public void beforeMethod() throws Exception {
+        super.beforeMethod();
+        final PaymentMethodPlugin paymentMethodInfo = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), true, null);
+        testHelper.addTestPaymentMethod(account, paymentMethodInfo);
+    }
+
+    @Test(groups = "fast")
+    public void testSimplePaymentWithNoAmount() throws Exception {
+        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
+        final BigDecimal requestedAmount = null;
+        final BigDecimal expectedAmount = invoiceAmount;
+
+        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
+    }
+
+    @Test(groups = "fast")
+    public void testSimplePaymentWithInvoiceAmount() throws Exception {
+        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
+        final BigDecimal requestedAmount = invoiceAmount;
+        final BigDecimal expectedAmount = invoiceAmount;
+
+        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
+    }
+
+    @Test(groups = "fast")
+    public void testSimplePaymentWithLowerAmount() throws Exception {
+        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
+        final BigDecimal requestedAmount = new BigDecimal("8.0091");
+        final BigDecimal expectedAmount = requestedAmount;
+
+        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
+    }
+
+    @Test(groups = "fast")
+    public void testSimplePaymentWithInvalidAmount() throws Exception {
+        final BigDecimal invoiceAmount = new BigDecimal("10.0011");
+        final BigDecimal requestedAmount = new BigDecimal("80.0091");
+        final BigDecimal expectedAmount = null;
+
+        testSimplePayment(invoiceAmount, requestedAmount, expectedAmount);
+    }
+
+    private void testSimplePayment(final BigDecimal invoiceAmount, final BigDecimal requestedAmount, final BigDecimal expectedAmount) throws Exception {
+        final LocalDate now = clock.getUTCToday();
+        final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD, callContext);
+
+        final UUID subscriptionId = UUID.randomUUID();
+        final UUID bundleId = UUID.randomUUID();
+
+        invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(), account.getId(),
+                                                            subscriptionId,
+                                                            bundleId,
+                                                            "test plan", "test phase",
+                                                            now,
+                                                            now.plusMonths(1),
+                                                            invoiceAmount,
+                                                            new BigDecimal("1.0"),
+                                                            Currency.USD));
+
+        try {
+            final Payment paymentInfo = paymentApi.createPayment(account, invoice.getId(), requestedAmount, callContext);
+            if (expectedAmount == null) {
+                fail("Expected to fail because requested amount > invoice amount");
+            }
+            assertNotNull(paymentInfo.getId());
+            assertTrue(paymentInfo.getAmount().compareTo(expectedAmount.setScale(2, RoundingMode.HALF_EVEN)) == 0);
+            assertNotNull(paymentInfo.getPaymentNumber());
+            assertEquals(paymentInfo.getPaymentStatus(), PaymentStatus.SUCCESS);
+            assertEquals(paymentInfo.getAttempts().size(), 1);
+            assertEquals(paymentInfo.getInvoiceId(), invoice.getId());
+            assertEquals(paymentInfo.getCurrency(), Currency.USD);
+
+            final PaymentAttempt paymentAttempt = paymentInfo.getAttempts().get(0);
+            assertNotNull(paymentAttempt);
+            assertNotNull(paymentAttempt.getId());
+        } catch (PaymentApiException e) {
+            if (expectedAmount != null) {
+                fail("Failed to create payment", e);
+            } else {
+                log.info(e.getMessage());
+                assertEquals(e.getCode(), ErrorCode.PAYMENT_AMOUNT_DENIED.getCode());
+            }
+        }
+    }
+
+    @Test(groups = "fast")
+    public void testPaymentMethods() throws Exception {
+        List<PaymentMethod> methods = paymentApi.getPaymentMethods(account, false, callContext);
+        assertEquals(methods.size(), 1);
+
+        final PaymentMethod initDefaultMethod = methods.get(0);
+        assertEquals(initDefaultMethod.getId(), account.getPaymentMethodId());
+
+        final PaymentMethodPlugin newPaymenrMethod = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), true, null);
+        final UUID newPaymentMethodId = paymentApi.addPaymentMethod(MockPaymentProviderPlugin.PLUGIN_NAME, account, true, newPaymenrMethod, callContext);
+        Mockito.when(account.getPaymentMethodId()).thenReturn(newPaymentMethodId);
+
+        methods = paymentApi.getPaymentMethods(account, false, callContext);
+        assertEquals(methods.size(), 2);
+
+        assertEquals(newPaymentMethodId, account.getPaymentMethodId());
+
+        boolean failed = false;
+        try {
+            paymentApi.deletedPaymentMethod(account, newPaymentMethodId, false, callContext);
+        } catch (PaymentApiException e) {
+            failed = true;
+        }
+        assertTrue(failed);
+
+        paymentApi.deletedPaymentMethod(account, initDefaultMethod.getId(), true,  callContext);
+        methods = paymentApi.getPaymentMethods(account, false, callContext);
+        assertEquals(methods.size(), 1);
+
+        // NOW retry with default payment method with special flag
+        paymentApi.deletedPaymentMethod(account, newPaymentMethodId, true, callContext);
+
+        methods = paymentApi.getPaymentMethods(account, false, callContext);
+        assertEquals(methods.size(), 0);
+    }
+}