killbill-uncached

Add call from Payment Processor to rebalance CBA before making

6/14/2013 10:14:35 PM

Details

diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
index 4148e00..7294f86 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
@@ -49,6 +49,7 @@ import com.google.common.collect.Collections2;
 public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
 
     private static final WithInvoiceApiException<InvoicePayment> invoicePaymentWithException = new WithInvoiceApiException<InvoicePayment>();
+    private static final WithInvoiceApiException<Void> voidWithException = new WithInvoiceApiException<Void>();
 
     private final InvoiceDao dao;
 
@@ -132,19 +133,22 @@ public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
                 if (amount.compareTo(BigDecimal.ZERO) <= 0) {
                     throw new InvoiceApiException(ErrorCode.PAYMENT_REFUND_AMOUNT_NEGATIVE_OR_NULL);
                 }
-
-                final Collection<InvoicePayment> invoicePayments = Collections2.transform(dao.getInvoicePayments(paymentId, context), new Function<InvoicePaymentModelDao, InvoicePayment>() {
-                    @Override
-                    public InvoicePayment apply(final InvoicePaymentModelDao input) {
-                        return new DefaultInvoicePayment(input);
-                    }
-                });
-
                 return new DefaultInvoicePayment(dao.createRefund(paymentId, amount, isInvoiceAdjusted, invoiceItemIdsWithAmounts, paymentCookieId, context));
             }
         });
     }
 
+    @Override
+    public void consumeExistingCBAOnAccountWithUnpaidInvoices(final UUID accountId, final InternalCallContext context) throws InvoiceApiException {
+        voidWithException.executeAndThrow(new WithInvoiceApiExceptionCallback<Void>()  {
+            @Override
+            public Void doHandle() throws InvoiceApiException {
+                dao.consumeExstingCBAOnAccountWithUnpaidInvoices(accountId, context);
+                return null;
+            }
+        });
+    }
+
     //
     // Allow to safely catch TransactionFailedException exceptions and rethrow the correct InvoiceApiException exception
     //
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
index 0992e64..3bd3665 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
@@ -49,6 +49,7 @@ import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.globallocker.GlobalLocker;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 import com.ning.billing.util.svcapi.tag.TagInternalApi;
 import com.ning.billing.util.svcsapi.bus.InternalBus;
 
@@ -67,12 +68,13 @@ public class PaymentMethodProcessor extends ProcessorBase {
     @Inject
     public PaymentMethodProcessor(final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
                                   final AccountInternalApi accountInternalApi,
+                                  final InvoiceInternalApi invoiceApi,
                                   final InternalBus eventBus,
                                   final PaymentDao paymentDao,
                                   final TagInternalApi tagUserApi,
                                   final GlobalLocker locker,
                                   @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
-        super(pluginRegistry, accountInternalApi, eventBus, paymentDao, tagUserApi, locker, executor);
+        super(pluginRegistry, accountInternalApi, eventBus, paymentDao, tagUserApi, locker, executor, invoiceApi);
     }
 
     public Set<String> getAvailablePlugins() {
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 b221108..016c534 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
@@ -78,7 +78,6 @@ import static com.ning.billing.payment.glue.PaymentModule.PLUGIN_EXECUTOR_NAMED;
 public class PaymentProcessor extends ProcessorBase {
 
     private final PaymentMethodProcessor paymentMethodProcessor;
-    private final InvoiceInternalApi invoiceApi;
     private final FailedPaymentRetryServiceScheduler failedPaymentRetryService;
     private final PluginFailureRetryServiceScheduler pluginFailureRetryService;
     private final AutoPayRetryServiceScheduler autoPayoffRetryService;
@@ -108,9 +107,8 @@ public class PaymentProcessor extends ProcessorBase {
                             final GlobalLocker locker,
                             final PaymentConfig paymentConfig,
                             @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
-        super(pluginRegistry, accountUserApi, eventBus, paymentDao, tagUserApi, locker, executor);
+        super(pluginRegistry, accountUserApi, eventBus, paymentDao, tagUserApi, locker, executor, invoiceApi);
         this.paymentMethodProcessor = paymentMethodProcessor;
-        this.invoiceApi = invoiceApi;
         this.failedPaymentRetryService = failedPaymentRetryService;
         this.pluginFailureRetryService = pluginFailureRetryService;
         this.autoPayoffRetryService = autoPayoffRetryService;
@@ -250,9 +248,8 @@ public class PaymentProcessor extends ProcessorBase {
 
 
                                                                                                                 try {
-                                                                                                                    final Invoice invoice = invoiceApi.getInvoiceById(invoiceId, context);
-
-                                                                                                                    if (invoice.isMigrationInvoice()) {
+                                                                                                                    final Invoice invoice = rebalanceAndGetInvoice(account.getId(), invoiceId, context);
+                                                                                                                    if (invoice == null || invoice.isMigrationInvoice()) {
                                                                                                                         log.error("Received invoice for payment that is a migration invoice - don't know how to handle those yet: {}", invoice);
                                                                                                                         return null;
                                                                                                                     }
@@ -388,8 +385,8 @@ public class PaymentProcessor extends ProcessorBase {
                                                                                                            return null;
                                                                                                        }
 
-                                                                                                       final Invoice invoice = invoiceApi.getInvoiceById(payment.getInvoiceId(), context);
-                                                                                                       if (invoice.isMigrationInvoice()) {
+                                                                                                       final Invoice invoice = rebalanceAndGetInvoice(payment.getAccountId(), payment.getInvoiceId(), context);
+                                                                                                       if (invoice == null || invoice.isMigrationInvoice()) {
                                                                                                            return null;
                                                                                                        }
                                                                                                        if (invoice.getBalance().compareTo(BigDecimal.ZERO) <= 0) {
diff --git a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
index e3366aa..f6f23c3 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
@@ -30,6 +30,8 @@ import com.ning.billing.ErrorCode;
 import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.payment.api.PaymentApiException;
 import com.ning.billing.payment.dao.PaymentDao;
@@ -44,6 +46,7 @@ import com.ning.billing.util.globallocker.GlobalLocker;
 import com.ning.billing.util.globallocker.GlobalLocker.LockerType;
 import com.ning.billing.util.globallocker.LockFailedException;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 import com.ning.billing.util.svcapi.tag.TagInternalApi;
 import com.ning.billing.util.svcsapi.bus.InternalBus;
 import com.ning.billing.util.svcsapi.bus.InternalBus.EventBusException;
@@ -66,6 +69,7 @@ public abstract class ProcessorBase {
     protected final TagInternalApi tagInternalApi;
 
     private static final Logger log = LoggerFactory.getLogger(ProcessorBase.class);
+    protected final InvoiceInternalApi invoiceApi;
 
     public ProcessorBase(final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
                          final AccountInternalApi accountInternalApi,
@@ -73,7 +77,7 @@ public abstract class ProcessorBase {
                          final PaymentDao paymentDao,
                          final TagInternalApi tagInternalApi,
                          final GlobalLocker locker,
-                         final ExecutorService executor) {
+                         final ExecutorService executor, final InvoiceInternalApi invoiceApi) {
         this.pluginRegistry = pluginRegistry;
         this.accountInternalApi = accountInternalApi;
         this.eventBus = eventBus;
@@ -81,6 +85,7 @@ public abstract class ProcessorBase {
         this.locker = locker;
         this.executor = executor;
         this.tagInternalApi = tagInternalApi;
+        this.invoiceApi = invoiceApi;
     }
 
     protected boolean isAccountAutoPayOff(final UUID accountId, final InternalTenantContext context) {
@@ -143,6 +148,12 @@ public abstract class ProcessorBase {
         }
     }
 
+    protected Invoice rebalanceAndGetInvoice(final UUID accountId, final UUID invoiceId, final InternalCallContext context) throws InvoiceApiException {
+        invoiceApi.consumeExistingCBAOnAccountWithUnpaidInvoices(accountId, context);
+        final Invoice invoice = invoiceApi.getInvoiceById(invoiceId, context);
+        return invoice;
+    }
+
     public interface WithAccountLockCallback<T> {
 
         public T doOperation() throws PaymentApiException;
diff --git a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
index 5a515d4..e76087d 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
@@ -73,7 +73,6 @@ public class RefundProcessor extends ProcessorBase {
 
     private static final Logger log = LoggerFactory.getLogger(RefundProcessor.class);
 
-    private final InvoiceInternalApi invoiceApi;
     private final InternalCallContextFactory internalCallContextFactory;
 
     @Inject
@@ -86,8 +85,7 @@ public class RefundProcessor extends ProcessorBase {
                            final PaymentDao paymentDao,
                            final GlobalLocker locker,
                            @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
-        super(pluginRegistry, accountApi, eventBus, paymentDao, tagUserApi, locker, executor);
-        this.invoiceApi = invoiceApi;
+        super(pluginRegistry, accountApi, eventBus, paymentDao, tagUserApi, locker, executor, invoiceApi);
         this.internalCallContextFactory = internalCallContextFactory;
     }
 
diff --git a/util/src/main/java/com/ning/billing/util/svcapi/invoice/InvoiceInternalApi.java b/util/src/main/java/com/ning/billing/util/svcapi/invoice/InvoiceInternalApi.java
index ffcfaef..2e6095d 100644
--- a/util/src/main/java/com/ning/billing/util/svcapi/invoice/InvoiceInternalApi.java
+++ b/util/src/main/java/com/ning/billing/util/svcapi/invoice/InvoiceInternalApi.java
@@ -65,4 +65,12 @@ public interface InvoiceInternalApi {
     public InvoicePayment createRefund(UUID paymentId, BigDecimal amount, boolean isInvoiceAdjusted, final Map<UUID, BigDecimal> invoiceItemIdsWithAmounts,
                                        UUID paymentCookieId, InternalCallContext context) throws InvoiceApiException;
 
+    /**
+     * Rebalance CBA for account which have credit and unpaid invoices
+     *
+     * @param accountId account id
+     * @param context the callcontext
+     */
+    public void consumeExistingCBAOnAccountWithUnpaidInvoices(final UUID accountId, final InternalCallContext context) throws InvoiceApiException;
+
 }